Skip to content

Commit bc1670a

Browse files
authored
fix: should get server routes from route.json in serve command (#6627)
1 parent 13e19ba commit bc1670a

File tree

9 files changed

+111
-19
lines changed

9 files changed

+111
-19
lines changed

.changeset/soft-spoons-greet.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@modern-js/app-tools': patch
3+
'@modern-js/server-core': patch
4+
---
5+
6+
fix: should get server routes from route.json in serve command
7+
fix: 在 serve 命令下应该从 route.json 中获取 server routes

packages/server/core/src/adapters/node/plugins/resource.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type {
1616
ServerManifest,
1717
ServerPlugin,
1818
} from '../../../types';
19+
import { uniqueKeyByRoute } from '../../../utils';
1920

2021
export async function getHtmlTemplates(pwd: string, routes: ServerRoute[]) {
2122
const htmls = await Promise.all(
@@ -27,7 +28,7 @@ export async function getHtmlTemplates(pwd: string, routes: ServerRoute[]) {
2728
} catch (e) {
2829
// ignore error
2930
}
30-
return [route.entryName!, html];
31+
return [uniqueKeyByRoute(route), html];
3132
}) || [],
3233
);
3334

packages/server/core/src/plugins/render/render.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {
1212
} from '../../types';
1313
import type { Render } from '../../types';
1414
import type { Params } from '../../types/requestHandler';
15+
import { uniqueKeyByRoute } from '../../utils';
1516
import {
1617
ErrorDigest,
1718
createErrorHtml,
@@ -139,8 +140,7 @@ export async function createRender({
139140
});
140141
}
141142

