diff --git a/packages/server/core/src/plugins/index.ts b/packages/server/core/src/plugins/index.ts index 3dd30f0dbb8a..629dfa7d8f3c 100644 --- a/packages/server/core/src/plugins/index.ts +++ b/packages/server/core/src/plugins/index.ts @@ -14,3 +14,4 @@ export { } from './default'; export { compatPlugin, handleSetupResult } from './compat'; export { injectConfigMiddlewarePlugin } from './middlewares'; +export { routerRewritePlugin } from './rewrite'; diff --git a/packages/server/core/src/plugins/rewrite.ts b/packages/server/core/src/plugins/rewrite.ts new file mode 100644 index 000000000000..7e10d93f352c --- /dev/null +++ b/packages/server/core/src/plugins/rewrite.ts @@ -0,0 +1,40 @@ +import type { ServerPluginLegacy } from '../types'; + +declare module 'Hono' { + interface Context { + rewriteByEntry: (entry: string) => void; + rewrite: (entry: string) => void; + } +} + +export const routerRewritePlugin = (): ServerPluginLegacy => ({ + name: '@Modern-js/plugin-router-rewrite-plugin', + setup(api) { + return { + prepare() { + const { middlewares, routes } = api.useAppContext(); + if (!routes) { + return; + } + + middlewares.push({ + name: 'router-rewrite', + order: 'pre', + handler: async (c, next) => { + c.rewriteByEntry = (entry: string) => { + const rewriteRoute = routes + .filter(route => !route.isApi) + .find(route => route.entryName === entry); + + if (rewriteRoute) { + c.set('matchPathname', rewriteRoute.urlPath); + c.set('matchEntryName', entry); + } + }; + await next(); + }, + }); + }, + }; + }, +}); diff --git a/packages/server/prod-server/src/apply.ts b/packages/server/prod-server/src/apply.ts index 2d21b67492b2..166993e3435a 100644 --- a/packages/server/prod-server/src/apply.ts +++ b/packages/server/prod-server/src/apply.ts @@ -9,6 +9,7 @@ import { injectConfigMiddlewarePlugin, onError, renderPlugin, + routerRewritePlugin, } from '@modern-js/server-core'; import { injectNodeSeverPlugin, @@ -59,6 +60,7 @@ export async function applyPlugins( const { middlewares, renderMiddlewares } = options.serverConfig || {}; const plugins = [ + routerRewritePlugin(), ...(nodeServer ? [injectNodeSeverPlugin({ nodeServer })] : []), ...createDefaultPlugins({ cacheConfig, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ec8d4ece6ff3..b7dff86d4888 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6982,6 +6982,9 @@ importers: '@modern-js/app-tools': specifier: workspace:* version: link:../../../packages/solutions/app-tools + '@modern-js/server-runtime': + specifier: workspace:* + version: link:../../../packages/server/server-runtime '@types/fs-extra': specifier: 9.0.13 version: 9.0.13 @@ -6997,9 +7000,15 @@ importers: '@types/react-dom': specifier: ^18.3.1 version: 18.3.5(@types/react@18.3.18) + ts-node: + specifier: ^10.9.1 + version: 10.9.2(@swc/core@1.10.18(@swc/helpers@0.5.17))(@types/node@14.18.35)(typescript@5.0.4) + tsconfig-paths: + specifier: ~3.14.1 + version: 3.14.1 typescript: - specifier: ^5 - version: 5.6.3 + specifier: ~5.0.4 + version: 5.0.4 tests/integration/routes-match: dependencies: @@ -43452,6 +43461,26 @@ snapshots: typescript: 5.6.3 webpack: 5.99.8(@swc/core@1.10.18(@swc/helpers@0.5.17))(esbuild@0.17.19) + ts-node@10.9.2(@swc/core@1.10.18(@swc/helpers@0.5.17))(@types/node@14.18.35)(typescript@5.0.4): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 14.18.35 + acorn: 8.14.1 + acorn-walk: 8.3.4 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.0.4 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + optionalDependencies: + '@swc/core': 1.10.18(@swc/helpers@0.5.17) + ts-node@10.9.2(@swc/core@1.10.18(@swc/helpers@0.5.17))(@types/node@14.18.35)(typescript@5.6.3): dependencies: '@cspotcode/source-map-support': 0.8.1 diff --git a/tests/integration/routes/modern.config.ts b/tests/integration/routes/modern.config.ts index 40afacfe9a5e..9164a8788315 100644 --- a/tests/integration/routes/modern.config.ts +++ b/tests/integration/routes/modern.config.ts @@ -33,6 +33,7 @@ export default defineConfig({ loaderFailureMode: 'clientRender', }, four: false, + rewrite: false, }, }, }); diff --git a/tests/integration/routes/package.json b/tests/integration/routes/package.json index a7a3998f3fc3..7e7631e16ff1 100644 --- a/tests/integration/routes/package.json +++ b/tests/integration/routes/package.json @@ -25,6 +25,9 @@ "@types/node": "^14", "@types/react": "^18.3.11", "@types/react-dom": "^18.3.1", - "typescript": "^5" + "typescript": "~5.0.4", + "@modern-js/server-runtime": "workspace:*", + "ts-node": "^10.9.1", + "tsconfig-paths": "~3.14.1" } } diff --git a/tests/integration/routes/server/.eslintrc.js b/tests/integration/routes/server/.eslintrc.js new file mode 100644 index 000000000000..2538816f15b1 --- /dev/null +++ b/tests/integration/routes/server/.eslintrc.js @@ -0,0 +1,18 @@ +module.exports = { + root: true, + plugins: ['prettier'], + rules: { + // eslint-disable-next-line + 'prettier/prettier': 'error', + }, + overrides: [ + { + files: ['*.js', '*.jsx'], + extends: '@byted/eslint-config-standard', + }, + { + files: ['*.ts', '*.tsx'], + extends: '@byted/eslint-config-standard-ts', + }, + ], +}; diff --git a/tests/integration/routes/server/modern.server.ts b/tests/integration/routes/server/modern.server.ts new file mode 100644 index 000000000000..63fe6ae59e7a --- /dev/null +++ b/tests/integration/routes/server/modern.server.ts @@ -0,0 +1,21 @@ +import { + type MiddlewareHandler, + defineServerConfig, +} from '@modern-js/server-runtime'; + +const renderTiming: MiddlewareHandler = async (c, next) => { + if (c.req.path === '/rewrite') { + c.rewriteByEntry('one'); + } + + await next(); +}; + +export default defineServerConfig({ + renderMiddlewares: [ + { + name: 'render-timing', + handler: renderTiming, + }, + ], +}); diff --git a/tests/integration/routes/src/rewrite/App.css b/tests/integration/routes/src/rewrite/App.css new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/integration/routes/src/rewrite/App.tsx b/tests/integration/routes/src/rewrite/App.tsx new file mode 100644 index 000000000000..000d0f81c7c4 --- /dev/null +++ b/tests/integration/routes/src/rewrite/App.tsx @@ -0,0 +1,5 @@ +import './App.css'; + +const App = () =>

rewrite page

; + +export default App; diff --git a/tests/integration/routes/tsconfig.json b/tests/integration/routes/tsconfig.json index f2c10d4cd9e9..2bd10fd4bd4c 100644 --- a/tests/integration/routes/tsconfig.json +++ b/tests/integration/routes/tsconfig.json @@ -9,5 +9,5 @@ "@shared/*": ["./shared/*"] } }, - "include": ["src", "shared", "config"] + "include": ["src", "shared", "config", "server"] }