@bleedingdev/modern-js-app-tools 3.5.0-ultramodern.97 → 3.5.0-ultramodern.99
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/dist/cjs/builder/generator/createBuilderProviderConfig.js +5 -1
- package/dist/cjs/builder/generator/getBuilderEnvironments.js +7 -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 +56 -15
- 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/builder/generator/getBuilderEnvironments.mjs +7 -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/builder/generator/getBuilderEnvironments.mjs +7 -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/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/_nav.json +36 -0
- package/docs/apis/_meta.json +13 -0
- package/docs/apis/app/commands.mdx +205 -0
- package/docs/apis/app/hooks/_meta.json +28 -0
- package/docs/apis/app/hooks/api/lambda.mdx +13 -0
- package/docs/apis/app/hooks/config/_meta.json +1 -0
- package/docs/apis/app/hooks/config/favicon.mdx +29 -0
- package/docs/apis/app/hooks/config/html.mdx +9 -0
- package/docs/apis/app/hooks/config/icon.mdx +29 -0
- package/docs/apis/app/hooks/config/mock.mdx +10 -0
- package/docs/apis/app/hooks/config/public.mdx +30 -0
- package/docs/apis/app/hooks/config/upload.mdx +54 -0
- package/docs/apis/app/hooks/modern-config.mdx +9 -0
- package/docs/apis/app/hooks/server/server.mdx +10 -0
- package/docs/apis/app/hooks/shared.mdx +7 -0
- package/docs/apis/app/hooks/src/app.mdx +30 -0
- package/docs/apis/app/hooks/src/entry.mdx +39 -0
- package/docs/apis/app/hooks/src/entry.server.mdx +56 -0
- package/docs/apis/app/hooks/src/modern.runtime.mdx +9 -0
- package/docs/apis/app/hooks/src/routes.mdx +90 -0
- package/docs/apis/app/hooks/src/server.mdx +7 -0
- package/docs/apis/app/runtime/_meta.json +32 -0
- package/docs/apis/app/runtime/bff/use-backend-context.mdx +30 -0
- package/docs/apis/app/runtime/core/create-root.mdx +22 -0
- package/docs/apis/app/runtime/core/render.mdx +42 -0
- package/docs/apis/app/runtime/core/runtime-context.mdx +160 -0
- package/docs/apis/app/runtime/router/router.mdx +288 -0
- package/docs/apis/app/runtime/ssr/no-ssr.mdx +38 -0
- package/docs/apis/app/runtime/ssr/renderStreaming.mdx +71 -0
- package/docs/apis/app/runtime/ssr/renderString.mdx +64 -0
- package/docs/apis/app/runtime/ssr/requestHandler.mdx +48 -0
- package/docs/apis/app/runtime/utility/css-in-js.mdx +44 -0
- package/docs/apis/app/runtime/utility/head.mdx +38 -0
- package/docs/apis/app/runtime/utility/loadable.mdx +85 -0
- package/docs/components/auto-upgrade.mdx +0 -0
- package/docs/components/bff-upload.mdx +97 -0
- package/docs/components/build-output.mdx +45 -0
- package/docs/components/bundler.mdx +3 -0
- package/docs/components/convention-routing-motivation.mdx +0 -0
- package/docs/components/debug-app.mdx +15 -0
- package/docs/components/default-browserslist.mdx +7 -0
- package/docs/components/deploy-command.mdx +14 -0
- package/docs/components/deploy.mdx +1 -0
- package/docs/components/enable-bff-caution.mdx +3 -0
- package/docs/components/enable-bff.mdx +56 -0
- package/docs/components/enable-ssg.mdx +49 -0
- package/docs/components/entry-mode.mdx +0 -0
- package/docs/components/entry-scan-logic.mdx +7 -0
- package/docs/components/extend-bff-function.mdx +3 -0
- package/docs/components/hono.mdx +120 -0
- package/docs/components/init-app.mdx +93 -0
- package/docs/components/init-rspack-app.mdx +5 -0
- package/docs/components/internal-logger.mdx +25 -0
- package/docs/components/internal-metrics.mdx +20 -0
- package/docs/components/international/custom-instance-code.mdx +16 -0
- package/docs/components/international/init-options-desc.mdx +1 -0
- package/docs/components/international/install-command.mdx +10 -0
- package/docs/components/international/instance-code.mdx +16 -0
- package/docs/components/international/introduce.mdx +5 -0
- package/docs/components/international/platform-support.mdx +0 -0
- package/docs/components/language-config.mdx +9 -0
- package/docs/components/micro-frontend.mdx +6 -0
- package/docs/components/micro-master-manifest-config.mdx +15 -0
- package/docs/components/micro-runtime-config.mdx +17 -0
- package/docs/components/module-federation.mdx +7 -0
- package/docs/components/new-entry-tooltip.mdx +0 -0
- package/docs/components/nodeVersion.mdx +28 -0
- package/docs/components/other-plugins.mdx +0 -0
- package/docs/components/output-asset-prefix-extend.mdx +0 -0
- package/docs/components/output-distpath-warning.mdx +0 -0
- package/docs/components/output-polyfill-extend.mdx +1 -0
- package/docs/components/prerequisites.mdx +18 -0
- package/docs/components/release-note.mdx +1 -0
- package/docs/components/routes-practice.mdx +0 -0
- package/docs/components/rsbuild-config-tooltip.mdx +5 -0
- package/docs/components/rsbuild.mdx +3 -0
- package/docs/components/rsc-deploy-tip.mdx +1 -0
- package/docs/components/rspack.mdx +3 -0
- package/docs/components/rspackTip.mdx +7 -0
- package/docs/components/runtime-cli-config.mdx +0 -0
- package/docs/components/serve-command.mdx +22 -0
- package/docs/components/ssr-monitor.mdx +3 -0
- package/docs/components/stream-ssr-performance.mdx +0 -0
- package/docs/components/swc.mdx +3 -0
- package/docs/components/tech-stack-node-framework.mdx +1 -0
- package/docs/components/turtorials-example-list.mdx +2 -0
- package/docs/components/ua-polyfill.mdx +44 -0
- package/docs/components/upgrade-browserslist.mdx +0 -0
- package/docs/components/upgrade-config-deploy.mdx +0 -0
- package/docs/components/upgrade-faq.mdx +0 -0
- package/docs/configure/_meta.json +78 -0
- package/docs/configure/app/bff/cross-project.mdx +24 -0
- package/docs/configure/app/bff/effect.mdx +319 -0
- package/docs/configure/app/bff/prefix.mdx +33 -0
- package/docs/configure/app/bff/runtime-framework.mdx +30 -0
- package/docs/configure/app/builder-plugins.mdx +70 -0
- package/docs/configure/app/dev/asset-prefix.mdx +18 -0
- package/docs/configure/app/dev/before-start-url.mdx +21 -0
- package/docs/configure/app/dev/client.mdx +45 -0
- package/docs/configure/app/dev/hmr.mdx +14 -0
- package/docs/configure/app/dev/host.mdx +22 -0
- package/docs/configure/app/dev/https.mdx +81 -0
- package/docs/configure/app/dev/lazy-compilation.mdx +45 -0
- package/docs/configure/app/dev/live-reload.mdx +14 -0
- package/docs/configure/app/dev/mock-dir.mdx +35 -0
- package/docs/configure/app/dev/progress-bar.mdx +23 -0
- package/docs/configure/app/dev/server.mdx +128 -0
- package/docs/configure/app/dev/setup-middlewares.mdx +36 -0
- package/docs/configure/app/dev/start-url.mdx +53 -0
- package/docs/configure/app/dev/watch-files.mdx +31 -0
- package/docs/configure/app/dev/write-to-disk.mdx +14 -0
- package/docs/configure/app/experiments/source-build.mdx +33 -0
- package/docs/configure/app/html/app-icon.mdx +32 -0
- package/docs/configure/app/html/crossorigin.mdx +14 -0
- package/docs/configure/app/html/favicon.mdx +20 -0
- package/docs/configure/app/html/inject.mdx +14 -0
- package/docs/configure/app/html/meta.mdx +28 -0
- package/docs/configure/app/html/mount-id.mdx +14 -0
- package/docs/configure/app/html/output-structure.mdx +14 -0
- package/docs/configure/app/html/script-loading.mdx +14 -0
- package/docs/configure/app/html/tags.mdx +19 -0
- package/docs/configure/app/html/template-parameters.mdx +37 -0
- package/docs/configure/app/html/template.mdx +14 -0
- package/docs/configure/app/html/title.mdx +22 -0
- package/docs/configure/app/output/asset-prefix.mdx +18 -0
- package/docs/configure/app/output/assets-retry.mdx +81 -0
- package/docs/configure/app/output/charset.mdx +14 -0
- package/docs/configure/app/output/clean-dist-path.mdx +20 -0
- package/docs/configure/app/output/convert-to-rem.mdx +83 -0
- package/docs/configure/app/output/copy.mdx +14 -0
- package/docs/configure/app/output/css-modules.mdx +52 -0
- package/docs/configure/app/output/data-uri-limit.mdx +30 -0
- package/docs/configure/app/output/disable-css-module-extension.mdx +59 -0
- package/docs/configure/app/output/disable-inline-runtime-chunk.mdx +45 -0
- package/docs/configure/app/output/disable-svgr.mdx +22 -0
- package/docs/configure/app/output/disable-ts-checker.mdx +53 -0
- package/docs/configure/app/output/dist-path.mdx +51 -0
- package/docs/configure/app/output/enable-asset-manifest.mdx +40 -0
- package/docs/configure/app/output/enable-css-module-tsdeclaration.mdx +32 -0
- package/docs/configure/app/output/enable-inline-route-manifests.mdx +20 -0
- package/docs/configure/app/output/externals.mdx +24 -0
- package/docs/configure/app/output/filename-hash.mdx +14 -0
- package/docs/configure/app/output/filename.mdx +59 -0
- package/docs/configure/app/output/inject-styles.mdx +14 -0
- package/docs/configure/app/output/inline-scripts.mdx +33 -0
- package/docs/configure/app/output/inline-styles.mdx +33 -0
- package/docs/configure/app/output/legal-comments.mdx +22 -0
- package/docs/configure/app/output/minify.mdx +26 -0
- package/docs/configure/app/output/override-browserslist.mdx +26 -0
- package/docs/configure/app/output/polyfill.mdx +18 -0
- package/docs/configure/app/output/source-map.mdx +34 -0
- package/docs/configure/app/output/split-route-chunks.mdx +20 -0
- package/docs/configure/app/output/ssg.mdx +85 -0
- package/docs/configure/app/output/ssgByEntries.mdx +93 -0
- package/docs/configure/app/output/svg-default-export.mdx +34 -0
- package/docs/configure/app/output/temp-dir.mdx +24 -0
- package/docs/configure/app/performance/build-cache.mdx +48 -0
- package/docs/configure/app/performance/chunk-split.mdx +44 -0
- package/docs/configure/app/performance/dns-prefetch.mdx +19 -0
- package/docs/configure/app/performance/preconnect.mdx +20 -0
- package/docs/configure/app/performance/prefetch.mdx +25 -0
- package/docs/configure/app/performance/preload.mdx +27 -0
- package/docs/configure/app/performance/print-file-size.mdx +44 -0
- package/docs/configure/app/performance/profile.mdx +14 -0
- package/docs/configure/app/performance/remove-console.mdx +14 -0
- package/docs/configure/app/performance/remove-moment-locale.mdx +14 -0
- package/docs/configure/app/performance/rsdoctor.mdx +42 -0
- package/docs/configure/app/plugins.mdx +59 -0
- package/docs/configure/app/resolve/alias-strategy.mdx +14 -0
- package/docs/configure/app/resolve/alias.mdx +13 -0
- package/docs/configure/app/resolve/condition-names.mdx +18 -0
- package/docs/configure/app/resolve/dedupe.mdx +13 -0
- package/docs/configure/app/resolve/extensions.mdx +18 -0
- package/docs/configure/app/runtime/0-intro.mdx +61 -0
- package/docs/configure/app/runtime/plugins.mdx +58 -0
- package/docs/configure/app/runtime/router.mdx +39 -0
- package/docs/configure/app/security/check-syntax.mdx +73 -0
- package/docs/configure/app/security/nonce.mdx +19 -0
- package/docs/configure/app/security/sri.mdx +24 -0
- package/docs/configure/app/server/base-url.mdx +30 -0
- package/docs/configure/app/server/port.mdx +22 -0
- package/docs/configure/app/server/public-routes.mdx +26 -0
- package/docs/configure/app/server/routes.mdx +90 -0
- package/docs/configure/app/server/rsc.mdx +30 -0
- package/docs/configure/app/server/ssr-by-entries.mdx +29 -0
- package/docs/configure/app/server/ssr.mdx +85 -0
- package/docs/configure/app/server/tsconfig-path.mdx +63 -0
- package/docs/configure/app/source/alias-strategy.mdx +18 -0
- package/docs/configure/app/source/alias.mdx +27 -0
- package/docs/configure/app/source/config-dir.mdx +24 -0
- package/docs/configure/app/source/decorators.mdx +29 -0
- package/docs/configure/app/source/define.mdx +20 -0
- package/docs/configure/app/source/disable-default-entries.mdx +32 -0
- package/docs/configure/app/source/enable-async-entry.mdx +54 -0
- package/docs/configure/app/source/enable-async-pre-entry.mdx +30 -0
- package/docs/configure/app/source/entries-dir.mdx +39 -0
- package/docs/configure/app/source/entries.mdx +183 -0
- package/docs/configure/app/source/exclude.mdx +14 -0
- package/docs/configure/app/source/global-vars.mdx +110 -0
- package/docs/configure/app/source/include.mdx +40 -0
- package/docs/configure/app/source/main-entry-name.mdx +28 -0
- package/docs/configure/app/source/pre-entry.mdx +14 -0
- package/docs/configure/app/source/react-compiler.mdx +72 -0
- package/docs/configure/app/source/transform-import.mdx +31 -0
- package/docs/configure/app/split-chunks.mdx +17 -0
- package/docs/configure/app/tools/autoprefixer.mdx +48 -0
- package/docs/configure/app/tools/bundler-chain.mdx +30 -0
- package/docs/configure/app/tools/css-extract.mdx +37 -0
- package/docs/configure/app/tools/css-loader.mdx +21 -0
- package/docs/configure/app/tools/dev-server.mdx +117 -0
- package/docs/configure/app/tools/html-plugin.mdx +45 -0
- package/docs/configure/app/tools/less.mdx +85 -0
- package/docs/configure/app/tools/lightningcss-loader.mdx +39 -0
- package/docs/configure/app/tools/minify-css.mdx +57 -0
- package/docs/configure/app/tools/postcss.mdx +38 -0
- package/docs/configure/app/tools/rspack.mdx +14 -0
- package/docs/configure/app/tools/sass.mdx +82 -0
- package/docs/configure/app/tools/style-loader.mdx +14 -0
- package/docs/configure/app/tools/swc.mdx +69 -0
- package/docs/configure/app/tools/ts-checker.mdx +103 -0
- package/docs/configure/app/usage.mdx +276 -0
- package/docs/guides/_meta.json +37 -0
- package/docs/guides/advanced-features/_meta.json +32 -0
- package/docs/guides/advanced-features/bff/_meta.json +10 -0
- package/docs/guides/advanced-features/bff/cross-project.mdx +110 -0
- package/docs/guides/advanced-features/bff/data-platform.mdx +120 -0
- package/docs/guides/advanced-features/bff/extend-server.mdx +120 -0
- package/docs/guides/advanced-features/bff/frameworks.mdx +131 -0
- package/docs/guides/advanced-features/bff/function.mdx +265 -0
- package/docs/guides/advanced-features/bff/operators.mdx +629 -0
- package/docs/guides/advanced-features/bff/sdk.mdx +116 -0
- package/docs/guides/advanced-features/bff/upload.mdx +7 -0
- package/docs/guides/advanced-features/bff.mdx +22 -0
- package/docs/guides/advanced-features/build-performance.mdx +134 -0
- package/docs/guides/advanced-features/compatibility.mdx +81 -0
- package/docs/guides/advanced-features/international/_meta.json +10 -0
- package/docs/guides/advanced-features/international/advanced.mdx +132 -0
- package/docs/guides/advanced-features/international/api.mdx +271 -0
- package/docs/guides/advanced-features/international/best-practices.mdx +290 -0
- package/docs/guides/advanced-features/international/configuration.mdx +222 -0
- package/docs/guides/advanced-features/international/locale-detection.mdx +130 -0
- package/docs/guides/advanced-features/international/quick-start.mdx +112 -0
- package/docs/guides/advanced-features/international/resource-loading.mdx +158 -0
- package/docs/guides/advanced-features/international/routing.mdx +177 -0
- package/docs/guides/advanced-features/international.mdx +29 -0
- package/docs/guides/advanced-features/low-level.mdx +50 -0
- package/docs/guides/advanced-features/page-performance/_meta.json +1 -0
- package/docs/guides/advanced-features/page-performance/code-split.mdx +81 -0
- package/docs/guides/advanced-features/page-performance/inline-assets.mdx +163 -0
- package/docs/guides/advanced-features/page-performance/optimize-bundle.mdx +101 -0
- package/docs/guides/advanced-features/page-performance/react-compiler.mdx +51 -0
- package/docs/guides/advanced-features/server-monitor/_meta.json +1 -0
- package/docs/guides/advanced-features/server-monitor/logger.mdx +19 -0
- package/docs/guides/advanced-features/server-monitor/metrics.mdx +41 -0
- package/docs/guides/advanced-features/server-monitor/monitors.mdx +242 -0
- package/docs/guides/advanced-features/source-build.mdx +168 -0
- package/docs/guides/advanced-features/web-server.mdx +296 -0
- package/docs/guides/basic-features/_meta.json +49 -0
- package/docs/guides/basic-features/alias.mdx +106 -0
- package/docs/guides/basic-features/css/_meta.json +1 -0
- package/docs/guides/basic-features/css/css-in-js.mdx +69 -0
- package/docs/guides/basic-features/css/css-modules.mdx +212 -0
- package/docs/guides/basic-features/css/css.mdx +31 -0
- package/docs/guides/basic-features/css/tailwindcss.mdx +27 -0
- package/docs/guides/basic-features/data/_meta.json +1 -0
- package/docs/guides/basic-features/data/data-cache.mdx +515 -0
- package/docs/guides/basic-features/data/data-fetch.mdx +419 -0
- package/docs/guides/basic-features/data/data-write.mdx +230 -0
- package/docs/guides/basic-features/debug/_meta.json +1 -0
- package/docs/guides/basic-features/debug/mock.mdx +113 -0
- package/docs/guides/basic-features/debug/proxy.mdx +25 -0
- package/docs/guides/basic-features/debug/rsdoctor.mdx +47 -0
- package/docs/guides/basic-features/debug/using-storybook.mdx +100 -0
- package/docs/guides/basic-features/deploy.mdx +448 -0
- package/docs/guides/basic-features/env-vars.mdx +181 -0
- package/docs/guides/basic-features/html.mdx +259 -0
- package/docs/guides/basic-features/output-files.mdx +145 -0
- package/docs/guides/basic-features/render/_meta.json +1 -0
- package/docs/guides/basic-features/render/before-render.mdx +108 -0
- package/docs/guides/basic-features/render/overview.mdx +51 -0
- package/docs/guides/basic-features/render/rsc.mdx +533 -0
- package/docs/guides/basic-features/render/ssg.mdx +167 -0
- package/docs/guides/basic-features/render/ssr-cache.mdx +201 -0
- package/docs/guides/basic-features/render/ssr.mdx +323 -0
- package/docs/guides/basic-features/render/streaming-ssr.mdx +267 -0
- package/docs/guides/basic-features/routes/_meta.json +1 -0
- package/docs/guides/basic-features/routes/config-routes.mdx +427 -0
- package/docs/guides/basic-features/routes/routes.mdx +532 -0
- package/docs/guides/basic-features/static-assets/_meta.json +1 -0
- package/docs/guides/basic-features/static-assets/json-files.mdx +124 -0
- package/docs/guides/basic-features/static-assets/svg-assets.mdx +172 -0
- package/docs/guides/basic-features/static-assets/wasm-assets.mdx +66 -0
- package/docs/guides/basic-features/static-assets.mdx +164 -0
- package/docs/guides/basic-features/testing/_meta.json +1 -0
- package/docs/guides/basic-features/testing/playwright.mdx +111 -0
- package/docs/guides/basic-features/testing/rstest.mdx +192 -0
- package/docs/guides/concept/_meta.json +1 -0
- package/docs/guides/concept/builder.mdx +60 -0
- package/docs/guides/concept/entries.mdx +325 -0
- package/docs/guides/concept/server.mdx +35 -0
- package/docs/guides/get-started/_meta.json +9 -0
- package/docs/guides/get-started/ai-coding-agents.mdx +63 -0
- package/docs/guides/get-started/glossary.mdx +63 -0
- package/docs/guides/get-started/introduction.mdx +45 -0
- package/docs/guides/get-started/quick-start.mdx +92 -0
- package/docs/guides/get-started/tech-stack.mdx +97 -0
- package/docs/guides/get-started/ultramodern.mdx +433 -0
- package/docs/guides/get-started/upgrade.mdx +114 -0
- package/docs/guides/topic-detail/_meta.json +8 -0
- package/docs/guides/topic-detail/module-federation/_meta.json +1 -0
- package/docs/guides/topic-detail/module-federation/application.mdx +116 -0
- package/docs/guides/topic-detail/module-federation/deploy.mdx +104 -0
- package/docs/guides/topic-detail/module-federation/i18n.mdx +670 -0
- package/docs/guides/topic-detail/module-federation/introduce.mdx +36 -0
- package/docs/guides/topic-detail/module-federation/ssr.mdx +177 -0
- package/docs/guides/topic-detail/module-federation/usage.mdx +202 -0
- package/docs/guides/troubleshooting/_meta.json +1 -0
- package/docs/guides/troubleshooting/builder.mdx +114 -0
- package/docs/guides/troubleshooting/cli.mdx +39 -0
- package/docs/guides/troubleshooting/dependencies.mdx +123 -0
- package/docs/guides/troubleshooting/hmr.mdx +148 -0
- package/docs/guides/upgrade/_meta.json +1 -0
- package/docs/guides/upgrade/config.mdx +951 -0
- package/docs/guides/upgrade/entry.mdx +463 -0
- package/docs/guides/upgrade/other.mdx +183 -0
- package/docs/guides/upgrade/overview.mdx +33 -0
- package/docs/guides/upgrade/tailwindcss.mdx +92 -0
- package/docs/guides/upgrade/web-server.md +109 -0
- package/docs/index.md +4 -0
- package/package.json +43 -20
- package/scripts/copy-main-doc.mjs +50 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# Streaming Server-Side Rendering
|
|
2
|
+
|
|
3
|
+
Streaming rendering is an advanced rendering method that progressively returns content during the page rendering process, significantly improving user experience.
|
|
4
|
+
|
|
5
|
+
In traditional SSR rendering, the page is rendered all at once, requiring all data to be loaded before returning the complete HTML. In streaming rendering, the page is rendered progressively, allowing content to be returned as it renders, so users can see initial content faster.
|
|
6
|
+
|
|
7
|
+
:::info Default Mode
|
|
8
|
+
**Streaming SSR is the default rendering mode for Modern.js SSR**. When you enable SSR, streaming rendering is available without additional configuration.
|
|
9
|
+
|
|
10
|
+
If you need to switch to traditional SSR mode (waiting for all data to load before returning at once), you can configure `server.ssr.mode` to `'string'`. For detailed information, refer to the [Server-Side Rendering (SSR)](/guides/basic-features/render/ssr) documentation.
|
|
11
|
+
:::
|
|
12
|
+
|
|
13
|
+
Compared to traditional SSR rendering:
|
|
14
|
+
|
|
15
|
+
- **Faster Perceived Speed**: Streaming rendering can progressively display content, quickly rendering the home page.
|
|
16
|
+
- **Enhanced User Experience**: Users can see page content faster and interact without waiting for the entire page to render.
|
|
17
|
+
- **Better Performance Control**: Developers can better control the loading priority and order, optimizing performance and user experience.
|
|
18
|
+
- **Better Adaptability**: Streaming rendering adapts better to various network speeds and device performance, ensuring good performance across different environments.
|
|
19
|
+
|
|
20
|
+
## Enabling Streaming Rendering
|
|
21
|
+
|
|
22
|
+
Modern.js supports React 18+ streaming rendering. When you enable SSR, streaming rendering is enabled by default:
|
|
23
|
+
|
|
24
|
+
```ts title="modern.config.ts"
|
|
25
|
+
import { defineConfig } from '@modern-js/app-tools';
|
|
26
|
+
|
|
27
|
+
export default defineConfig({
|
|
28
|
+
server: {
|
|
29
|
+
ssr: true, // Streaming rendering enabled by default
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
If you need to explicitly specify streaming rendering mode, you can configure:
|
|
35
|
+
|
|
36
|
+
```ts title="modern.config.ts"
|
|
37
|
+
import { defineConfig } from '@modern-js/app-tools';
|
|
38
|
+
|
|
39
|
+
export default defineConfig({
|
|
40
|
+
server: {
|
|
41
|
+
ssr: {
|
|
42
|
+
mode: 'stream', // Explicitly specify streaming rendering mode
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Modern.js streaming rendering is based on React Router and involves several key APIs:
|
|
49
|
+
|
|
50
|
+
- [`Await`](https://reactrouter.com/en/main/components/await): Used to render the asynchronous data returned by the Data Loader.
|
|
51
|
+
- [`useAsyncValue`](https://reactrouter.com/en/main/hooks/use-async-value): Used to fetch data from the nearest parent `Await` component.
|
|
52
|
+
|
|
53
|
+
## Fetching Data
|
|
54
|
+
|
|
55
|
+
```ts title="user/[id]/page.data.ts"
|
|
56
|
+
import { defer, type LoaderFunctionArgs } from '@modern-js/runtime/router';
|
|
57
|
+
|
|
58
|
+
interface User {
|
|
59
|
+
name: string;
|
|
60
|
+
age: number;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface Data {
|
|
64
|
+
data: User;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const loader = ({ params }: LoaderFunctionArgs) => {
|
|
68
|
+
const userId = params.id;
|
|
69
|
+
|
|
70
|
+
const user = new Promise<User>(resolve => {
|
|
71
|
+
setTimeout(() => {
|
|
72
|
+
resolve({
|
|
73
|
+
name: `user-${userId}`,
|
|
74
|
+
age: 18,
|
|
75
|
+
});
|
|
76
|
+
}, 200);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return defer({ data: user });
|
|
80
|
+
};
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Here, `user` is a Promise object representing asynchronously fetched data, processed using `defer`. Notice that `defer` must receive an object parameter; a direct Promise cannot be passed.
|
|
84
|
+
|
|
85
|
+
Additionally, `defer` can receive both asynchronous and synchronous data. In the example below, short-duration requests are returned using object data, while longer-duration requests are returned using a Promise:
|
|
86
|
+
|
|
87
|
+
```ts title="user/[id]/page.data.ts"
|
|
88
|
+
export const loader = async ({ params }: LoaderFunctionArgs) => {
|
|
89
|
+
const userId = params.id;
|
|
90
|
+
|
|
91
|
+
const user = new Promise<User>(resolve => {
|
|
92
|
+
setTimeout(() => {
|
|
93
|
+
resolve({
|
|
94
|
+
name: `user-${userId}`,
|
|
95
|
+
age: 18,
|
|
96
|
+
});
|
|
97
|
+
}, 2000);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const otherData = new Promise<string>(resolve => {
|
|
101
|
+
setTimeout(() => {
|
|
102
|
+
resolve('some sync data');
|
|
103
|
+
}, 200);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
return defer({
|
|
107
|
+
data: user,
|
|
108
|
+
other: await otherData,
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
This way, the application can prioritize displaying partially available content without waiting for the most time-consuming data requests.
|
|
114
|
+
|
|
115
|
+
## Rendering Data
|
|
116
|
+
|
|
117
|
+
To render the asynchronous data returned by the Data Loader, use the `Await` component. For example:
|
|
118
|
+
|
|
119
|
+
```tsx title="user/[id]/page.tsx"
|
|
120
|
+
import { Await, useLoaderData } from '@modern-js/runtime/router';
|
|
121
|
+
import { Suspense } from 'react';
|
|
122
|
+
import type { Data } from './page.data';
|
|
123
|
+
|
|
124
|
+
const Page = () => {
|
|
125
|
+
const data = useLoaderData() as Data;
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
<div>
|
|
129
|
+
User info:
|
|
130
|
+
<Suspense fallback={<div id="loading">loading user data ...</div>}>
|
|
131
|
+
<Await resolve={data.data}>
|
|
132
|
+
{user => {
|
|
133
|
+
return (
|
|
134
|
+
<div id="data">
|
|
135
|
+
name: {user.name}, age: {user.age}
|
|
136
|
+
</div>
|
|
137
|
+
);
|
|
138
|
+
}}
|
|
139
|
+
</Await>
|
|
140
|
+
</Suspense>
|
|
141
|
+
</div>
|
|
142
|
+
);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export default Page;
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
The `Await` component needs to be wrapped inside a `Suspense` component. The `resolve` prop of `Await` should be the asynchronously fetched data from the Data Loader. When the data is fetched, it will be rendered using the [Render Props](https://zh-hans.react.dev/reference/react/cloneElement#passing-data-with-a-render-prop) pattern. During data fetching, the content set by the `fallback` prop of `Suspense` is displayed.
|
|
149
|
+
|
|
150
|
+
:::warning Warning
|
|
151
|
+
When importing types from the `page.data.ts` file, use `import type` to ensure only type information is imported, preventing Data Loader code from being bundled into the frontend.
|
|
152
|
+
:::
|
|
153
|
+
|
|
154
|
+
In the component, you can also fetch asynchronous data returned by the Data Loader using `useAsyncValue`. For example:
|
|
155
|
+
|
|
156
|
+
```tsx title='page.tsx'
|
|
157
|
+
import { useAsyncValue } from '@modern-js/runtime/router';
|
|
158
|
+
|
|
159
|
+
const UserInfo = () => {
|
|
160
|
+
const user = useAsyncValue();
|
|
161
|
+
return (
|
|
162
|
+
<div>
|
|
163
|
+
name: {user.name}, age: {user.age}
|
|
164
|
+
</div>
|
|
165
|
+
);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const Page = () => {
|
|
169
|
+
const data = useLoaderData() as Data;
|
|
170
|
+
return (
|
|
171
|
+
<div>
|
|
172
|
+
User info:
|
|
173
|
+
<Suspense fallback={<div id="loading">loading user data ...</div>}>
|
|
174
|
+
<Await resolve={data.data}>
|
|
175
|
+
<UserInfo />
|
|
176
|
+
</Await>
|
|
177
|
+
</Suspense>
|
|
178
|
+
</div>
|
|
179
|
+
);
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
export default Page;
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Error Handling
|
|
186
|
+
|
|
187
|
+
The `errorElement` prop of the `Await` component handles errors in Data Loader or sub-component rendering. For example, intentionally throwing an error in the Data Loader function:
|
|
188
|
+
|
|
189
|
+
```ts title="page.loader.ts"
|
|
190
|
+
import { defer } from '@modern-js/runtime/router';
|
|
191
|
+
|
|
192
|
+
export default () => {
|
|
193
|
+
const data = new Promise((resolve, reject) => {
|
|
194
|
+
setTimeout(() => {
|
|
195
|
+
reject(new Error('error occurs'));
|
|
196
|
+
}, 200);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
return defer({ data });
|
|
200
|
+
};
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Then, fetch the error using `useAsyncError` and set a component to render the error message for the `errorElement` prop of the `Await` component:
|
|
204
|
+
|
|
205
|
+
```tsx title="page.ts"
|
|
206
|
+
import { Await, useAsyncError, useLoaderData } from '@modern-js/runtime/router';
|
|
207
|
+
import { Suspense } from 'react';
|
|
208
|
+
|
|
209
|
+
export default function Page() {
|
|
210
|
+
const data = useLoaderData();
|
|
211
|
+
|
|
212
|
+
return (
|
|
213
|
+
<div>
|
|
214
|
+
Error page
|
|
215
|
+
<Suspense fallback={<div>loading ...</div>}>
|
|
216
|
+
<Await resolve={data.data} errorElement={<ErrorElement />}>
|
|
217
|
+
{(data: any) => {
|
|
218
|
+
return <div>never displayed</div>;
|
|
219
|
+
}}
|
|
220
|
+
</Await>
|
|
221
|
+
</Suspense>
|
|
222
|
+
</div>
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function ErrorElement() {
|
|
227
|
+
const error = useAsyncError() as Error;
|
|
228
|
+
return <p>Something went wrong! {error.message}</p>;
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Controlling When to Wait for Full HTML
|
|
233
|
+
|
|
234
|
+
Streaming improves perceived speed, but in some cases (SEO crawlers, A/B buckets, compliance pages) you may want to wait for all content before sending the response.
|
|
235
|
+
|
|
236
|
+
Modern.js decides the streaming mode with this priority:
|
|
237
|
+
|
|
238
|
+
1. Request header `x-should-stream-all` (set per-request in middleware).
|
|
239
|
+
2. Env `MODERN_JS_STREAM_TO_STRING` (forces full HTML).
|
|
240
|
+
3. [isbot](https://www.npmjs.com/package/isbot) check on `user-agent` (bots get full HTML).
|
|
241
|
+
4. Default: stream shell first.
|
|
242
|
+
|
|
243
|
+
Set the header in your middleware to choose the behavior dynamically:
|
|
244
|
+
|
|
245
|
+
```ts title="middleware example"
|
|
246
|
+
export const middleware = async (ctx, next) => {
|
|
247
|
+
const ua = ctx.req.header('user-agent') || '';
|
|
248
|
+
const shouldWaitAll = /Lighthouse|Googlebot/i.test(ua) || ctx.req.path === '/marketing';
|
|
249
|
+
|
|
250
|
+
// Write a boolean string: true -> onAllReady, false -> onShellReady
|
|
251
|
+
ctx.req.headers.set('x-should-stream-all', String(shouldWaitAll));
|
|
252
|
+
|
|
253
|
+
await next();
|
|
254
|
+
};
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
import StreamSSRPerformance from '@site-docs-en/components/stream-ssr-performance';
|
|
258
|
+
|
|
259
|
+
<StreamSSRPerformance />
|
|
260
|
+
|
|
261
|
+
## Related Documentation
|
|
262
|
+
|
|
263
|
+
- [Rendering Mode Overview](/guides/basic-features/render/overview)
|
|
264
|
+
- [Server-Side Rendering (SSR)](/guides/basic-features/render/ssr)
|
|
265
|
+
- [Rendering Cache](/guides/basic-features/render/ssr-cache)
|
|
266
|
+
- [React Server Components (RSC)](/guides/basic-features/render/rsc) - Use with Streaming SSR
|
|
267
|
+
- [New Suspense SSR Architecture in React 18](https://github.com/reactwg/react-18/discussions/37) - React 18 Architecture Overview
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
["routes", "config-routes"]
|
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 3
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Config Routes
|
|
6
|
+
|
|
7
|
+
By default, Modern.js recommends using [Convention Routes](./routes.mdx) as the way to define routes. At the same time, Modern.js also provides a config-based routing capability that can be used together with convention routes or used separately.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
## When to Use Config Routes
|
|
11
|
+
|
|
12
|
+
Config routes are particularly useful in the following scenarios:
|
|
13
|
+
|
|
14
|
+
- **Need flexible route control**: When the file structure cannot directly map to the desired URL structure
|
|
15
|
+
- **Multiple routes pointing to the same component**: Need to point different URL paths to the same page component
|
|
16
|
+
- **Conditional routes**: Dynamically configure routes based on different conditions
|
|
17
|
+
- **Legacy project migration**: Maintain the original routing structure when migrating from other routing systems
|
|
18
|
+
- **Complex route naming**: Need to customize route paths without being limited by file directory structure
|
|
19
|
+
|
|
20
|
+
## Basic Usage
|
|
21
|
+
|
|
22
|
+
In the `src` directory or each entry directory, you can define a `modern.routes.ts` file to configure routes:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { defineRoutes } from '@modern-js/runtime/config-routes'
|
|
26
|
+
|
|
27
|
+
export default defineRoutes(({ route, layout, page, $ }, fileRoutes) => {
|
|
28
|
+
return [
|
|
29
|
+
route("home.tsx", "/"),
|
|
30
|
+
]
|
|
31
|
+
})
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Function Signature Description
|
|
35
|
+
|
|
36
|
+
`defineRoutes` accepts a callback function with two parameters:
|
|
37
|
+
1. `routeFunctions`: An object containing `route`, `layout`, `page`, `$` functions
|
|
38
|
+
2. `fileRoutes`: An array of route configurations generated by convention routes
|
|
39
|
+
|
|
40
|
+
Basic signature of route functions:
|
|
41
|
+
- First parameter: File path relative to `modern.routes.ts`
|
|
42
|
+
- Second parameter: Route path (optional, must be a string)
|
|
43
|
+
- Third parameter: Array of child routes (optional)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
## Route Functions
|
|
47
|
+
|
|
48
|
+
Modern.js provides four main route configuration functions:
|
|
49
|
+
|
|
50
|
+
:::tip Path Description
|
|
51
|
+
|
|
52
|
+
The first parameter (path) of all route functions is a **relative path**, which will be concatenated with the parent path to generate the final route path:
|
|
53
|
+
- **Root path**: `"/"` or `""` represents the root path of the current level
|
|
54
|
+
- **Relative path**: Child route paths will be concatenated relative to the parent path
|
|
55
|
+
- **Dynamic path**: Use `:param` syntax to represent dynamic parameters
|
|
56
|
+
- **Wildcard path**: Use `"*"` syntax to match all paths
|
|
57
|
+
|
|
58
|
+
:::
|
|
59
|
+
|
|
60
|
+
:::info
|
|
61
|
+
|
|
62
|
+
- The first parameter (component file path) of functions like `route`, `layout`, `page`, `$` must point to real files in the current project. Files from `node_modules` and other repositories in Monorepo are not currently supported.
|
|
63
|
+
- Path aliases are not supported (such as `@/pages/...`, `~/pages/...`, etc.); please use relative paths relative to `modern.routes.ts`.
|
|
64
|
+
|
|
65
|
+
:::
|
|
66
|
+
|
|
67
|
+
### `route` Function
|
|
68
|
+
|
|
69
|
+
The `route` function is a general-purpose route configuration function that automatically determines whether to generate a page route or layout route based on whether there are child routes. It can replace `layout`, `page`, `$` and other functions.
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
export default defineRoutes(({ route }, fileRoutes) => {
|
|
73
|
+
return [
|
|
74
|
+
// When no child routes, automatically generates page route
|
|
75
|
+
route("home.tsx", "/"),
|
|
76
|
+
route("about.tsx", "about"),
|
|
77
|
+
|
|
78
|
+
// When has child routes, automatically generates layout route
|
|
79
|
+
// dashboard/layout.tsx needs to contain <Outlet> to render child routes
|
|
80
|
+
route("dashboard/layout.tsx", "dashboard", [
|
|
81
|
+
route("dashboard/overview.tsx", "overview"), // Generated path: /dashboard/overview
|
|
82
|
+
route("dashboard/settings.tsx", "settings"), // Generated path: /dashboard/settings
|
|
83
|
+
]),
|
|
84
|
+
|
|
85
|
+
// Dynamic routes
|
|
86
|
+
route("products/detail.tsx", "products/:id"),
|
|
87
|
+
|
|
88
|
+
// Multiple paths pointing to the same component
|
|
89
|
+
route("user/profile.tsx", "user"),
|
|
90
|
+
route("user/profile.tsx", "profile"),
|
|
91
|
+
]
|
|
92
|
+
})
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Use cases**:
|
|
96
|
+
- Quick route configuration without explicitly specifying page or layout
|
|
97
|
+
- Simplify the complexity of route configuration
|
|
98
|
+
|
|
99
|
+
### `layout` Function
|
|
100
|
+
|
|
101
|
+
The `layout` function is specifically used to configure layout routes, always generates layout components, and must contain child routes:
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
export default defineRoutes(({ layout, page }, fileRoutes) => {
|
|
105
|
+
return [
|
|
106
|
+
// Generate layout route with path "/auth", must contain child routes
|
|
107
|
+
layout("auth/layout.tsx", "auth", [
|
|
108
|
+
page("auth/login/page.tsx", "login"), // Generated path: /auth/login
|
|
109
|
+
page("auth/register/page.tsx", "register"), // Generated path: /auth/register
|
|
110
|
+
]),
|
|
111
|
+
]
|
|
112
|
+
})
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Use cases**:
|
|
116
|
+
- Need to explicitly specify a component as a layout component
|
|
117
|
+
- Provide common layout structure for multiple pages
|
|
118
|
+
- Need to share navigation, sidebar and other UI components across multiple routes
|
|
119
|
+
|
|
120
|
+
### `page` Function
|
|
121
|
+
|
|
122
|
+
The `page` function is specifically used to configure page routes, always generates page components:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
export default defineRoutes(({ layout, page }, fileRoutes) => {
|
|
126
|
+
return [
|
|
127
|
+
layout("dashboard/layout.tsx", "dashboard", [
|
|
128
|
+
page("dashboard/overview.tsx", "overview"), // Generated path: /dashboard/overview
|
|
129
|
+
page("dashboard/settings.tsx", "settings"), // Generated path: /dashboard/settings
|
|
130
|
+
]),
|
|
131
|
+
]
|
|
132
|
+
})
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Use cases**:
|
|
136
|
+
- Need to explicitly specify a component as a page component
|
|
137
|
+
- Ensure the component does not contain `<Outlet>` child component rendering
|
|
138
|
+
- Provide clearer semantic expression
|
|
139
|
+
|
|
140
|
+
### `$` Function
|
|
141
|
+
|
|
142
|
+
The `$` function is specifically used to configure wildcard routes for handling unmatched routes:
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
export default defineRoutes(({ layout, page, $ }, fileRoutes) => {
|
|
146
|
+
return [
|
|
147
|
+
layout("blog/layout.tsx", "blog", [
|
|
148
|
+
page("blog/page.tsx", ""), // Generated path: /blog
|
|
149
|
+
page("blog/[id]/page.tsx", ":id"), // Generated path: /blog/:id
|
|
150
|
+
$("blog/$.tsx", "*"), // Wildcard route, matches all unmatched paths under /blog
|
|
151
|
+
]),
|
|
152
|
+
]
|
|
153
|
+
})
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Use cases**:
|
|
157
|
+
- Custom 404 pages
|
|
158
|
+
- Handle all unmatched requests under specific paths
|
|
159
|
+
|
|
160
|
+
:::tip
|
|
161
|
+
The `$` function has the same functionality as the `$.tsx` file in convention routes, used to catch unmatched route requests.
|
|
162
|
+
:::
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
## Configuring Routes
|
|
166
|
+
|
|
167
|
+
### Basic Example
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
export default defineRoutes(({ page }, fileRoutes) => {
|
|
171
|
+
return [
|
|
172
|
+
// Use page function to explicitly specify page route
|
|
173
|
+
page("home.tsx", "/"),
|
|
174
|
+
page("about.tsx", "about"),
|
|
175
|
+
page("contact.tsx", "contact"),
|
|
176
|
+
]
|
|
177
|
+
})
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Routes Without Path
|
|
181
|
+
|
|
182
|
+
When no path is specified, routes inherit the parent path:
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
export default defineRoutes(({ layout, page }, fileRoutes) => {
|
|
186
|
+
return [
|
|
187
|
+
// Use layout function to explicitly specify layout route
|
|
188
|
+
// auth/layout.tsx needs to contain <Outlet> to render child routes
|
|
189
|
+
layout("auth/layout.tsx", [
|
|
190
|
+
page("login/page.tsx", "login"),
|
|
191
|
+
page("register/page.tsx", "register"),
|
|
192
|
+
]),
|
|
193
|
+
]
|
|
194
|
+
})
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
The above configuration will generate:
|
|
198
|
+
- `/login` → `auth/layout.tsx` + `login/page.tsx`
|
|
199
|
+
- `/register` → `auth/layout.tsx` + `register/page.tsx`
|
|
200
|
+
|
|
201
|
+
### Multiple Paths Pointing to the Same Component
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
export default defineRoutes(({ page }, fileRoutes) => {
|
|
205
|
+
return [
|
|
206
|
+
page("user.tsx", "user"),
|
|
207
|
+
page("user.tsx", "profile"),
|
|
208
|
+
page("user.tsx", "account"),
|
|
209
|
+
]
|
|
210
|
+
})
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
### Dynamic Routes
|
|
215
|
+
|
|
216
|
+
Config routes support dynamic route parameters:
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
export default defineRoutes(({ page }, fileRoutes) => {
|
|
220
|
+
return [
|
|
221
|
+
// Required parameter
|
|
222
|
+
page("blog/detail.tsx", "blog/:id"),
|
|
223
|
+
|
|
224
|
+
// Optional parameter
|
|
225
|
+
page("blog/index.tsx", "blog/:slug?"),
|
|
226
|
+
]
|
|
227
|
+
})
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
## Automatic Route-Related File Discovery
|
|
232
|
+
|
|
233
|
+
Config routes automatically discover component-related files without manual configuration. For any component file specified in `modern.routes.ts`, Modern.js will automatically find the following related files:
|
|
234
|
+
|
|
235
|
+
```ts
|
|
236
|
+
// modern.routes.ts
|
|
237
|
+
export default defineRoutes(({ route }, fileRoutes) => {
|
|
238
|
+
return [
|
|
239
|
+
route("pages/profile.tsx", "profile"),
|
|
240
|
+
route("pages/user/detail.tsx", "user/:id"),
|
|
241
|
+
]
|
|
242
|
+
})
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Modern.js will automatically find and load:
|
|
246
|
+
|
|
247
|
+
- `pages/profile.data.ts` → Data loader
|
|
248
|
+
- `pages/profile.config.ts` → Route configuration
|
|
249
|
+
- `pages/profile.error.tsx` → Error boundary
|
|
250
|
+
- `pages/profile.loading.tsx` → Loading component
|
|
251
|
+
|
|
252
|
+
### Discovery Rules
|
|
253
|
+
|
|
254
|
+
- **File location**: Related files must be in the same directory as the component file
|
|
255
|
+
- **File naming**: Related file names are the same as the component file name (excluding extension)
|
|
256
|
+
- **Auto-discovery**: Modern.js automatically discovers and loads these files
|
|
257
|
+
|
|
258
|
+
:::tip
|
|
259
|
+
|
|
260
|
+
For more detailed information about data fetching, please refer to the [Data Fetching](../data/data-fetch.mdx) documentation. For Loading component usage, please refer to [Convention Routes - Loading](./routes.mdx#loading-experimental).
|
|
261
|
+
|
|
262
|
+
:::
|
|
263
|
+
|
|
264
|
+
## Route Merging
|
|
265
|
+
|
|
266
|
+
Config routes can be used together with convention routes. You can merge routes by modifying the `fileRoutes` parameter:
|
|
267
|
+
|
|
268
|
+
1. **Override routes**: You can actively remove convention routes and replace them with config routes
|
|
269
|
+
2. **Supplement routes**: You can add new config routes based on convention routes
|
|
270
|
+
3. **Mixed usage**: You can add config child routes under convention layout routes
|
|
271
|
+
|
|
272
|
+
:::info
|
|
273
|
+
|
|
274
|
+
Current route structure can be viewed through the [`modern routes`](#debugging-routes) command
|
|
275
|
+
|
|
276
|
+
:::
|
|
277
|
+
|
|
278
|
+
### Merging Examples
|
|
279
|
+
|
|
280
|
+
The following examples demonstrate how to merge config routes with convention routes:
|
|
281
|
+
|
|
282
|
+
```ts
|
|
283
|
+
// modern.routes.ts
|
|
284
|
+
import { defineRoutes } from '@modern-js/runtime/config-routes';
|
|
285
|
+
|
|
286
|
+
export default defineRoutes(({ page }, fileRoutes) => {
|
|
287
|
+
// Scenario 1: Override convention routes
|
|
288
|
+
// Remove the original shop route and replace with custom component
|
|
289
|
+
const shopPageIndex = fileRoutes[0].children?.findIndex(
|
|
290
|
+
route => route.id === 'three_shop/page',
|
|
291
|
+
);
|
|
292
|
+
fileRoutes[0].children?.splice(shopPageIndex!, 1);
|
|
293
|
+
fileRoutes[0].children?.push(page('routes/CustomShop.tsx', 'shop'));
|
|
294
|
+
|
|
295
|
+
// Scenario 2: Supplement convention routes
|
|
296
|
+
// Add config routes without corresponding convention routes
|
|
297
|
+
fileRoutes[0].children?.push(page('routes/Settings.tsx', 'settings'));
|
|
298
|
+
|
|
299
|
+
// Scenario 3: Mixed nested routes
|
|
300
|
+
// Add config child routes under convention layout routes
|
|
301
|
+
const userRoute = fileRoutes[0].children?.find(
|
|
302
|
+
(route: any) => route.path === 'user',
|
|
303
|
+
);
|
|
304
|
+
if (userRoute?.children) {
|
|
305
|
+
userRoute.children.push(page('routes/user/CustomTab.tsx', 'custom-tab'));
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Scenario 4: Automatic discovery of related files
|
|
309
|
+
// Product.tsx will automatically discover Product.data.ts and Product.error.tsx
|
|
310
|
+
fileRoutes[0].children?.push(page('routes/Product.tsx', 'product/:id'));
|
|
311
|
+
|
|
312
|
+
return fileRoutes;
|
|
313
|
+
});
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## Debugging Routes
|
|
317
|
+
|
|
318
|
+
Since the final structure after route merging may not be intuitive, Modern.js provides debugging commands to help you view complete route information:
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
# Generate route structure analysis report
|
|
322
|
+
npx modern routes
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
This command will generate the final route structure in the `dist/routes-inspect.json` file, helping you understand the complete route information after merging.
|
|
326
|
+
|
|
327
|
+
### Report File Examples
|
|
328
|
+
|
|
329
|
+
#### Single Entry Scenario
|
|
330
|
+
|
|
331
|
+
```json title="dist/routes-inspect.json"
|
|
332
|
+
{
|
|
333
|
+
"routes": [
|
|
334
|
+
{
|
|
335
|
+
"path": "/",
|
|
336
|
+
"component": "@_modern_js_src/routes/page",
|
|
337
|
+
"data": "@_modern_js_src/routes/page.data",
|
|
338
|
+
"clientData": "@_modern_js_src/routes/page.data.client",
|
|
339
|
+
"error": "@_modern_js_src/routes/page.error",
|
|
340
|
+
"loading": "@_modern_js_src/routes/page.loading"
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
"path": "/dashboard",
|
|
344
|
+
"component": "pages/admin",
|
|
345
|
+
"config": "pages/admin.config",
|
|
346
|
+
"error": "pages/admin.error"
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
"path": "/user",
|
|
350
|
+
"component": "layouts/user",
|
|
351
|
+
"children": [
|
|
352
|
+
{
|
|
353
|
+
"path": "/user/profile",
|
|
354
|
+
"component": "@_modern_js_src/routes/user/profile",
|
|
355
|
+
"data": "@_modern_js_src/routes/user/profile.data"
|
|
356
|
+
}
|
|
357
|
+
]
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
"path": "@_modern_js_src/routes/blog/:id",
|
|
361
|
+
"component": "blog/detail",
|
|
362
|
+
"params": ["id"],
|
|
363
|
+
"data": "blog/detail.data",
|
|
364
|
+
"loading": "blog/detail.loading"
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
"path": "/files/*",
|
|
368
|
+
"component": "@_modern_js_src/routes/files/list"
|
|
369
|
+
}
|
|
370
|
+
]
|
|
371
|
+
}
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
#### Multi-entry Scenario
|
|
375
|
+
|
|
376
|
+
In multi-entry projects, the report file will be grouped by entry name, where the key is entryName:
|
|
377
|
+
|
|
378
|
+
```json title="dist/routes-inspect.json"
|
|
379
|
+
{
|
|
380
|
+
"main": {
|
|
381
|
+
"routes": [
|
|
382
|
+
{
|
|
383
|
+
"path": "/",
|
|
384
|
+
"component": "@_modern_js_src/routes/page",
|
|
385
|
+
"data": "@_modern_js_src/routes/page.data",
|
|
386
|
+
"error": "@_modern_js_src/routes/page.error",
|
|
387
|
+
"loading": "@_modern_js_src/routes/page.loading"
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
"path": "/dashboard",
|
|
391
|
+
"component": "@_modern_js_src/routes/dashboard",
|
|
392
|
+
"config": "@_modern_js_src/routes/dashboard.config"
|
|
393
|
+
}
|
|
394
|
+
]
|
|
395
|
+
},
|
|
396
|
+
"admin": {
|
|
397
|
+
"routes": [
|
|
398
|
+
{
|
|
399
|
+
"path": "/",
|
|
400
|
+
"component": "@_modern_js_src/routes/dashboard",
|
|
401
|
+
"data": "@_modern_js_src/routes/dashboard.data",
|
|
402
|
+
"clientData": "@_modern_js_src/routes/dashboard.data.client",
|
|
403
|
+
"config": "@_modern_js_src/routes/dashboard.config"
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
"path": "/users",
|
|
407
|
+
"component": "@_modern_js_src/routes/users",
|
|
408
|
+
"data": "@_modern_js_src/routes/users.data",
|
|
409
|
+
"error": "@_modern_js_src/routes/users.error",
|
|
410
|
+
"loading": "@_modern_js_src/routes/users.loading"
|
|
411
|
+
}
|
|
412
|
+
]
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
#### Route-Related File Field Descriptions
|
|
418
|
+
|
|
419
|
+
In addition to basic route information, the report also displays related files found for each route:
|
|
420
|
+
|
|
421
|
+
- **`data`**: Server-side data loading file (`.data.ts`), used to fetch data on the server
|
|
422
|
+
- **`clientData`**: Client-side data loading file (`.data.client.ts`), used to refetch data on the client
|
|
423
|
+
- **`error`**: Error boundary file (`.error.tsx`), used to handle route rendering errors
|
|
424
|
+
- **`loading`**: Loading state component file (`.loading.tsx`), used to display data loading state
|
|
425
|
+
- **`config`**: Route configuration file (`.config.ts`), used to configure route metadata
|
|
426
|
+
|
|
427
|
+
These fields are optional and will only be displayed in the report when corresponding files are found. By viewing these fields, you can quickly understand the complete file structure for each route.
|