Skip to content

Commit 3516e99

Browse files
authored
feat(rsbuild): enable ESM for SSR examples (#339)
1 parent 635a446 commit 3516e99

File tree

10 files changed

+75
-57
lines changed

10 files changed

+75
-57
lines changed

.vscode/settings.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,11 @@
1414
"**/.DS_Store": true
1515
},
1616
"editor.defaultFormatter": "biomejs.biome",
17-
"mdx.validate.validateFileLinks": "ignore"
17+
"mdx.validate.validateFileLinks": "ignore",
18+
"[javascript]": {
19+
"editor.defaultFormatter": "biomejs.biome"
20+
},
21+
"[typescript]": {
22+
"editor.defaultFormatter": "biomejs.biome"
23+
}
1824
}

pnpm-lock.yaml

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rsbuild/ssr-express-with-manifest/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"private": true,
55
"scripts": {
66
"build": "rsbuild build",
7-
"dev": "node ./server.mjs",
7+
"dev": "cross-env NODE_OPTIONS=\"--experimental-vm-modules --no-warnings\" node ./server.mjs",
88
"preview": "node ./prod-server.mjs"
99
},
1010
"dependencies": {
@@ -17,6 +17,7 @@
1717
"@types/express": "^5.0.3",
1818
"@types/react": "^19.1.11",
1919
"@types/react-dom": "^19.1.7",
20+
"cross-env": "^10.0.0",
2021
"express": "^5.1.0",
2122
"typescript": "^5.9.2"
2223
}
Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,35 @@
1-
import { defineConfig } from "@rsbuild/core";
2-
import { pluginReact } from "@rsbuild/plugin-react";
1+
import { defineConfig } from '@rsbuild/core';
2+
import { pluginReact } from '@rsbuild/plugin-react';
33

44
export default defineConfig({
55
plugins: [pluginReact()],
66
environments: {
77
web: {
8-
output: {
9-
target: "web",
10-
},
118
source: {
129
entry: {
13-
index: "./src/index",
10+
index: './src/index',
1411
},
1512
},
1613
output: {
1714
manifest: true,
1815
},
1916
},
20-
ssr: {
17+
node: {
2118
output: {
22-
target: "node",
19+
module: true,
20+
target: 'node',
2321
distPath: {
24-
root: "dist/server",
22+
root: 'dist/server',
2523
},
2624
},
2725
source: {
2826
entry: {
29-
index: "./src/index.server",
27+
index: './src/index.server',
3028
},
3129
},
3230
},
3331
},
3432
tools: {
35-
htmlPlugin: false
36-
}
33+
htmlPlugin: false,
34+
},
3735
});

rsbuild/ssr-express-with-manifest/server.mjs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,29 @@
1-
import express from "express";
21
import fs from 'node:fs';
3-
import { createRsbuild, loadConfig, logger } from "@rsbuild/core";
2+
import { createRsbuild, loadConfig, logger } from '@rsbuild/core';
3+
import express from 'express';
44

55
const templateHtml = fs.readFileSync('./template.html', 'utf-8');
66

77
let manifest;
88

99
const serverRender = (serverAPI) => async (_req, res) => {
10-
const indexModule = await serverAPI.environments.ssr.loadBundle("index");
10+
const indexModule = await serverAPI.environments.node.loadBundle('index');
1111

1212
const markup = indexModule.render();
1313

1414
const { entries } = JSON.parse(manifest);
1515

16-
const { js = [], css = []} = entries['index'].initial;
16+
const { js = [], css = [] } = entries['index'].initial;
1717

18-
const scriptTags = js
19-
.map((url) => `<script src="${url}" defer></script>`)
20-
.join('\n');
21-
const styleTags = css
22-
.map((file) => `<link rel="stylesheet" href="${file}">`)
23-
.join('\n');
18+
const scriptTags = js.map((url) => `<script src="${url}" defer></script>`).join('\n');
19+
const styleTags = css.map((file) => `<link rel="stylesheet" href="${file}">`).join('\n');
2420

25-
const html = templateHtml.replace("<!--app-content-->", markup).replace('<!--app-head-->', `${scriptTags}\n${styleTags}`);
21+
const html = templateHtml
22+
.replace('<!--app-content-->', markup)
23+
.replace('<!--app-head-->', `${scriptTags}\n${styleTags}`);
2624

2725
res.writeHead(200, {
28-
"Content-Type": "text/html",
26+
'Content-Type': 'text/html',
2927
});
3028
res.end(html);
3129
};
@@ -41,7 +39,7 @@ export async function startDevServer() {
4139
rsbuild.onDevCompileDone(async () => {
4240
// update manifest info when rebuild
4341
manifest = await fs.promises.readFile('./dist/manifest.json', 'utf-8');
44-
})
42+
});
4543

4644
const app = express();
4745

