Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
386 changes: 194 additions & 192 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions rsbuild/ssr/rsbuild.config.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { type RequestHandler, type ServerAPIs, defineConfig, logger } from '@rsbuild/core';
import { type RequestHandler, type SetupMiddlewaresContext, defineConfig, logger } from '@rsbuild/core';
import { pluginReact } from '@rsbuild/plugin-react';

export const serverRender =
(serverAPI: ServerAPIs): RequestHandler =>
(serverContext: SetupMiddlewaresContext): RequestHandler =>
async (_req, res, _next) => {
const indexModule = await serverAPI.environments.ssr.loadBundle<{
const indexModule = await serverContext.environments.ssr.loadBundle<{
render: () => string;
}>('index');

const markup = indexModule.render();

const template = await serverAPI.environments.web.getTransformedHtml('index');
const template = await serverContext.environments.web.getTransformedHtml('index');

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

Expand All @@ -24,8 +24,8 @@ export default defineConfig({
plugins: [pluginReact()],
dev: {
setupMiddlewares: [
({ unshift }, serverAPI) => {
const serverRenderMiddleware = serverRender(serverAPI);
({ unshift }, serverContext) => {
const serverRenderMiddleware = serverRender(serverContext);

unshift(async (req, res, next) => {
if (req.method === 'GET' && req.url === '/') {
Expand Down
1 change: 1 addition & 0 deletions rsbuild/vue3-element-plus/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
// biome-ignore lint: disable
export {}

/* prettier-ignore */
Expand Down
1 change: 1 addition & 0 deletions rsbuild/vue3-vant/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
// biome-ignore lint: disable
export {}

/* prettier-ignore */
Expand Down
5 changes: 5 additions & 0 deletions rspack/react-ssr-esm/client/client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React from "react";
import ReactDOM from "react-dom";
import { App } from "./components/app";

ReactDOM.hydrate(<App />, document.getElementById("root"));
3 changes: 3 additions & 0 deletions rspack/react-ssr-esm/client/components/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import React from "react";

export const App: React.FC = () => <p>Rspack + React + SSR + ESM</p>;
56 changes: 56 additions & 0 deletions rspack/react-ssr-esm/dev.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { spawn } from "cross-spawn";
import path from "path";
import rspack from "@rspack/core";
import rspackConfigClient from "./rspack.config.client.js";
import rspackConfigServer from "./rspack.config.server.js";
import { fileURLToPath } from 'url'
import { dirname } from 'path'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)

const compiler = rspack([
{
...rspackConfigClient,
mode: "development",
devtool: "source-map",
output: {
...rspackConfigClient.output,
filename: "[name].js",
},
},
{
...rspackConfigServer,
mode: "development",
devtool: "source-map",
},
]);

let node;

compiler.hooks.watchRun.tap("Dev", (compiler) => {
console.log(`Compiling ${compiler.name} ...`);
if (compiler.name === "server" && node) {
node.kill();
node = undefined;
}
});

compiler.watch({}, (err, stats) => {
if (err) {
console.error(err);
process.exit(1);
}
console.log(stats?.toString("minimal"));
const compiledSuccessfully = !stats?.hasErrors();
if (compiledSuccessfully && !node) {
console.log("Starting Node.js ...");
node = spawn(
"node",
["--inspect", path.join(__dirname, "dist/server.js")],
{
stdio: "inherit",
}
);
}
});
29 changes: 29 additions & 0 deletions rspack/react-ssr-esm/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "example-react-ssr-esm",
"version": "1.0.0",
"type": "module",
"scripts": {
"build:server": "rspack --config rspack.config.server.js",
"build:client": "rspack --config rspack.config.client.js",
"start": "node ./dist/server.js",
"start:dev": "node dev.js"
},
"devDependencies": {
"@types/cross-spawn": "^6.0.6",
"@types/express": "^5.0.3",
"@types/node": "^22.17.1",
"@types/react": "^19.1.9",
"@types/react-dom": "^19.1.7",
"cross-spawn": "^7.0.6",
"typescript": "^5.9.2",
"rspack-manifest-plugin": "^5.0.3",
"@rspack/core": "1.4.11",
"@rspack/cli": "1.4.11"
},
"dependencies": {
"ejs": "^3.1.10",
"express": "^5.1.0",
"react": "^19.1.1",
"react-dom": "^19.1.1"
}
}
39 changes: 39 additions & 0 deletions rspack/react-ssr-esm/rspack.config.client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import path from "path";
import { RspackManifestPlugin } from "rspack-manifest-plugin";
import { fileURLToPath } from "url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

export default {
name: "client",
entry: {
client: path.resolve(__dirname, "client/client.tsx"),
},
mode: "production",
output: {
clean: true,
path: path.resolve(__dirname + "/dist/static"),
filename: "[name].[contenthash].js",
publicPath: "",
},
resolve: {
extensions: [".ts", ".tsx", ".js"],
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: "builtin:swc-loader",
},
],
},
target: "web",
plugins: [new RspackManifestPlugin()],
output: {
module: true,
},
experiments: {
outputModule: true,
},
};
56 changes: 56 additions & 0 deletions rspack/react-ssr-esm/rspack.config.server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import path from 'path'
import rspack from '@rspack/core'
import { fileURLToPath } from 'url'
import { dirname } from 'path'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)

export default {
name: 'server',
entry: {
server: path.resolve(__dirname, 'server', 'server.ts'),
},
mode: 'production',
experiments: {
outputModule: true,
},
output: {
module: true,
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
externalsType: 'node-commonjs',
externals: ['react', 'express', 'react-dom/server'],
resolve: {
extensions: ['.ts', '.tsx'],
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: "builtin:swc-loader",
},
],
},
target: 'node',
node: {
__dirname: false,
__filename: false,
},

plugins: [
new rspack.BannerPlugin({
banner: `
import { fileURLToPath as __rspack_fileURLToPath } from 'url';
import { dirname as __rspack_dirname } from 'path'
const __filename = __rspack_fileURLToPath(import.meta.url);
const __dirname = __rspack_dirname(__filename);
`,
raw: true,
}),
new rspack.CopyRspackPlugin({
patterns: [{ context: 'server', from: 'views', to: 'views' }],
}),
],
}
28 changes: 28 additions & 0 deletions rspack/react-ssr-esm/server/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import express from "express";
import fs from "fs";
import path from "path";
import React from "react";
import ReactDOMServer from "react-dom/server";
import { App } from "../client/components/app";

const server = express();

server.set("view engine", "ejs");
server.set("views", path.join(__dirname, "views"));

server.use("/", express.static(path.join(__dirname, "static")));

const manifest = fs.readFileSync(
path.join(__dirname, "static/manifest.json"),
"utf-8"
);
const assets = JSON.parse(manifest);

server.get("/", (req, res) => {
const component = ReactDOMServer.renderToString(React.createElement(App));
res.render("client", { assets, component });
});

server.listen(3000, () => {
console.log(`Server running on http://localhost:3000`);
});
11 changes: 11 additions & 0 deletions rspack/react-ssr-esm/server/views/client.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Rspack + React + Node.js App</title>
</head>
<body>
<div id="root"><%- component %></div>
<script defer="defer" src="<%= assets["client.js"] %>"></script>
</body>
</html>