@modern-js/app-tools 3.6.0 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/modern-bundle-docs.js +7 -0
- package/dist/cjs/builder/generator/createBuilderProviderConfig.js +5 -1
- package/dist/cjs/bundleDocs.js +114 -0
- package/dist/cjs/commands/build.js +2 -1
- package/dist/cjs/commands/deploy.js +4 -2
- package/dist/cjs/commands/index.js +0 -4
- package/dist/cjs/config/default.js +2 -0
- package/dist/cjs/index.js +52 -14
- package/dist/cjs/plugins/analyze/index.js +2 -2
- package/dist/cjs/plugins/analyze/utils.js +3 -2
- package/dist/cjs/plugins/initialize/index.js +4 -3
- package/dist/cjs/plugins/serverBuild.js +3 -2
- package/dist/esm/builder/generator/createBuilderProviderConfig.mjs +5 -1
- package/dist/esm/bundleDocs.mjs +62 -0
- package/dist/esm/commands/build.mjs +2 -1
- package/dist/esm/commands/deploy.mjs +4 -2
- package/dist/esm/commands/index.mjs +0 -4
- package/dist/esm/config/default.mjs +2 -0
- package/dist/esm/index.mjs +15 -1
- package/dist/esm/plugins/analyze/index.mjs +2 -2
- package/dist/esm/plugins/analyze/utils.mjs +3 -2
- package/dist/esm/plugins/initialize/index.mjs +4 -3
- package/dist/esm/plugins/serverBuild.mjs +3 -2
- package/dist/esm-node/builder/generator/createBuilderProviderConfig.mjs +5 -1
- package/dist/esm-node/bundleDocs.mjs +63 -0
- package/dist/esm-node/commands/build.mjs +2 -1
- package/dist/esm-node/commands/deploy.mjs +4 -2
- package/dist/esm-node/commands/index.mjs +0 -4
- package/dist/esm-node/config/default.mjs +2 -0
- package/dist/esm-node/index.mjs +15 -1
- package/dist/esm-node/plugins/analyze/index.mjs +2 -2
- package/dist/esm-node/plugins/analyze/utils.mjs +3 -2
- package/dist/esm-node/plugins/initialize/index.mjs +4 -3
- package/dist/esm-node/plugins/serverBuild.mjs +3 -2
- package/dist/types/bundleDocs.d.ts +20 -0
- package/dist/types/commands/deploy.d.ts +2 -1
- package/dist/types/index.d.ts +4 -1
- package/dist/types/plugins/analyze/utils.d.ts +1 -1
- package/dist/types/types/config/dev.d.ts +6 -0
- package/docs/apis/app/commands.md +241 -0
- package/docs/apis/app/hooks/api/lambda.md +9 -0
- package/docs/apis/app/hooks/config/favicon.md +24 -0
- package/docs/apis/app/hooks/config/html.md +5 -0
- package/docs/apis/app/hooks/config/icon.md +24 -0
- package/docs/apis/app/hooks/config/mock.md +6 -0
- package/docs/apis/app/hooks/config/public.md +26 -0
- package/docs/apis/app/hooks/config/upload.md +50 -0
- package/docs/apis/app/hooks/modern-config.md +5 -0
- package/docs/apis/app/hooks/server/server.md +5 -0
- package/docs/apis/app/hooks/shared.md +3 -0
- package/docs/apis/app/hooks/src/app.md +30 -0
- package/docs/apis/app/hooks/src/entry.md +34 -0
- package/docs/apis/app/hooks/src/entry.server.md +51 -0
- package/docs/apis/app/hooks/src/modern.runtime.md +5 -0
- package/docs/apis/app/hooks/src/routes.md +86 -0
- package/docs/apis/app/hooks/src/server.md +3 -0
- package/docs/apis/app/runtime/bff/use-hono-context.md +27 -0
- package/docs/apis/app/runtime/core/create-root.md +19 -0
- package/docs/apis/app/runtime/core/render.md +39 -0
- package/docs/apis/app/runtime/core/runtime-context.md +156 -0
- package/docs/apis/app/runtime/router/router.md +280 -0
- package/docs/apis/app/runtime/ssr/no-ssr.md +35 -0
- package/docs/apis/app/runtime/ssr/renderStreaming.md +67 -0
- package/docs/apis/app/runtime/ssr/renderString.md +60 -0
- package/docs/apis/app/runtime/ssr/requestHandler.md +44 -0
- package/docs/apis/app/runtime/utility/css-in-js.md +40 -0
- package/docs/apis/app/runtime/utility/head.md +35 -0
- package/docs/apis/app/runtime/utility/loadable.md +82 -0
- package/docs/community/blog/2022-0708-updates.md +91 -0
- package/docs/community/blog/2022-0910-updates.md +76 -0
- package/docs/community/blog/overview.md +63 -0
- package/docs/community/blog/v2-release-note.md +238 -0
- package/docs/community/blog/v3-release-note.md +622 -0
- package/docs/community/contributing-guide.md +253 -0
- package/docs/community/releases.md +27 -0
- package/docs/community/showcase.md +34 -0
- package/docs/community/team.md +14 -0
- package/docs/configure/app/bff/cross-project.md +20 -0
- package/docs/configure/app/bff/prefix.md +29 -0
- package/docs/configure/app/builder-plugins.md +66 -0
- package/docs/configure/app/dev/asset-prefix.md +13 -0
- package/docs/configure/app/dev/before-start-url.md +17 -0
- package/docs/configure/app/dev/client.md +41 -0
- package/docs/configure/app/dev/hmr.md +10 -0
- package/docs/configure/app/dev/host.md +18 -0
- package/docs/configure/app/dev/https.md +77 -0
- package/docs/configure/app/dev/lazy-compilation.md +39 -0
- package/docs/configure/app/dev/live-reload.md +10 -0
- package/docs/configure/app/dev/mock-dir.md +31 -0
- package/docs/configure/app/dev/progress-bar.md +19 -0
- package/docs/configure/app/dev/server.md +124 -0
- package/docs/configure/app/dev/setup-middlewares.md +32 -0
- package/docs/configure/app/dev/start-url.md +48 -0
- package/docs/configure/app/dev/watch-files.md +27 -0
- package/docs/configure/app/dev/write-to-disk.md +10 -0
- package/docs/configure/app/experiments/source-build.md +31 -0
- package/docs/configure/app/html/app-icon.md +28 -0
- package/docs/configure/app/html/crossorigin.md +10 -0
- package/docs/configure/app/html/favicon.md +16 -0
- package/docs/configure/app/html/inject.md +10 -0
- package/docs/configure/app/html/meta.md +24 -0
- package/docs/configure/app/html/mount-id.md +10 -0
- package/docs/configure/app/html/output-structure.md +10 -0
- package/docs/configure/app/html/script-loading.md +10 -0
- package/docs/configure/app/html/tags.md +15 -0
- package/docs/configure/app/html/template-parameters.md +33 -0
- package/docs/configure/app/html/template.md +10 -0
- package/docs/configure/app/html/title.md +18 -0
- package/docs/configure/app/output/asset-prefix.md +11 -0
- package/docs/configure/app/output/assets-retry.md +77 -0
- package/docs/configure/app/output/charset.md +10 -0
- package/docs/configure/app/output/clean-dist-path.md +16 -0
- package/docs/configure/app/output/convert-to-rem.md +79 -0
- package/docs/configure/app/output/copy.md +10 -0
- package/docs/configure/app/output/css-modules.md +48 -0
- package/docs/configure/app/output/data-uri-limit.md +26 -0
- package/docs/configure/app/output/disable-css-module-extension.md +55 -0
- package/docs/configure/app/output/disable-inline-runtime-chunk.md +41 -0
- package/docs/configure/app/output/disable-svgr.md +16 -0
- package/docs/configure/app/output/disable-ts-checker.md +49 -0
- package/docs/configure/app/output/dist-path.md +43 -0
- package/docs/configure/app/output/enable-asset-manifest.md +36 -0
- package/docs/configure/app/output/enable-css-module-tsdeclaration.md +28 -0
- package/docs/configure/app/output/enable-inline-route-manifests.md +16 -0
- package/docs/configure/app/output/externals.md +20 -0
- package/docs/configure/app/output/filename-hash.md +10 -0
- package/docs/configure/app/output/filename.md +55 -0
- package/docs/configure/app/output/inject-styles.md +10 -0
- package/docs/configure/app/output/inline-scripts.md +29 -0
- package/docs/configure/app/output/inline-styles.md +29 -0
- package/docs/configure/app/output/legal-comments.md +18 -0
- package/docs/configure/app/output/minify.md +22 -0
- package/docs/configure/app/output/override-browserslist.md +22 -0
- package/docs/configure/app/output/polyfill.md +12 -0
- package/docs/configure/app/output/source-map.md +30 -0
- package/docs/configure/app/output/split-route-chunks.md +16 -0
- package/docs/configure/app/output/ssg.md +81 -0
- package/docs/configure/app/output/ssgByEntries.md +90 -0
- package/docs/configure/app/output/svg-default-export.md +30 -0
- package/docs/configure/app/output/temp-dir.md +20 -0
- package/docs/configure/app/performance/build-cache.md +39 -0
- package/docs/configure/app/performance/chunk-split.md +40 -0
- package/docs/configure/app/performance/dns-prefetch.md +15 -0
- package/docs/configure/app/performance/preconnect.md +16 -0
- package/docs/configure/app/performance/prefetch.md +21 -0
- package/docs/configure/app/performance/preload.md +23 -0
- package/docs/configure/app/performance/print-file-size.md +40 -0
- package/docs/configure/app/performance/profile.md +10 -0
- package/docs/configure/app/performance/remove-console.md +10 -0
- package/docs/configure/app/performance/remove-moment-locale.md +10 -0
- package/docs/configure/app/plugins.md +59 -0
- package/docs/configure/app/resolve/alias-strategy.md +10 -0
- package/docs/configure/app/resolve/alias.md +9 -0
- package/docs/configure/app/resolve/condition-names.md +13 -0
- package/docs/configure/app/resolve/dedupe.md +9 -0
- package/docs/configure/app/resolve/extensions.md +13 -0
- package/docs/configure/app/runtime/0-intro.md +58 -0
- package/docs/configure/app/runtime/plugins.md +58 -0
- package/docs/configure/app/runtime/router.md +35 -0
- package/docs/configure/app/security/check-syntax.md +69 -0
- package/docs/configure/app/security/nonce.md +15 -0
- package/docs/configure/app/security/sri.md +20 -0
- package/docs/configure/app/server/base-url.md +26 -0
- package/docs/configure/app/server/port.md +18 -0
- package/docs/configure/app/server/public-routes.md +22 -0
- package/docs/configure/app/server/routes.md +86 -0
- package/docs/configure/app/server/rsc.md +26 -0
- package/docs/configure/app/server/ssr-by-entries.md +25 -0
- package/docs/configure/app/server/ssr.md +78 -0
- package/docs/configure/app/server/tsconfig-path.md +59 -0
- package/docs/configure/app/source/alias-strategy.md +14 -0
- package/docs/configure/app/source/alias.md +23 -0
- package/docs/configure/app/source/config-dir.md +20 -0
- package/docs/configure/app/source/decorators.md +25 -0
- package/docs/configure/app/source/define.md +16 -0
- package/docs/configure/app/source/disable-default-entries.md +28 -0
- package/docs/configure/app/source/enable-async-entry.md +54 -0
- package/docs/configure/app/source/enable-async-pre-entry.md +26 -0
- package/docs/configure/app/source/entries-dir.md +35 -0
- package/docs/configure/app/source/entries.md +179 -0
- package/docs/configure/app/source/exclude.md +10 -0
- package/docs/configure/app/source/global-vars.md +106 -0
- package/docs/configure/app/source/include.md +36 -0
- package/docs/configure/app/source/main-entry-name.md +24 -0
- package/docs/configure/app/source/pre-entry.md +10 -0
- package/docs/configure/app/source/react-compiler.md +68 -0
- package/docs/configure/app/source/transform-import.md +27 -0
- package/docs/configure/app/split-chunks.md +17 -0
- package/docs/configure/app/tools/autoprefixer.md +44 -0
- package/docs/configure/app/tools/bundler-chain.md +26 -0
- package/docs/configure/app/tools/css-extract.md +33 -0
- package/docs/configure/app/tools/css-loader.md +17 -0
- package/docs/configure/app/tools/dev-server.md +113 -0
- package/docs/configure/app/tools/html-plugin.md +41 -0
- package/docs/configure/app/tools/less.md +81 -0
- package/docs/configure/app/tools/lightningcss-loader.md +35 -0
- package/docs/configure/app/tools/minify-css.md +53 -0
- package/docs/configure/app/tools/postcss.md +34 -0
- package/docs/configure/app/tools/rspack.md +10 -0
- package/docs/configure/app/tools/sass.md +78 -0
- package/docs/configure/app/tools/style-loader.md +10 -0
- package/docs/configure/app/tools/swc.md +65 -0
- package/docs/configure/app/tools/ts-checker.md +109 -0
- package/docs/configure/app/usage.md +276 -0
- package/docs/guides/advanced-features/bff/cross-project.md +109 -0
- package/docs/guides/advanced-features/bff/extend-server.md +120 -0
- package/docs/guides/advanced-features/bff/frameworks.md +124 -0
- package/docs/guides/advanced-features/bff/function.md +314 -0
- package/docs/guides/advanced-features/bff/operators.md +554 -0
- package/docs/guides/advanced-features/bff/sdk.md +116 -0
- package/docs/guides/advanced-features/bff/upload.md +101 -0
- package/docs/guides/advanced-features/bff.md +18 -0
- package/docs/guides/advanced-features/build-performance.md +130 -0
- package/docs/guides/advanced-features/compatibility.md +120 -0
- package/docs/guides/advanced-features/international/advanced.md +128 -0
- package/docs/guides/advanced-features/international/api.md +231 -0
- package/docs/guides/advanced-features/international/best-practices.md +286 -0
- package/docs/guides/advanced-features/international/configuration.md +227 -0
- package/docs/guides/advanced-features/international/locale-detection.md +126 -0
- package/docs/guides/advanced-features/international/quick-start.md +128 -0
- package/docs/guides/advanced-features/international/resource-loading.md +154 -0
- package/docs/guides/advanced-features/international/routing.md +130 -0
- package/docs/guides/advanced-features/international.md +27 -0
- package/docs/guides/advanced-features/low-level.md +46 -0
- package/docs/guides/advanced-features/page-performance/code-split.md +77 -0
- package/docs/guides/advanced-features/page-performance/inline-assets.md +159 -0
- package/docs/guides/advanced-features/page-performance/optimize-bundle.md +97 -0
- package/docs/guides/advanced-features/page-performance/react-compiler.md +69 -0
- package/docs/guides/advanced-features/server-monitor/logger.md +41 -0
- package/docs/guides/advanced-features/server-monitor/metrics.md +58 -0
- package/docs/guides/advanced-features/server-monitor/monitors.md +242 -0
- package/docs/guides/advanced-features/source-build.md +164 -0
- package/docs/guides/advanced-features/web-server.md +288 -0
- package/docs/guides/basic-features/alias.md +102 -0
- package/docs/guides/basic-features/css/css-in-js.md +72 -0
- package/docs/guides/basic-features/css/css-modules.md +212 -0
- package/docs/guides/basic-features/css/css.md +27 -0
- package/docs/guides/basic-features/css/tailwindcss.md +27 -0
- package/docs/guides/basic-features/data/data-cache.md +510 -0
- package/docs/guides/basic-features/data/data-fetch.md +415 -0
- package/docs/guides/basic-features/data/data-write.md +227 -0
- package/docs/guides/basic-features/debug/mock.md +109 -0
- package/docs/guides/basic-features/debug/proxy.md +21 -0
- package/docs/guides/basic-features/debug/rsdoctor.md +62 -0
- package/docs/guides/basic-features/debug/using-storybook.md +112 -0
- package/docs/guides/basic-features/deploy.md +458 -0
- package/docs/guides/basic-features/env-vars.md +177 -0
- package/docs/guides/basic-features/html.md +255 -0
- package/docs/guides/basic-features/output-files.md +141 -0
- package/docs/guides/basic-features/render/before-render.md +108 -0
- package/docs/guides/basic-features/render/overview.md +47 -0
- package/docs/guides/basic-features/render/rsc.md +525 -0
- package/docs/guides/basic-features/render/ssg.md +228 -0
- package/docs/guides/basic-features/render/ssr-cache.md +201 -0
- package/docs/guides/basic-features/render/ssr.md +321 -0
- package/docs/guides/basic-features/render/streaming-ssr.md +264 -0
- package/docs/guides/basic-features/routes/config-routes.md +426 -0
- package/docs/guides/basic-features/routes/routes.md +498 -0
- package/docs/guides/basic-features/static-assets/json-files.md +120 -0
- package/docs/guides/basic-features/static-assets/svg-assets.md +168 -0
- package/docs/guides/basic-features/static-assets/wasm-assets.md +62 -0
- package/docs/guides/basic-features/static-assets.md +160 -0
- package/docs/guides/basic-features/testing/playwright.md +120 -0
- package/docs/guides/basic-features/testing/rstest.md +251 -0
- package/docs/guides/concept/builder.md +37 -0
- package/docs/guides/concept/entries.md +319 -0
- package/docs/guides/concept/server.md +35 -0
- package/docs/guides/get-started/ai-coding-agents.md +58 -0
- package/docs/guides/get-started/glossary.md +63 -0
- package/docs/guides/get-started/introduction.md +36 -0
- package/docs/guides/get-started/quick-start.md +236 -0
- package/docs/guides/get-started/tech-stack.md +82 -0
- package/docs/guides/get-started/upgrade.md +123 -0
- package/docs/guides/topic-detail/module-federation/application.md +116 -0
- package/docs/guides/topic-detail/module-federation/deploy.md +104 -0
- package/docs/guides/topic-detail/module-federation/i18n.md +670 -0
- package/docs/guides/topic-detail/module-federation/introduce.md +35 -0
- package/docs/guides/topic-detail/module-federation/ssr.md +118 -0
- package/docs/guides/topic-detail/module-federation/usage.md +219 -0
- package/docs/guides/troubleshooting/builder.md +110 -0
- package/docs/guides/troubleshooting/cli.md +35 -0
- package/docs/guides/troubleshooting/dependencies.md +119 -0
- package/docs/guides/troubleshooting/hmr.md +144 -0
- package/docs/guides/upgrade/config.md +963 -0
- package/docs/guides/upgrade/entry.md +463 -0
- package/docs/guides/upgrade/other.md +183 -0
- package/docs/guides/upgrade/overview.md +33 -0
- package/docs/guides/upgrade/tailwindcss.md +91 -0
- package/docs/guides/upgrade/web-server.md +109 -0
- package/docs/index.md +33 -0
- package/docs/llms.txt +285 -0
- package/docs/plugin/cli-plugins/api.md +573 -0
- package/docs/plugin/cli-plugins/life-cycle.md +2 -0
- package/docs/plugin/introduction.md +152 -0
- package/docs/plugin/official/cli-plugins/plugin-bff.md +5 -0
- package/docs/plugin/official/cli-plugins/plugin-ssg.md +5 -0
- package/docs/plugin/official/cli-plugins/plugin-styled-components.md +5 -0
- package/docs/plugin/official/cli-plugins.md +4 -0
- package/docs/plugin/plugin-system.md +238 -0
- package/docs/plugin/runtime-plugins/api.md +194 -0
- package/docs/plugin/runtime-plugins/life-cycle.md +2 -0
- package/docs/plugin/server-plugins/api.md +209 -0
- package/docs/plugin/server-plugins/life-cycle.md +13 -0
- package/docs/tutorials/examples/csr-auth.md +9 -0
- package/docs/tutorials/foundations/introduction.md +16 -0
- package/package.json +48 -15
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# Static Site Generation
|
|
2
|
+
|
|
3
|
+
SSG (Static Site Generation) is a technical solution that generates complete static web pages at build time based on data and templates. This means that in a production environment, pages are pre-rendered with content and can be cached by a CDN. SSG can offer better performance and higher security for pages that do not require dynamic data.
|
|
4
|
+
|
|
5
|
+
## Enabling SSG
|
|
6
|
+
|
|
7
|
+
To enable SSG functionality in a Modern.js project, follow these steps to modify the code:
|
|
8
|
+
|
|
9
|
+
1. Install SSG plugin dependencies
|
|
10
|
+
|
|
11
|
+
If the SSG plugin is not yet installed in your project, install it first:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add @modern-js/plugin-ssg
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
:::tip Version Consistency
|
|
18
|
+
|
|
19
|
+
Make sure the version of `@modern-js/plugin-ssg` matches the version of `@modern-js/app-tools` in your project. All Modern.js official packages are released with a uniform version number, and version mismatches may cause compatibility issues.
|
|
20
|
+
|
|
21
|
+
Check the version of `@modern-js/app-tools` first, then install the same version of `@modern-js/plugin-ssg`:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Check the current version of @modern-js/app-tools
|
|
25
|
+
pnpm list @modern-js/app-tools
|
|
26
|
+
|
|
27
|
+
# Install the same version of @modern-js/plugin-ssg
|
|
28
|
+
pnpm add @modern-js/plugin-ssg@<version>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
:::
|
|
32
|
+
|
|
33
|
+
2. Configure modern.config.ts
|
|
34
|
+
|
|
35
|
+
Import and add the SSG plugin in the `modern.config.ts` file, and configure `output.ssg`:
|
|
36
|
+
|
|
37
|
+
```ts title="modern.config.ts"
|
|
38
|
+
import { defineConfig, appTools } from '@modern-js/app-tools';
|
|
39
|
+
import { ssgPlugin } from '@modern-js/plugin-ssg';
|
|
40
|
+
|
|
41
|
+
export default defineConfig({
|
|
42
|
+
plugins: [appTools(), ssgPlugin()],
|
|
43
|
+
output: {
|
|
44
|
+
ssg: true,
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
:::info Scope of Application
|
|
50
|
+
|
|
51
|
+
- Use `output.ssg` for single-entry apps.
|
|
52
|
+
- Use `output.ssgByEntries` for multi-entry apps.
|
|
53
|
+
- When only `output.ssg: true` is set and `output.ssgByEntries` is not configured, all routes under all entries will be treated as SSG routes.
|
|
54
|
+
|
|
55
|
+
:::
|
|
56
|
+
|
|
57
|
+
## Development Debugging
|
|
58
|
+
|
|
59
|
+
Since SSG also renders pages in a Node.js environment, we can enable SSR during the **development phase** to expose code issues early and validate the SSG rendering effect:
|
|
60
|
+
|
|
61
|
+
```ts title="modern.config.ts"
|
|
62
|
+
export default defineConfig({
|
|
63
|
+
server: {
|
|
64
|
+
ssr: process.env.NODE_ENV === 'development',
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Using SSG in Conventional Routing
|
|
70
|
+
|
|
71
|
+
In **conventional routing**, Modern.js generates routes based on the file structure under the entry point, allowing the framework to collect complete route information.
|
|
72
|
+
|
|
73
|
+
### Basic Usage
|
|
74
|
+
|
|
75
|
+
For example, the following is a project directory structure using conventional routing:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
.
|
|
79
|
+
└── routes
|
|
80
|
+
├── layout.tsx
|
|
81
|
+
├── page.tsx
|
|
82
|
+
└── user
|
|
83
|
+
├── layout.tsx
|
|
84
|
+
├── page.tsx
|
|
85
|
+
└── profile
|
|
86
|
+
└── page.tsx
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The above file directory will generate the following three routes:
|
|
90
|
+
|
|
91
|
+
- `/`
|
|
92
|
+
- `/user`
|
|
93
|
+
- `/user/profile`
|
|
94
|
+
|
|
95
|
+
:::tip
|
|
96
|
+
If you are not familiar with the rules of conventional routing, refer to the [Routing Solution](/guides/basic-features/routes/routes.md) first.
|
|
97
|
+
|
|
98
|
+
:::
|
|
99
|
+
|
|
100
|
+
Add component code in `src/routes/page.tsx`:
|
|
101
|
+
|
|
102
|
+
```jsx title="src/routes/page.tsx"
|
|
103
|
+
export default () => {
|
|
104
|
+
return <div>Index Page</div>;
|
|
105
|
+
};
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Run the command `pnpm run dev` at the project root and check the `dist/` directory, where only one HTML file `main/index.html` is generated.
|
|
109
|
+
|
|
110
|
+
Run the command `pnpm run build` at the project root, and after the build completes, check the `dist/` directory again. This time, you'll find `main/index.html`, `main/user/index.html`, and `main/user/profile/index.html` files, each corresponding to the routes listed above.
|
|
111
|
+
|
|
112
|
+
Each route in **conventional routing** will generate a separate HTML file. Checking `main/index.html`, you will find it contains the text `Index Page`, which demonstrates the effect of SSG.
|
|
113
|
+
|
|
114
|
+
After running `pnpm run serve` to start the project, inspect the returned document in the Network tab of the browser's development tools. The document includes the fully rendered content from the component.
|
|
115
|
+
|
|
116
|
+
## Using SSG in Manual Routing
|
|
117
|
+
|
|
118
|
+
**Manual routing** defines routes through component code, requiring the application to run to obtain accurate route information. Therefore, you cannot use the SSG feature out of the box. Developers need to configure which routes require SSG.
|
|
119
|
+
|
|
120
|
+
For example, consider the following code with multiple routes. By setting `output.ssg` to `true`, it will only render the entry route (`/`) by default.
|
|
121
|
+
|
|
122
|
+
```tsx title="src/App.tsx"
|
|
123
|
+
import { BrowserRouter, Route, Routes } from '@modern-js/runtime/router';
|
|
124
|
+
import { StaticRouter } from '@modern-js/runtime/router/server';
|
|
125
|
+
import { use } from 'react';
|
|
126
|
+
import { RuntimeContext } from '@modern-js/runtime';
|
|
127
|
+
|
|
128
|
+
const Router = typeof window === 'undefined' ? StaticRouter : BrowserRouter;
|
|
129
|
+
|
|
130
|
+
export default () => {
|
|
131
|
+
const context = use(RuntimeContext);
|
|
132
|
+
const pathname = context?.request?.pathname;
|
|
133
|
+
return (
|
|
134
|
+
<Router location={pathname}>
|
|
135
|
+
<Routes>
|
|
136
|
+
<Route index element={<div>index</div>} />
|
|
137
|
+
<Route path="about" element={<div>about</div>} />
|
|
138
|
+
</Routes>
|
|
139
|
+
</Router>
|
|
140
|
+
);
|
|
141
|
+
};
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
If you want to enable SSG for `/about` as well, you can configure `output.ssg`:
|
|
145
|
+
|
|
146
|
+
```ts title="modern.config.ts"
|
|
147
|
+
export default defineConfig({
|
|
148
|
+
output: {
|
|
149
|
+
ssg: {
|
|
150
|
+
routes: ['/', '/about'],
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
After running `pnpm run build`, you will see a new `main/about/index.html` file in the `dist/` directory.
|
|
157
|
+
|
|
158
|
+
After running `pnpm run serve` to start the project, inspect the returned document in the Network tab of the browser's development tools. The document includes the fully rendered content from the component.
|
|
159
|
+
|
|
160
|
+
:::info
|
|
161
|
+
The above example introduces single-entry scenarios. For more information, refer to the [API Documentation](/configure/app/output/ssg.md).
|
|
162
|
+
:::
|
|
163
|
+
|
|
164
|
+
## Adding Dynamic Routes
|
|
165
|
+
|
|
166
|
+
In manual routing or conventional routing with dynamic segments (e.g., `/user/[id]`), provide concrete paths directly in `routes`.
|
|
167
|
+
|
|
168
|
+
```js
|
|
169
|
+
export default defineConfig({
|
|
170
|
+
output: {
|
|
171
|
+
ssg: {
|
|
172
|
+
routes: ['/', '/about', '/user/modernjs'],
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Multi-entry
|
|
179
|
+
|
|
180
|
+
For multi-entry apps, configure per entry via `output.ssgByEntries`:
|
|
181
|
+
|
|
182
|
+
```js
|
|
183
|
+
export default defineConfig({
|
|
184
|
+
output: {
|
|
185
|
+
ssgByEntries: {
|
|
186
|
+
home: {
|
|
187
|
+
routes: ['/', '/about', '/user/modernjs'],
|
|
188
|
+
},
|
|
189
|
+
admin: false,
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
:::info
|
|
196
|
+
See API details: [output.ssgByEntries](/configure/app/output/ssgByEntries.md)
|
|
197
|
+
:::
|
|
198
|
+
|
|
199
|
+
## Configuring Request Headers for Rendering
|
|
200
|
+
|
|
201
|
+
Modern.js supports configuring request headers for specific entries or routes. For example:
|
|
202
|
+
|
|
203
|
+
```js
|
|
204
|
+
export default defineConfig({
|
|
205
|
+
output: {
|
|
206
|
+
ssg: {
|
|
207
|
+
headers: {
|
|
208
|
+
'x-tt-env': 'ppe_modernjs',
|
|
209
|
+
},
|
|
210
|
+
routes: [
|
|
211
|
+
'/',
|
|
212
|
+
{
|
|
213
|
+
url: '/about',
|
|
214
|
+
headers: {
|
|
215
|
+
from: 'modern-website',
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
In the above configuration, the `x-tt-env` request header is set for all routes, and the `from` request header is specifically set for the `/about` route.
|
|
225
|
+
|
|
226
|
+
:::tip
|
|
227
|
+
Headers set in routes will override headers set for entries.
|
|
228
|
+
:::
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# Rendering Cache
|
|
2
|
+
|
|
3
|
+
When developing applications, sometimes we cache computation results using hooks like React's `useMemo` and `useCallback`. By leveraging caching, we can reduce the number of computations, thus saving CPU resources and improving user experience.
|
|
4
|
+
|
|
5
|
+
Modern.js supports caching server-side rendering (SSR) results, reducing the computational and rendering time during subsequent requests. This accelerates page load time and improves user experience. Additionally, caching lowers server load, conserves computational resources, and speeds up user access.
|
|
6
|
+
|
|
7
|
+
## Configuration
|
|
8
|
+
|
|
9
|
+
Create a `server/cache.[t|j]s` file in your application and export the `cacheOption` configuration to enable SSR rendering cache:
|
|
10
|
+
|
|
11
|
+
```ts title="server/cache.ts"
|
|
12
|
+
import type { CacheOption } from '@modern-js/server-runtime';
|
|
13
|
+
|
|
14
|
+
export const cacheOption: CacheOption = {
|
|
15
|
+
maxAge: 500, // ms
|
|
16
|
+
staleWhileRevalidate: 1000, // ms
|
|
17
|
+
};
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Configuration Details
|
|
21
|
+
|
|
22
|
+
### Cache Configuration
|
|
23
|
+
|
|
24
|
+
The caching strategy implements [stale-while-revalidate](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control).
|
|
25
|
+
|
|
26
|
+
Within the `maxAge` period, the cache content is directly returned. Exceeding `maxAge` but within `staleWhileRevalidate`, the cache content is still returned directly, but it re-renders asynchronously.
|
|
27
|
+
|
|
28
|
+
**Object Type**
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
export interface CacheControl {
|
|
32
|
+
maxAge: number;
|
|
33
|
+
staleWhileRevalidate: number;
|
|
34
|
+
customKey?: string | ((pathname: string) => string);
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Here, `customKey` is the custom cache key. By default, Modern.js uses the request `pathname` as the cache key, but developers can define it when necessary.
|
|
39
|
+
|
|
40
|
+
**Function Type**
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
export type CacheOptionProvider = (
|
|
44
|
+
req: IncomingMessage,
|
|
45
|
+
) => Promise<CacheControl | false> | CacheControl | false;
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Sometimes, developers need to use `req` to customize the cache key, or prevent caching for specific URLs. You can configure this as a function, as shown:
|
|
49
|
+
|
|
50
|
+
```ts title="server/cache.ts"
|
|
51
|
+
import type { CacheOption, CacheOptionProvider } from '@modern-js/server-runtime';
|
|
52
|
+
|
|
53
|
+
const provider: CacheOptionProvider = (req) => {
|
|
54
|
+
const { url, headers, ... } = req;
|
|
55
|
+
if(url.includes('no-cache=1')) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const key = computedKey(url, headers, ...);
|
|
60
|
+
return {
|
|
61
|
+
maxAge: 500, // ms
|
|
62
|
+
staleWhileRevalidate: 1000, // ms
|
|
63
|
+
customKey: key,
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const cacheOption: CacheOption = provider;
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Mapping Type**
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
export type CacheOptions = Record<string, CacheControl | CacheOptionProvider>;
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Sometimes, different routes require different caching strategies. We also offer a mapping configuration method, as shown below:
|
|
77
|
+
|
|
78
|
+
```ts title="server/cache.ts"
|
|
79
|
+
import type { CacheOption } from '@modern-js/server-runtime';
|
|
80
|
+
|
|
81
|
+
export const cacheOption: CacheOption = {
|
|
82
|
+
'/home': {
|
|
83
|
+
maxAge: 50,
|
|
84
|
+
staleWhileRevalidate: 100,
|
|
85
|
+
},
|
|
86
|
+
'/about': {
|
|
87
|
+
maxAge: 1000 * 60 * 60 * 24, // one day
|
|
88
|
+
staleWhileRevalidate: 1000 * 60 * 60 * 24 * 2 // two days
|
|
89
|
+
},
|
|
90
|
+
'*': (req) => { // If no above route matches, this applies
|
|
91
|
+
const { url, headers, ... } = req;
|
|
92
|
+
const key = computedKey(url, headers, ...);
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
maxAge: 500,
|
|
96
|
+
staleWhileRevalidate: 1000,
|
|
97
|
+
customKey: key,
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
- The route `http://xxx/home` will apply the first rule.
|
|
104
|
+
- The route `http://xxx/about` will apply the second rule.
|
|
105
|
+
- The route `http://xxx/abc` will apply the last rule.
|
|
106
|
+
|
|
107
|
+
The above `/home` and `/about` are patterns, meaning `/home/abc` will also match. You can use regex in these patterns, such as `/home/.+`.
|
|
108
|
+
|
|
109
|
+
### Cache Container
|
|
110
|
+
|
|
111
|
+
By default, the server uses memory for caching. Typically, services are deployed in a Serverless container, creating a new process for each access, making it impossible to use the previous cache.
|
|
112
|
+
|
|
113
|
+
Thus, Modern.js allows developers to define custom cache containers. Containers must implement the `Container` interface:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
export interface Container<K = string, V = string> {
|
|
117
|
+
/**
|
|
118
|
+
* Returns a specified element from the container. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Container.
|
|
119
|
+
* @returns Returns the element associated with the specified key. If no element is associated with the specified key, undefined is returned.
|
|
120
|
+
*/
|
|
121
|
+
get: (key: K) => Promise<V | undefined>;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Adds a new element with a specified key and value to the container. If an element with the same key already exists, the element will be updated.
|
|
125
|
+
*
|
|
126
|
+
* The ttl indicates cache expiration time.
|
|
127
|
+
*/
|
|
128
|
+
set: (key: K, value: V, options?: { ttl?: number }) => Promise<this>;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* @returns boolean indicating whether an element with the specified key exists or not.
|
|
132
|
+
*/
|
|
133
|
+
has: (key: K) => Promise<boolean>;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* @returns true if an element in the container existed and has been removed, or false if the element does not exist.
|
|
137
|
+
*/
|
|
138
|
+
delete: (key: K) => Promise<boolean>;
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Developers can implement a Redis cache container as shown below:
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
import Redis from 'ioredis';
|
|
146
|
+
import type { Container, CacheOption } from '@modern-js/server-runtime';
|
|
147
|
+
|
|
148
|
+
class RedisContainer implements Container {
|
|
149
|
+
redis = new Redis();
|
|
150
|
+
|
|
151
|
+
async get(key: string) {
|
|
152
|
+
return this.redis.get(key);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
async set(key: string, value: string): Promise<this> {
|
|
156
|
+
this.redis.set(key, value);
|
|
157
|
+
return this;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async has(key: string): Promise<boolean> {
|
|
161
|
+
return this.redis.exists(key) > 0;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async delete(key: string): Promise<boolean> {
|
|
165
|
+
return this.redis.del(key) > 0;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const container = new RedisContainer();
|
|
170
|
+
|
|
171
|
+
export const customContainer: Container = container;
|
|
172
|
+
|
|
173
|
+
export const cacheOption: CacheOption = {
|
|
174
|
+
maxAge: 500, // ms
|
|
175
|
+
staleWhileRevalidate: 1000, // ms
|
|
176
|
+
};
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Cache Identification
|
|
180
|
+
|
|
181
|
+
When rendering cache is enabled, Modern.js identifies the cache status of the current request through the `x-render-cache` response header. Here's an example response:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
< HTTP/1.1 200 OK
|
|
185
|
+
< Access-Control-Allow-Origin: *
|
|
186
|
+
< content-type: text/html; charset=utf-8
|
|
187
|
+
< x-render-cache: hit
|
|
188
|
+
< Date: Thu, 29 Feb 2024 02:46:49 GMT
|
|
189
|
+
< Connection: keep-alive
|
|
190
|
+
< Keep-Alive: timeout=5
|
|
191
|
+
< Content-Length: 2937
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
The `x-render-cache` header can have the following values:
|
|
195
|
+
|
|
196
|
+
| Name | Description |
|
|
197
|
+
| ------- | ----------------------------------------------------------------------------------- |
|
|
198
|
+
| hit | Cache hit, returned cache content |
|
|
199
|
+
| stale | Cache hit, but data is stale, returned cache content and re-rendered asynchronously |
|
|
200
|
+
| expired | Cache expired, re-rendered and returned new content |
|
|
201
|
+
| miss | Cache missed |
|