Skip to content

Commit d119ff8

Browse files
committed
feat(ssr): Implement server-side rendering for initial table
Implements a hybrid rendering model for the resistance table to improve performance and SEO. - The main plugin now processes all data at build time and injects it via Docusaurus's global data mechanism. - The <ResistanceTable> component is now pre-rendered with this initial data (SSR), embedding the table directly into the static HTML. - Client-side interactivity (changing data sources) is preserved, fetching new data dynamically (CSR). - Added build-time warnings in the remark plugin to notify authors of invalid configurations or empty tables. - Fixed a client-side hydration issue that prevented the adaptive layout from working correctly on the initial load. - Updated the README with a new section explaining the rendering architecture.
1 parent f16e27d commit d119ff8

File tree

7 files changed

+1715
-71
lines changed

7 files changed

+1715
-71
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,4 @@ example/data/eucast_expected_resistance.csv
4343
example/data/organism_classes.csv
4444
example/data/organisms.csv
4545
example/data/resistance_ars_2023_germany_all.csv
46-
example/data/resistance_ars_2023_germany_icu.csv
46+
example/data/resistance_ars_2023_germany_icu.csvexample/data/

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,23 @@ These files allow you to group antibiotics and organisms. The `organism_classes.
198198

199199
UI text is stored in `src/theme/ResistanceTable/i18n.ts`. You can edit this file to add support for new languages or change existing translations. The plugin uses the current Docusaurus locale and falls back to English if a translation is missing.
200200

201+
## For Developers: Rendering Architecture
202+
203+
The plugin employs a hybrid rendering strategy, leveraging both server-side rendering (SSR) at build time and client-side rendering (CSR) for interactivity.
204+
205+
### Build Time (SSR)
206+
207+
During the `docusaurus build` process, the plugin reads and processes all CSV data. It then transforms any `%%RESIST%%` directives in your Markdown files into a fully-formed `<ResistanceTable>` React component. This component is pre-rendered with its initial data, embedding the complete HTML table directly into the static page. This ensures fast initial page loads and makes the table content available to search engine crawlers.
208+
209+
### In the Browser (CSR & Interactivity)
210+
211+
When a user visits the page, the pre-rendered table is instantly visible. React then "hydrates" the component, making it interactive. At this stage, two key client-side features activate:
212+
213+
- **Adaptive Layout:** The component measures the available container width and automatically adjusts its display mode (e.g., by abbreviating names) to best fit the user's screen.
214+
- **Dynamic Data Loading:** If the user selects a new data source from the dropdown, the component fetches the corresponding data from the server and updates the table in place, without needing a page refresh.
215+
216+
This hybrid model provides the fast initial load times and SEO benefits of a static site, combined with the dynamic and responsive experience of a modern web application.
217+
201218
## License
202219

203220
This project is licensed under the MIT License.

dist/index.mjs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2173,8 +2173,12 @@ function docusaurusPluginResistogram(ctx, opts = {}) {
21732173
async contentLoaded({ actions }) {
21742174
const { abx, org, sources, hierarchicalSources, allAbxIds, allOrgIds, orgClasses, orgIdToRank, abxSyn2Id, orgSyn2Id } = await getSharedData(dataPath, files);
21752175
const resistanceDataFileNames = /* @__PURE__ */ new Map();
2176+
const allResistanceData = {};
21762177
for (const source of sources) {
21772178
const resistanceData = await loadResistanceDataForSource(source, sources, dataPath);
2179+
if (resistanceData.length > 0) {
2180+
allResistanceData[source.id] = resistanceData;
2181+
}
21782182
if (resistanceData.length === 0) continue;
21792183
const headers = Object.keys(resistanceData[0] || {});
21802184
const compressedData = [
@@ -2223,10 +2227,13 @@ function docusaurusPluginResistogram(ctx, opts = {}) {
22232227
const dataUrl = isDev ? join(ctx.baseUrl, "resistogram-data", pluginId) : join(ctx.baseUrl, "assets/json");
22242228
const globalData = {
22252229
sources: hierarchicalSources,
2226-
// Pass the tree structure to the client
22272230
resistanceDataFileNames: Object.fromEntries(resistanceDataFileNames),
22282231
sharedDataFileName,
2229-
dataUrl
2232+
dataUrl,
2233+
ssr: {
2234+
sharedData,
2235+
resistanceData: allResistanceData
2236+
}
22302237
};
22312238
actions.setGlobalData(globalData);
22322239
},

0 commit comments

Comments
 (0)