@@ -50,11 +48,12 @@ export async function startDevServer() {
5048

5149
const serverRenderMiddleware = serverRender(rsbuildServer);
5250

53-
app.get("/", async (req, res, next) => {
51+
app.get('/', async (req, res, next) => {
5452
try {
5553
await serverRenderMiddleware(req, res, next);
5654
} catch (err) {
57-
logger.error("SSR render error, downgrade to CSR...\n", err);
55+
logger.error('SSR render error, downgrade to CSR...');
56+
logger.error(err);
5857
next();
5958
}
6059
});

rsbuild/ssr-express/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"private": true,
55
"scripts": {
66
"build": "rsbuild build",
7-
"dev": "node ./server.mjs",
7+
"dev": "cross-env NODE_OPTIONS=\"--experimental-vm-modules --no-warnings\" node ./server.mjs",
88
"preview": "node ./prod-server.mjs"
99
},
1010
"dependencies": {
@@ -17,6 +17,7 @@
1717
"@types/express": "^5.0.3",
1818
"@types/react": "^19.1.11",
1919
"@types/react-dom": "^19.1.7",
20+
"cross-env": "^10.0.0",
2021
"express": "^5.1.0",
2122
"typescript": "^5.9.2"
2223
}
Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,32 @@
1-
import { defineConfig } from "@rsbuild/core";
2-
import { pluginReact } from "@rsbuild/plugin-react";
1+
import { defineConfig } from '@rsbuild/core';
2+
import { pluginReact } from '@rsbuild/plugin-react';
33

44
export default defineConfig({
55
plugins: [pluginReact()],
66
environments: {
77
web: {
8-
output: {
9-
target: "web",
10-
},
118
source: {
129
entry: {
13-
index: "./src/index",
10+
index: './src/index',
1411
},
1512
},
1613
},
17-
ssr: {
14+
node: {
1815
output: {
19-
target: "node",
16+
module: true,
17+
target: 'node',
2018
distPath: {
21-
root: "dist/server",
19+
root: 'dist/server',
2220
},
2321
},
2422
source: {
2523
entry: {
26-
index: "./src/index.server",
24+
index: './src/index.server',
2725
},
2826
},
2927
},
3028
},
3129
html: {
32-
template: "./template.html",
30+
template: './template.html',
3331
},
3432
});

rsbuild/ssr-express/server.mjs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
import express from "express";
2-
import { createRsbuild, loadConfig, logger } from "@rsbuild/core";
1+
import { createRsbuild, loadConfig, logger } from '@rsbuild/core';
2+
import express from 'express';
33

44
const serverRender = (serverAPI) => async (_req, res) => {
5-
const indexModule = await serverAPI.environments.ssr.loadBundle("index");
5+
const indexModule = await serverAPI.environments.node.loadBundle('index');
66

77
const markup = indexModule.render();
88

9-
const template = await serverAPI.environments.web.getTransformedHtml("index");
9+
const template = await serverAPI.environments.web.getTransformedHtml('index');
1010

11-
const html = template.replace("<!--app-content-->", markup);
11+
const html = template.replace('<!--app-content-->', markup);
1212

1313
res.writeHead(200, {
14-
"Content-Type": "text/html",
14+
'Content-Type': 'text/html',
1515
});
1616
res.end(html);
1717
};
@@ -31,11 +31,12 @@ export async function startDevServer() {
3131

3232
const serverRenderMiddleware = serverRender(rsbuildServer);
3333

34-
app.get("/", async (req, res, next) => {
34+
app.get('/', async (req, res, next) => {
3535
try {
3636
await serverRenderMiddleware(req, res, next);
3737
} catch (err) {
38-
logger.error("SSR render error, downgrade to CSR...\n", err);
38+
logger.error('SSR render error, downgrade to CSR...');
39+
logger.error(err);
3940
next();
4041
}
4142
});

rsbuild/ssr/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"private": true,
55
"scripts": {
66
"build": "rsbuild build",
7-
"dev": "rsbuild dev --open",
7+
"dev": "cross-env NODE_OPTIONS=\"--experimental-vm-modules --no-warnings\" rsbuild dev --open",
88
"preview": "rsbuild preview"
99
},
1010
"dependencies": {
@@ -16,6 +16,7 @@
1616
"@rsbuild/plugin-react": "1.3.5",
1717
"@types/react": "^19.1.11",
1818
"@types/react-dom": "^19.1.7",
19+
"cross-env": "^10.0.0",
1920
"typescript": "^5.9.2"
2021
}
2122
}

rsbuild/ssr/rsbuild.config.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
import { type RequestHandler, type SetupMiddlewaresContext, defineConfig, logger } from '@rsbuild/core';
1+
import {
2+
defineConfig,
3+
logger,
4+
type RequestHandler,
5+
type SetupMiddlewaresContext,
6+
} from '@rsbuild/core';
27
import { pluginReact } from '@rsbuild/plugin-react';
38

49
export const serverRender =
510
(serverContext: SetupMiddlewaresContext): RequestHandler =>
611
async (_req, res, _next) => {
7-
const indexModule = await serverContext.environments.ssr.loadBundle<{
12+
const indexModule = await serverContext.environments.node.loadBundle<{
813
render: () => string;
914
}>('index');
1015

@@ -32,7 +37,8 @@ export default defineConfig({
3237
try {
3338
await serverRenderMiddleware(req, res, next);
3439
} catch (err) {
35-
logger.error('SSR render error, downgrade to CSR...\n', err);
40+
logger.error('SSR render error, downgrade to CSR...');
41+
logger.error(err);
3642
next();
3743
}
3844
} else {
@@ -44,17 +50,15 @@ export default defineConfig({
4450
},
4551
environments: {
4652
web: {
47-
output: {
48-
target: 'web',
49-
},
5053
source: {
5154
entry: {
5255
index: './src/index',
5356
},
5457
},
5558
},
56-
ssr: {
59+
node: {
5760
output: {
61+
module: true,
5862
target: 'node',
5963
distPath: {
6064
root: 'dist/server',

0 commit comments

Comments
 (0)