142-
const html = templates[routeInfo.entryName!];
143-
143+
const html = templates[uniqueKeyByRoute(routeInfo)];
144144
if (!html) {
145145
return new Response(createErrorHtml(404), {
146146
status: 404,

packages/server/core/src/utils/entry.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,8 @@ import type { ServerRoute } from '@modern-js/types';
33
export const sortRoutes = (route1: ServerRoute, route2: ServerRoute) => {
44
return route2.urlPath.length - route1.urlPath.length;
55
};
6+
7+
// Because the same entryName may have different urlPath(ssg), so we need to add urlPath as key
8+
export const uniqueKeyByRoute = (route: ServerRoute) => {
9+
return `${route.entryName!}-${route.urlPath}`;
10+
};

packages/solutions/app-tools/src/plugins/analyze/getServerRoutes.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import fs from 'fs';
21
import path from 'path';
3-
import type { IAppContext } from '@modern-js/core';
42
import type { Entrypoint, ServerRoute } from '@modern-js/types';
53
import {
4+
fs,
5+
ROUTE_SPEC_FILE,
66
SERVER_BUNDLE_DIRECTORY,
77
SERVER_WORKER_BUNDLE_DIRECTORY,
88
getEntryOptions,
@@ -252,3 +252,15 @@ export const getServerRoutes = (
252252

253253
const toPosix = (pathStr: string) =>
254254
pathStr.split(path.sep).join(path.posix.sep);
255+
256+
export const getProdServerRoutes = (distDirectory: string) => {
257+
const routeJSON = path.join(distDirectory, ROUTE_SPEC_FILE);
258+
try {
259+
const { routes } = fs.readJSONSync(routeJSON);
260+
return routes;
261+
} catch (e) {
262+
throw new Error(
263+
`Failed to read routes from ${routeJSON}, please check if the file exists.`,
264+
);
265+
}
266+
};

packages/solutions/app-tools/src/plugins/analyze/index.ts

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as path from 'path';
2+
import type { ServerRoute } from '@modern-js/types';
23
import {
34
fs,
45
createDebugger,
@@ -18,7 +19,7 @@ import { emitResolvedConfig } from '../../utils/config';
1819
import { getSelectedEntries } from '../../utils/getSelectedEntries';
1920
import { printInstructions } from '../../utils/printInstructions';
2021
import { generateRoutes } from '../../utils/routes';
21-
import { checkIsBuildCommands } from './utils';
22+
import { checkIsBuildCommands, checkIsServeCommand } from './utils';
2223

2324
const debug = createDebugger('plugin-analyze');
2425

@@ -54,8 +55,21 @@ export default ({
5455
);
5556
await hooks.addRuntimeExports.call();
5657

58+
const [{ getProdServerRoutes }] = await Promise.all([
59+
import('./getServerRoutes.js'),
60+
]);
61+
5762
if (apiOnly) {
58-
const { routes } = await hooks.modifyServerRoutes.call({ routes: [] });
63+
const routes: ServerRoute[] = [];
64+
if (checkIsServeCommand()) {
65+
routes.push(...getProdServerRoutes(appContext.distDirectory));
66+
} else {
67+
const { routes: modifiedRoutes } =
68+
await hooks.modifyServerRoutes.call({
69+
routes: [],
70+
});
71+
routes.push(...modifiedRoutes);
72+
}
5973

6074
debug(`server routes: %o`, routes);
6175

@@ -80,14 +94,20 @@ export default ({
8094

8195
debug(`entrypoints: %o`, entrypoints);
8296

83-
const initialRoutes = getServerRoutes(entrypoints, {
84-
appContext,
85-
config: resolvedConfig,
86-
});
97+
const routes: ServerRoute[] = [];
98+
if (checkIsServeCommand()) {
99+
routes.push(...getProdServerRoutes(appContext.distDirectory));
100+
} else {
101+
const initialRoutes = getServerRoutes(entrypoints, {
102+
appContext,
103+
config: resolvedConfig,
104+
});
87105

88-
const { routes } = await hooks.modifyServerRoutes.call({
89-
routes: initialRoutes,
90-
});
106+
const { routes: modifiedRoutes } = await hooks.modifyServerRoutes.call({
107+
routes: initialRoutes,
108+
});
109+
routes.push(...modifiedRoutes);
110+
}
91111

92112
debug(`server routes: %o`, routes);
93113

packages/solutions/app-tools/src/plugins/analyze/utils.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ export const checkIsBuildCommands = () => {
7474
return buildCommands.includes(command);
7575
};
7676

77+
export const checkIsServeCommand = () => {
78+
const command = getCommand();
79+
80+
return command === 'serve';
81+
};
82+
7783
export const isSubDirOrEqual = (parent: string, child: string): boolean => {
7884
if (parent === child) {
7985
return true;

tests/integration/ssg/fixtures/nested-routes/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
"name": "ssg-fixtures-nested-routes",
44
"version": "2.9.0",
55
"scripts": {
6-
"build": "modern build"
6+
"build": "modern build",
7+
"serve": "modern serve"
78
},
89
"dependencies": {
910
"@modern-js/app-tools": "workspace:*",

tests/integration/ssg/tests/nested-routes.test.ts

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
import path, { join } from 'path';
22
import { fs } from '@modern-js/utils';
3-
import { killApp, modernBuild } from '../../../utils/modernTestUtils';
3+
import puppeteer from 'puppeteer';
4+
import {
5+
getPort,
6+
killApp,
7+
launchOptions,
8+
modernBuild,
9+
modernServe,
10+
} from '../../../utils/modernTestUtils';
411

512
const fixtureDir = path.resolve(__dirname, '../fixtures');
6-
13+
const appDir = join(fixtureDir, 'nested-routes');
714
jest.setTimeout(1000 * 60 * 3);
815

916
describe('ssg', () => {
1017
let app: any;
11-
let appDir: string;
1218
let distDir: string;
1319
beforeAll(async () => {
14-
appDir = join(fixtureDir, 'nested-routes');
1520
distDir = join(appDir, './dist');
1621
await modernBuild(appDir);
1722
});
@@ -31,3 +36,38 @@ describe('ssg', () => {
3136
expect(html.includes('Hello, User')).toBe(true);
3237
});
3338
});
39+
40+
describe('test ssg request', () => {
41+
let buildRes: { code: number };
42+
let app: any;
43+
let port: any;
44+
beforeAll(async () => {
45+
port = await getPort();
46+
47+
buildRes = await modernBuild(appDir);
48+
app = await modernServe(appDir, port, {
49+
cwd: appDir,
50+
});
51+
});
52+
53+
afterAll(async () => {
54+
await killApp(app);
55+
});
56+
57+
test('should support enableInlineScripts', async () => {
58+
const host = `http://localhost`;
59+
expect(buildRes.code === 0).toBe(true);
60+
const browser = await puppeteer.launch(launchOptions as any);
61+
const page = await browser.newPage();
62+
await page.goto(`${host}:${port}/user`);
63+
64+
const description = await page.$('#data');
65+
const targetText = await page.evaluate(el => el?.textContent, description);
66+
try {
67+
expect(targetText?.trim()).toEqual('Hello, User');
68+
} finally {
69+
await page.close();
70+
await browser.close();
71+
}
72+
});
73+
});

0 commit comments

Comments
 (0)