@esmx/rspack 3.0.0-rc.18 → 3.0.0-rc.20
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/LICENSE +1 -1
- package/README.md +42 -21
- package/README.zh-CN.md +50 -0
- package/dist/app.mjs +16 -28
- package/dist/config.mjs +51 -63
- package/dist/hmr-config.d.ts +2 -0
- package/dist/hmr-config.mjs +2 -0
- package/dist/hot-fix.d.ts +0 -0
- package/dist/hot-fix.mjs +44 -0
- package/dist/html-app.mjs +1 -1
- package/dist/pack.mjs +10 -6
- package/dist/utils/rsbuild.d.ts +2 -8
- package/dist/utils/rsbuild.mjs +7 -37
- package/package.json +13 -14
- package/src/app.ts +17 -28
- package/src/config.ts +62 -68
- package/src/hmr-config.ts +2 -0
- package/src/hot-fix.ts +51 -0
- package/src/html-app.ts +1 -1
- package/src/pack.ts +11 -7
- package/src/utils/rsbuild.ts +9 -38
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,29 +1,50 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="https://www.esmnext.com/logo.svg?t=2025" width="120" alt="Esmx Logo" />
|
|
3
|
+
<h1>@esmx/rspack</h1>
|
|
4
|
+
|
|
5
|
+
<div>
|
|
6
|
+
<a href="https://www.npmjs.com/package/@esmx/rspack">
|
|
7
|
+
<img src="https://img.shields.io/npm/v/@esmx/rspack.svg" alt="npm version" />
|
|
8
|
+
</a>
|
|
9
|
+
<a href="https://github.com/esmnext/esmx/actions/workflows/build.yml">
|
|
10
|
+
<img src="https://github.com/esmnext/esmx/actions/workflows/build.yml/badge.svg" alt="Build" />
|
|
11
|
+
</a>
|
|
12
|
+
<a href="https://www.esmnext.com/coverage/">
|
|
13
|
+
<img src="https://img.shields.io/badge/coverage-live%20report-brightgreen" alt="Coverage Report" />
|
|
14
|
+
</a>
|
|
15
|
+
<a href="https://nodejs.org/">
|
|
16
|
+
<img src="https://img.shields.io/node/v/@esmx/rspack.svg" alt="node version" />
|
|
17
|
+
</a>
|
|
18
|
+
<a href="https://bundlephobia.com/package/@esmx/rspack">
|
|
19
|
+
<img src="https://img.shields.io/bundlephobia/minzip/@esmx/rspack" alt="size" />
|
|
20
|
+
</a>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<p>A high-performance Rspack integration for Esmx microfrontend framework, providing module federation and SSR capabilities</p>
|
|
24
|
+
|
|
25
|
+
<p>
|
|
26
|
+
English | <a href="https://github.com/esmnext/esmx/blob/master/packages/rspack/README.zh-CN.md">中文</a>
|
|
27
|
+
</p>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
## 🚀 Features
|
|
31
|
+
|
|
32
|
+
- **High-Performance Build** - Ultra-fast building based on Rspack, providing excellent development experience
|
|
33
|
+
- **Application Support** - Complete support for standard applications and HTML applications development and building
|
|
34
|
+
- **Asset Processing** - Smart processing of various assets including JavaScript, CSS, images
|
|
35
|
+
- **SSR Support** - Built-in server-side rendering support for easy isomorphic application building
|
|
36
|
+
- **Developer Experience** - Supports hot reload, intelligent hints, and TypeScript
|
|
37
|
+
|
|
38
|
+
## 📦 Installation
|
|
14
39
|
|
|
15
40
|
```bash
|
|
16
|
-
pnpm add @esmx/rspack -D
|
|
17
|
-
# 或
|
|
18
|
-
yarn add @esmx/rspack -D
|
|
19
|
-
# 或
|
|
20
41
|
npm install @esmx/rspack -D
|
|
21
42
|
```
|
|
22
43
|
|
|
23
|
-
##
|
|
44
|
+
## 📚 Documentation
|
|
24
45
|
|
|
25
|
-
|
|
46
|
+
Visit the [official documentation](https://www.esmnext.com/api/app/rspack.html) for detailed usage guides and API reference.
|
|
26
47
|
|
|
27
|
-
##
|
|
48
|
+
## 📄 License
|
|
28
49
|
|
|
29
|
-
MIT
|
|
50
|
+
MIT © [Esmx Team](https://github.com/esmnext/esmx)
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="https://www.esmnext.com/logo.svg?t=2025" width="120" alt="Esmx Logo" />
|
|
3
|
+
<h1>@esmx/rspack</h1>
|
|
4
|
+
|
|
5
|
+
<div>
|
|
6
|
+
<a href="https://www.npmjs.com/package/@esmx/rspack">
|
|
7
|
+
<img src="https://img.shields.io/npm/v/@esmx/rspack.svg" alt="npm version" />
|
|
8
|
+
</a>
|
|
9
|
+
<a href="https://github.com/esmnext/esmx/actions/workflows/build.yml">
|
|
10
|
+
<img src="https://github.com/esmnext/esmx/actions/workflows/build.yml/badge.svg" alt="Build" />
|
|
11
|
+
</a>
|
|
12
|
+
<a href="https://www.esmnext.com/coverage/">
|
|
13
|
+
<img src="https://img.shields.io/badge/coverage-live%20report-brightgreen" alt="Coverage Report" />
|
|
14
|
+
</a>
|
|
15
|
+
<a href="https://nodejs.org/">
|
|
16
|
+
<img src="https://img.shields.io/node/v/@esmx/rspack.svg" alt="node version" />
|
|
17
|
+
</a>
|
|
18
|
+
<a href="https://bundlephobia.com/package/@esmx/rspack">
|
|
19
|
+
<img src="https://img.shields.io/bundlephobia/minzip/@esmx/rspack" alt="size" />
|
|
20
|
+
</a>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<p>为 Esmx 微前端框架提供的高性能 Rspack 集成,具备模块联邦和 SSR 能力</p>
|
|
24
|
+
|
|
25
|
+
<p>
|
|
26
|
+
<a href="https://github.com/esmnext/esmx/blob/master/packages/rspack/README.md">English</a> | 中文
|
|
27
|
+
</p>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
## 🚀 特性
|
|
31
|
+
|
|
32
|
+
- **高性能构建** - 基于 Rspack 的极速构建,为应用提供卓越的开发体验
|
|
33
|
+
- **应用支持** - 完整支持标准应用和 HTML 应用的开发与构建
|
|
34
|
+
- **资源处理** - 智能处理各类资源,支持 JavaScript、CSS、图片等
|
|
35
|
+
- **SSR 支持** - 内置服务端渲染支持,轻松构建同构应用
|
|
36
|
+
- **开发体验** - 支持热更新、智能提示和 TypeScript
|
|
37
|
+
|
|
38
|
+
## 📦 安装
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install @esmx/rspack -D
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 📚 文档
|
|
45
|
+
|
|
46
|
+
访问[官方文档](https://www.esmnext.com/api/app/rspack.html)获取详细的使用指南和 API 参考。
|
|
47
|
+
|
|
48
|
+
## 📄 许可证
|
|
49
|
+
|
|
50
|
+
MIT © [Esmx Team](https://github.com/esmnext/esmx)
|
package/dist/app.mjs
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
4
|
import {
|
|
5
|
-
PathType,
|
|
6
5
|
RenderContext,
|
|
7
6
|
createApp,
|
|
8
7
|
mergeMiddlewares
|
|
@@ -12,6 +11,11 @@ import hotMiddleware from "webpack-hot-middleware";
|
|
|
12
11
|
import { createRspackConfig } from "./config.mjs";
|
|
13
12
|
import { pack } from "./pack.mjs";
|
|
14
13
|
import { createRsBuild } from "./utils/index.mjs";
|
|
14
|
+
const extension = path.extname(fileURLToPath(import.meta.url));
|
|
15
|
+
const hotFixCode = fs.readFileSync(
|
|
16
|
+
fileURLToPath(new URL(`./hot-fix${extension}`, import.meta.url)),
|
|
17
|
+
"utf-8"
|
|
18
|
+
);
|
|
15
19
|
export async function createRspackApp(esmx, options) {
|
|
16
20
|
const app = await createApp(esmx, esmx.command);
|
|
17
21
|
switch (esmx.command) {
|
|
@@ -75,35 +79,19 @@ function rewriteRender(esmx) {
|
|
|
75
79
|
const serverRender = module[rc.entryName];
|
|
76
80
|
if (typeof serverRender === "function") {
|
|
77
81
|
await serverRender(rc);
|
|
82
|
+
rc.html = rc.html.replace(
|
|
83
|
+
"</head>",
|
|
84
|
+
`
|
|
85
|
+
<script type="module">${hotFixCode}<\/script>
|
|
86
|
+
</head>
|
|
87
|
+
`
|
|
88
|
+
);
|
|
78
89
|
}
|
|
79
90
|
return rc;
|
|
80
91
|
};
|
|
81
92
|
}
|
|
82
93
|
function rewriteBuild(esmx, options = {}) {
|
|
83
94
|
return async () => {
|
|
84
|
-
for (const item of esmx.moduleConfig.exports) {
|
|
85
|
-
if (item.type === PathType.root) {
|
|
86
|
-
const text = fs.readFileSync(
|
|
87
|
-
esmx.resolvePath("./", item.exportPath),
|
|
88
|
-
"utf-8"
|
|
89
|
-
);
|
|
90
|
-
if (/\bexport\s+\*\s+from\b/.test(text)) {
|
|
91
|
-
console.log(
|
|
92
|
-
styleText(
|
|
93
|
-
"red",
|
|
94
|
-
`The export * syntax is used in the file '${item.exportPath}', which will cause the packaging to fail.`
|
|
95
|
-
)
|
|
96
|
-
);
|
|
97
|
-
console.log(
|
|
98
|
-
styleText(
|
|
99
|
-
"red",
|
|
100
|
-
`Please use specific export syntax, such as export { a, b } from './a';`
|
|
101
|
-
)
|
|
102
|
-
);
|
|
103
|
-
return false;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
95
|
const ok = await createRsBuild([
|
|
108
96
|
generateBuildConfig(esmx, options, "client"),
|
|
109
97
|
generateBuildConfig(esmx, options, "server"),
|
|
@@ -113,10 +101,10 @@ function rewriteBuild(esmx, options = {}) {
|
|
|
113
101
|
return false;
|
|
114
102
|
}
|
|
115
103
|
esmx.writeSync(
|
|
116
|
-
esmx.resolvePath("dist/index.
|
|
104
|
+
esmx.resolvePath("dist/index.mjs"),
|
|
117
105
|
`
|
|
118
106
|
async function start() {
|
|
119
|
-
const options = await import('./node/src/entry.node.
|
|
107
|
+
const options = await import('./node/src/entry.node.mjs').then(
|
|
120
108
|
(mod) => mod.default
|
|
121
109
|
);
|
|
122
110
|
const { Esmx } = await import('@esmx/core');
|
package/dist/config.mjs
CHANGED
|
@@ -3,52 +3,26 @@ import {
|
|
|
3
3
|
rspack
|
|
4
4
|
} from "@rspack/core";
|
|
5
5
|
import nodeExternals from "webpack-node-externals";
|
|
6
|
+
import { HMR_DIR, HMR_JSONP } from "./hmr-config.mjs";
|
|
6
7
|
export function createRspackConfig(esmx, buildTarget, options) {
|
|
7
|
-
const isWebApp = buildTarget === "client" || buildTarget === "server";
|
|
8
8
|
const isHot = buildTarget === "client" && !esmx.isProd;
|
|
9
9
|
return {
|
|
10
10
|
/**
|
|
11
11
|
* 项目根目录,不可修改
|
|
12
12
|
*/
|
|
13
13
|
context: esmx.root,
|
|
14
|
-
entry: (() => {
|
|
15
|
-
const importPaths = [];
|
|
16
|
-
switch (buildTarget) {
|
|
17
|
-
case "client":
|
|
18
|
-
importPaths.push(esmx.resolvePath("src/entry.client.ts"));
|
|
19
|
-
isHot && importPaths.push(
|
|
20
|
-
`${resolve("webpack-hot-middleware/client")}?path=${esmx.basePath}hot-middleware&timeout=5000&overlay=false`
|
|
21
|
-
);
|
|
22
|
-
break;
|
|
23
|
-
case "server":
|
|
24
|
-
importPaths.push(esmx.resolvePath("src/entry.server.ts"));
|
|
25
|
-
break;
|
|
26
|
-
case "node":
|
|
27
|
-
importPaths.push(esmx.resolvePath("src/entry.node.ts"));
|
|
28
|
-
break;
|
|
29
|
-
}
|
|
30
|
-
return {
|
|
31
|
-
[`./src/entry.${buildTarget}`]: {
|
|
32
|
-
import: importPaths
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
})(),
|
|
36
14
|
output: {
|
|
37
15
|
clean: esmx.isProd,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
chunkLoading: esmx.isProd ? "import" : void 0,
|
|
41
|
-
chunkFilename: esmx.isProd ? "chunks/[name].[contenthash:8].final.js" : "chunks/[name].js",
|
|
42
|
-
library: {
|
|
43
|
-
type: esmx.isProd ? "modern-module" : "module"
|
|
44
|
-
},
|
|
45
|
-
filename: buildTarget !== "node" && esmx.isProd ? "[name].[contenthash:8].final.js" : "[name].js",
|
|
16
|
+
chunkFilename: esmx.isProd ? "[name].[contenthash:8].final.mjs" : "[name].mjs",
|
|
17
|
+
filename: buildTarget !== "node" && esmx.isProd ? "[name].[contenthash:8].final.mjs" : "[name].mjs",
|
|
46
18
|
cssFilename: esmx.isProd ? "[name].[contenthash:8].final.css" : "[name].css",
|
|
47
|
-
cssChunkFilename: esmx.isProd ? "
|
|
19
|
+
cssChunkFilename: esmx.isProd ? "[name].[contenthash:8].final.css" : "[name].css",
|
|
48
20
|
publicPath: buildTarget === "client" ? "auto" : `${esmx.basePathPlaceholder}${esmx.basePath}`,
|
|
49
21
|
uniqueName: esmx.varName,
|
|
50
|
-
|
|
51
|
-
|
|
22
|
+
hotUpdateGlobal: HMR_JSONP,
|
|
23
|
+
chunkLoadingGlobal: HMR_JSONP + "_chunk",
|
|
24
|
+
hotUpdateChunkFilename: `${HMR_DIR}/[id].[fullhash].hot-update.mjs`,
|
|
25
|
+
hotUpdateMainFilename: `${HMR_DIR}/[runtime].[fullhash].hot-update.json`,
|
|
52
26
|
path: (() => {
|
|
53
27
|
switch (buildTarget) {
|
|
54
28
|
case "client":
|
|
@@ -58,33 +32,23 @@ export function createRspackConfig(esmx, buildTarget, options) {
|
|
|
58
32
|
case "node":
|
|
59
33
|
return esmx.resolvePath("dist/node");
|
|
60
34
|
}
|
|
61
|
-
})()
|
|
62
|
-
environment: {
|
|
63
|
-
dynamicImport: true,
|
|
64
|
-
dynamicImportInWorker: true,
|
|
65
|
-
module: true,
|
|
66
|
-
nodePrefixForCoreModules: true
|
|
67
|
-
}
|
|
35
|
+
})()
|
|
68
36
|
},
|
|
69
|
-
// 默认插件,不可修改
|
|
70
37
|
plugins: (() => {
|
|
71
38
|
return [
|
|
72
|
-
// 进度条插件
|
|
73
39
|
new rspack.ProgressPlugin({
|
|
74
40
|
prefix: buildTarget
|
|
75
41
|
}),
|
|
76
|
-
|
|
77
|
-
isWebApp ? moduleLinkPlugin(esmx.moduleConfig) : false,
|
|
78
|
-
// 热更新插件
|
|
42
|
+
createModuleLinkPlugin(esmx, buildTarget),
|
|
79
43
|
isHot ? new rspack.HotModuleReplacementPlugin() : false
|
|
80
44
|
];
|
|
81
45
|
})(),
|
|
82
46
|
module: {
|
|
83
47
|
parser: {
|
|
84
48
|
javascript: {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
49
|
+
// DEV hot update fix
|
|
50
|
+
dynamicImportMode: esmx.isProd ? "lazy" : "eager",
|
|
51
|
+
url: buildTarget === "client" ? true : "relative"
|
|
88
52
|
}
|
|
89
53
|
},
|
|
90
54
|
generator: {
|
|
@@ -104,12 +68,11 @@ export function createRspackConfig(esmx, buildTarget, options) {
|
|
|
104
68
|
},
|
|
105
69
|
optimization: {
|
|
106
70
|
minimize: options.minimize ?? esmx.isProd,
|
|
107
|
-
avoidEntryIife: esmx.isProd,
|
|
108
|
-
concatenateModules: esmx.isProd,
|
|
109
71
|
emitOnErrors: true,
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
72
|
+
// DEV hot update fix
|
|
73
|
+
splitChunks: esmx.isProd ? void 0 : false,
|
|
74
|
+
// DEV hot update fix
|
|
75
|
+
runtimeChunk: esmx.isProd ? void 0 : false
|
|
113
76
|
},
|
|
114
77
|
externalsPresets: {
|
|
115
78
|
web: buildTarget === "client",
|
|
@@ -128,18 +91,43 @@ export function createRspackConfig(esmx, buildTarget, options) {
|
|
|
128
91
|
}
|
|
129
92
|
return [];
|
|
130
93
|
})(),
|
|
131
|
-
experiments: {
|
|
132
|
-
outputModule: true,
|
|
133
|
-
parallelCodeSplitting: true,
|
|
134
|
-
rspackFuture: {
|
|
135
|
-
bundlerInfo: { force: false }
|
|
136
|
-
}
|
|
137
|
-
},
|
|
138
94
|
target: buildTarget === "client" ? "web" : "node22.6",
|
|
139
95
|
mode: esmx.isProd ? "production" : "development",
|
|
140
96
|
cache: !esmx.isProd
|
|
141
97
|
};
|
|
142
98
|
}
|
|
143
|
-
function
|
|
144
|
-
|
|
99
|
+
function createModuleLinkPlugin(esmx, buildTarget) {
|
|
100
|
+
if (buildTarget === "node") {
|
|
101
|
+
return moduleLinkPlugin({
|
|
102
|
+
name: esmx.name,
|
|
103
|
+
exports: {
|
|
104
|
+
"src/entry.node": {
|
|
105
|
+
rewrite: false,
|
|
106
|
+
file: "./src/entry.node"
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
const exports = {};
|
|
112
|
+
for (const [name, item] of Object.entries(esmx.moduleConfig.exports)) {
|
|
113
|
+
if (item.inputTarget[buildTarget]) {
|
|
114
|
+
exports[name] = {
|
|
115
|
+
rewrite: item.rewrite,
|
|
116
|
+
file: item.inputTarget[buildTarget]
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const preEntries = [];
|
|
121
|
+
if (buildTarget === "client" && !esmx.isProd) {
|
|
122
|
+
preEntries.push(
|
|
123
|
+
`webpack-hot-middleware/client?path=/${esmx.name}/hot-middleware`
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
return moduleLinkPlugin({
|
|
127
|
+
name: esmx.name,
|
|
128
|
+
injectChunkName: buildTarget === "server",
|
|
129
|
+
imports: esmx.moduleConfig.imports,
|
|
130
|
+
exports,
|
|
131
|
+
preEntries
|
|
132
|
+
});
|
|
145
133
|
}
|
|
File without changes
|
package/dist/hot-fix.mjs
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
(() => {
|
|
2
|
+
const HMR_JSONP = "__esmx_rspack_hmr_jsonp__";
|
|
3
|
+
const HMR_JSONP_LIST = "__esmx_rspack_hmr_jsonp_list__";
|
|
4
|
+
const list = window[HMR_JSONP_LIST] = window[HMR_JSONP_LIST] || [];
|
|
5
|
+
Object.defineProperty(window, HMR_JSONP, {
|
|
6
|
+
get() {
|
|
7
|
+
return (...args) => {
|
|
8
|
+
const hotUrl = getStackUrl(new Error().stack || "", 1);
|
|
9
|
+
if (hotUrl) {
|
|
10
|
+
const item = list.find(
|
|
11
|
+
(item2) => isSameModule(hotUrl, item2.url)
|
|
12
|
+
);
|
|
13
|
+
if (item) {
|
|
14
|
+
return item.jsonp(...args);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
console.log("%chot update not found", "color: red", args);
|
|
18
|
+
};
|
|
19
|
+
},
|
|
20
|
+
set(jsonp) {
|
|
21
|
+
const url = getStackUrl(new Error().stack || "", 1);
|
|
22
|
+
if (url) {
|
|
23
|
+
list.push({ url, jsonp });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
function isSameModule(hotUrl, originalUrl) {
|
|
28
|
+
const normalizedHotUrl = hotUrl.replace(/\/__hot__\//, "/").replace(/\.\w+\.hot-update\.mjs$/, ".mjs");
|
|
29
|
+
const normalizedOriginalUrl = originalUrl;
|
|
30
|
+
return normalizedHotUrl === normalizedOriginalUrl;
|
|
31
|
+
}
|
|
32
|
+
function getStackUrl(stack, index = 0) {
|
|
33
|
+
const lines = stack.split("\n");
|
|
34
|
+
const stackLines = lines.filter((line2) => line2.includes("at "));
|
|
35
|
+
if (index < 0 || index >= stackLines.length) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const line = stackLines[index];
|
|
39
|
+
const withoutAt = line.replace(/^\s*at\s+/, "");
|
|
40
|
+
const urlMatch = withoutAt.match(/\((.*?)\)/);
|
|
41
|
+
const url = urlMatch ? urlMatch[1] : withoutAt;
|
|
42
|
+
return url.replace(/:\d+:\d+$/, "");
|
|
43
|
+
}
|
|
44
|
+
})();
|
package/dist/html-app.mjs
CHANGED
|
@@ -10,7 +10,7 @@ export async function createRspackHtmlApp(esmx, options) {
|
|
|
10
10
|
options = {
|
|
11
11
|
...options,
|
|
12
12
|
target: {
|
|
13
|
-
web: ["chrome>=
|
|
13
|
+
web: ["chrome>=63", "firefox>=67", "safari>=11.1"],
|
|
14
14
|
node: ["node>=22.6"],
|
|
15
15
|
...options?.target
|
|
16
16
|
},
|
package/dist/pack.mjs
CHANGED
|
@@ -30,8 +30,12 @@ export async function pack(esmx) {
|
|
|
30
30
|
}
|
|
31
31
|
async function buildPackageJson(esmx) {
|
|
32
32
|
const [clientJson, serverJson, curJson] = await Promise.all([
|
|
33
|
-
esmx.readJson(
|
|
34
|
-
|
|
33
|
+
esmx.readJson(
|
|
34
|
+
esmx.resolvePath("dist/client/manifest.json")
|
|
35
|
+
),
|
|
36
|
+
esmx.readJson(
|
|
37
|
+
esmx.resolvePath("dist/server/manifest.json")
|
|
38
|
+
),
|
|
35
39
|
esmx.readJson(esmx.resolvePath("package.json"))
|
|
36
40
|
]);
|
|
37
41
|
const exports = {
|
|
@@ -47,13 +51,13 @@ async function buildPackageJson(esmx) {
|
|
|
47
51
|
const exportName = `./${name}`;
|
|
48
52
|
if (client && server) {
|
|
49
53
|
exports[exportName] = {
|
|
50
|
-
default: `./server/${server}`,
|
|
51
|
-
browser: `./client/${client}`
|
|
54
|
+
default: `./server/${server.file}`,
|
|
55
|
+
browser: `./client/${client.file}`
|
|
52
56
|
};
|
|
53
57
|
} else if (client) {
|
|
54
|
-
exports[exportName] = `./client/${client}`;
|
|
58
|
+
exports[exportName] = `./client/${client.file}`;
|
|
55
59
|
} else if (server) {
|
|
56
|
-
exports[exportName] = `./server/${server}`;
|
|
60
|
+
exports[exportName] = `./server/${server.file}`;
|
|
57
61
|
}
|
|
58
62
|
});
|
|
59
63
|
const buildJson = {
|
package/dist/utils/rsbuild.d.ts
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type RspackOptions } from '@rspack/core';
|
|
2
2
|
export declare function createRsBuild(options: RspackOptions[]): {
|
|
3
|
-
readonly compilers: Compiler[];
|
|
3
|
+
readonly compilers: import("@rspack/core").Compiler[];
|
|
4
4
|
build(): Promise<boolean>;
|
|
5
5
|
watch(): void;
|
|
6
6
|
};
|
|
7
|
-
export declare class RsBuild {
|
|
8
|
-
private compiler;
|
|
9
|
-
constructor(options: RspackOptions);
|
|
10
|
-
build(): Promise<boolean>;
|
|
11
|
-
watch(): void;
|
|
12
|
-
}
|
package/dist/utils/rsbuild.mjs
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { styleText } from "node:util";
|
|
2
2
|
import { rspack } from "@rspack/core";
|
|
3
|
+
function showError(message) {
|
|
4
|
+
console.error(styleText("red", message));
|
|
5
|
+
}
|
|
3
6
|
export function createRsBuild(options) {
|
|
4
7
|
const multiCompiler = rspack(options);
|
|
5
8
|
return {
|
|
@@ -10,17 +13,18 @@ export function createRsBuild(options) {
|
|
|
10
13
|
return new Promise((resolve) => {
|
|
11
14
|
multiCompiler.run((err, stats) => {
|
|
12
15
|
if (err) {
|
|
16
|
+
showError(err.message);
|
|
13
17
|
return resolve(false);
|
|
14
18
|
}
|
|
15
19
|
if (stats?.hasErrors()) {
|
|
16
20
|
stats.toJson({ errors: true })?.errors?.forEach((err2) => {
|
|
17
|
-
|
|
21
|
+
showError(err2.message);
|
|
18
22
|
});
|
|
19
23
|
return resolve(false);
|
|
20
24
|
}
|
|
21
25
|
multiCompiler.close((err2) => {
|
|
22
26
|
if (err2) {
|
|
23
|
-
|
|
27
|
+
showError(err2.message);
|
|
24
28
|
return resolve(false);
|
|
25
29
|
}
|
|
26
30
|
process.nextTick(() => {
|
|
@@ -33,7 +37,7 @@ export function createRsBuild(options) {
|
|
|
33
37
|
watch() {
|
|
34
38
|
const watching = multiCompiler.watch({}, (err, stats) => {
|
|
35
39
|
if (err) {
|
|
36
|
-
console.
|
|
40
|
+
console.log(styleText("red", err.message));
|
|
37
41
|
return;
|
|
38
42
|
}
|
|
39
43
|
if (stats?.hasErrors()) {
|
|
@@ -61,37 +65,3 @@ export function createRsBuild(options) {
|
|
|
61
65
|
}
|
|
62
66
|
};
|
|
63
67
|
}
|
|
64
|
-
export class RsBuild {
|
|
65
|
-
compiler;
|
|
66
|
-
constructor(options) {
|
|
67
|
-
this.compiler = rspack(options);
|
|
68
|
-
}
|
|
69
|
-
async build() {
|
|
70
|
-
return new Promise((resolve) => {
|
|
71
|
-
this.compiler.run((err, stats) => {
|
|
72
|
-
if (err) {
|
|
73
|
-
return resolve(false);
|
|
74
|
-
}
|
|
75
|
-
if (stats?.hasErrors()) {
|
|
76
|
-
stats.toJson({ errors: true })?.errors?.forEach((err2) => {
|
|
77
|
-
console.error(err2);
|
|
78
|
-
});
|
|
79
|
-
return resolve(false);
|
|
80
|
-
}
|
|
81
|
-
this.compiler.close((err2) => {
|
|
82
|
-
if (err2) {
|
|
83
|
-
console.error(err2);
|
|
84
|
-
return resolve(false);
|
|
85
|
-
}
|
|
86
|
-
process.nextTick(() => {
|
|
87
|
-
resolve(true);
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
watch() {
|
|
94
|
-
const watching = this.compiler.watch({}, () => {
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
}
|
package/package.json
CHANGED
|
@@ -63,10 +63,10 @@
|
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"@esmx/import": "3.0.0-rc.
|
|
67
|
-
"@esmx/rspack-module-link-plugin": "3.0.0-rc.
|
|
66
|
+
"@esmx/import": "3.0.0-rc.20",
|
|
67
|
+
"@esmx/rspack-module-link-plugin": "3.0.0-rc.20",
|
|
68
68
|
"@npmcli/arborist": "^9.0.1",
|
|
69
|
-
"@rspack/core": "1.
|
|
69
|
+
"@rspack/core": "1.4.0",
|
|
70
70
|
"css-loader": "^7.1.2",
|
|
71
71
|
"less-loader": "^12.2.0",
|
|
72
72
|
"node-polyfill-webpack-plugin": "^4.1.0",
|
|
@@ -79,21 +79,20 @@
|
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
81
|
"@biomejs/biome": "1.9.4",
|
|
82
|
-
"@esmx/core": "3.0.0-rc.
|
|
83
|
-
"@esmx/lint": "3.0.0-rc.
|
|
84
|
-
"@
|
|
85
|
-
"@types/
|
|
86
|
-
"@types/npmcli__arborist": "^5.6.11",
|
|
82
|
+
"@esmx/core": "3.0.0-rc.20",
|
|
83
|
+
"@esmx/lint": "3.0.0-rc.20",
|
|
84
|
+
"@types/node": "22.15.18",
|
|
85
|
+
"@types/npmcli__arborist": "^6.3.1",
|
|
87
86
|
"@types/pacote": "^11.1.8",
|
|
88
87
|
"@types/webpack-hot-middleware": "^2.25.9",
|
|
89
88
|
"@types/webpack-node-externals": "^3.0.4",
|
|
90
|
-
"@vitest/coverage-v8": "3.
|
|
91
|
-
"stylelint": "16.
|
|
89
|
+
"@vitest/coverage-v8": "3.1.3",
|
|
90
|
+
"stylelint": "16.19.1",
|
|
92
91
|
"typescript": "5.8.2",
|
|
93
|
-
"unbuild": "
|
|
94
|
-
"vitest": "3.
|
|
92
|
+
"unbuild": "3.5.0",
|
|
93
|
+
"vitest": "3.1.3"
|
|
95
94
|
},
|
|
96
|
-
"version": "3.0.0-rc.
|
|
95
|
+
"version": "3.0.0-rc.20",
|
|
97
96
|
"type": "module",
|
|
98
97
|
"private": false,
|
|
99
98
|
"exports": {
|
|
@@ -112,5 +111,5 @@
|
|
|
112
111
|
"template",
|
|
113
112
|
"public"
|
|
114
113
|
],
|
|
115
|
-
"gitHead": "
|
|
114
|
+
"gitHead": "4c6490c23cbc148cb189b3f2cdae930eed901607"
|
|
116
115
|
}
|
package/src/app.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
4
4
|
import {
|
|
5
5
|
type App,
|
|
6
6
|
type Esmx,
|
|
7
7
|
type Middleware,
|
|
8
|
-
PathType,
|
|
9
8
|
RenderContext,
|
|
10
9
|
type RenderContextOptions,
|
|
11
10
|
type ServerRenderHandle,
|
|
@@ -20,6 +19,12 @@ import { createRspackConfig } from './config';
|
|
|
20
19
|
import { pack } from './pack';
|
|
21
20
|
import { createRsBuild } from './utils';
|
|
22
21
|
|
|
22
|
+
const extension = path.extname(fileURLToPath(import.meta.url));
|
|
23
|
+
const hotFixCode = fs.readFileSync(
|
|
24
|
+
fileURLToPath(new URL(`./hot-fix${extension}`, import.meta.url)),
|
|
25
|
+
'utf-8'
|
|
26
|
+
);
|
|
27
|
+
|
|
23
28
|
/**
|
|
24
29
|
* Rspack 应用配置上下文接口。
|
|
25
30
|
*
|
|
@@ -263,6 +268,13 @@ function rewriteRender(esmx: Esmx) {
|
|
|
263
268
|
const serverRender: ServerRenderHandle = module[rc.entryName];
|
|
264
269
|
if (typeof serverRender === 'function') {
|
|
265
270
|
await serverRender(rc);
|
|
271
|
+
rc.html = rc.html.replace(
|
|
272
|
+
'</head>',
|
|
273
|
+
`
|
|
274
|
+
<script type="module">${hotFixCode}</script>
|
|
275
|
+
</head>
|
|
276
|
+
`
|
|
277
|
+
);
|
|
266
278
|
}
|
|
267
279
|
return rc;
|
|
268
280
|
};
|
|
@@ -270,29 +282,6 @@ function rewriteRender(esmx: Esmx) {
|
|
|
270
282
|
|
|
271
283
|
function rewriteBuild(esmx: Esmx, options: RspackAppOptions = {}) {
|
|
272
284
|
return async (): Promise<boolean> => {
|
|
273
|
-
for (const item of esmx.moduleConfig.exports) {
|
|
274
|
-
if (item.type === PathType.root) {
|
|
275
|
-
const text = fs.readFileSync(
|
|
276
|
-
esmx.resolvePath('./', item.exportPath),
|
|
277
|
-
'utf-8'
|
|
278
|
-
);
|
|
279
|
-
if (/\bexport\s+\*\s+from\b/.test(text)) {
|
|
280
|
-
console.log(
|
|
281
|
-
styleText(
|
|
282
|
-
'red',
|
|
283
|
-
`The export * syntax is used in the file '${item.exportPath}', which will cause the packaging to fail.`
|
|
284
|
-
)
|
|
285
|
-
);
|
|
286
|
-
console.log(
|
|
287
|
-
styleText(
|
|
288
|
-
'red',
|
|
289
|
-
`Please use specific export syntax, such as export { a, b } from './a';`
|
|
290
|
-
)
|
|
291
|
-
);
|
|
292
|
-
return false;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
285
|
const ok = await createRsBuild([
|
|
297
286
|
generateBuildConfig(esmx, options, 'client'),
|
|
298
287
|
generateBuildConfig(esmx, options, 'server'),
|
|
@@ -302,10 +291,10 @@ function rewriteBuild(esmx: Esmx, options: RspackAppOptions = {}) {
|
|
|
302
291
|
return false;
|
|
303
292
|
}
|
|
304
293
|
esmx.writeSync(
|
|
305
|
-
esmx.resolvePath('dist/index.
|
|
294
|
+
esmx.resolvePath('dist/index.mjs'),
|
|
306
295
|
`
|
|
307
296
|
async function start() {
|
|
308
|
-
const options = await import('./node/src/entry.node.
|
|
297
|
+
const options = await import('./node/src/entry.node.mjs').then(
|
|
309
298
|
(mod) => mod.default
|
|
310
299
|
);
|
|
311
300
|
const { Esmx } = await import('@esmx/core');
|
package/src/config.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { Esmx } from '@esmx/core';
|
|
|
2
2
|
import { moduleLinkPlugin } from '@esmx/rspack-module-link-plugin';
|
|
3
3
|
import {
|
|
4
4
|
type ExternalItem,
|
|
5
|
+
type Plugin,
|
|
5
6
|
type Plugins,
|
|
6
7
|
type RspackOptions,
|
|
7
8
|
rspack
|
|
@@ -9,6 +10,7 @@ import {
|
|
|
9
10
|
import nodeExternals from 'webpack-node-externals';
|
|
10
11
|
import type { RspackAppOptions } from './app';
|
|
11
12
|
import type { BuildTarget } from './build-target';
|
|
13
|
+
import { HMR_DIR, HMR_JSONP } from './hmr-config';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* 构建 Client、Server、Node 的基础配置
|
|
@@ -18,65 +20,36 @@ export function createRspackConfig(
|
|
|
18
20
|
buildTarget: BuildTarget,
|
|
19
21
|
options: RspackAppOptions
|
|
20
22
|
): RspackOptions {
|
|
21
|
-
const isWebApp = buildTarget === 'client' || buildTarget === 'server';
|
|
22
23
|
const isHot = buildTarget === 'client' && !esmx.isProd;
|
|
23
24
|
return {
|
|
24
25
|
/**
|
|
25
26
|
* 项目根目录,不可修改
|
|
26
27
|
*/
|
|
27
28
|
context: esmx.root,
|
|
28
|
-
entry: (() => {
|
|
29
|
-
const importPaths: string[] = [];
|
|
30
|
-
switch (buildTarget) {
|
|
31
|
-
case 'client':
|
|
32
|
-
importPaths.push(esmx.resolvePath('src/entry.client.ts'));
|
|
33
|
-
isHot &&
|
|
34
|
-
importPaths.push(
|
|
35
|
-
`${resolve('webpack-hot-middleware/client')}?path=${esmx.basePath}hot-middleware&timeout=5000&overlay=false`
|
|
36
|
-
);
|
|
37
|
-
break;
|
|
38
|
-
case 'server':
|
|
39
|
-
importPaths.push(esmx.resolvePath('src/entry.server.ts'));
|
|
40
|
-
break;
|
|
41
|
-
case 'node':
|
|
42
|
-
importPaths.push(esmx.resolvePath('src/entry.node.ts'));
|
|
43
|
-
break;
|
|
44
|
-
}
|
|
45
|
-
return {
|
|
46
|
-
[`./src/entry.${buildTarget}`]: {
|
|
47
|
-
import: importPaths
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
})(),
|
|
51
29
|
output: {
|
|
52
30
|
clean: esmx.isProd,
|
|
53
|
-
module: true,
|
|
54
|
-
chunkFormat: esmx.isProd ? 'module' : undefined,
|
|
55
|
-
chunkLoading: esmx.isProd ? 'import' : undefined,
|
|
56
31
|
chunkFilename: esmx.isProd
|
|
57
|
-
? '
|
|
58
|
-
: '
|
|
59
|
-
library: {
|
|
60
|
-
type: esmx.isProd ? 'modern-module' : 'module'
|
|
61
|
-
},
|
|
32
|
+
? '[name].[contenthash:8].final.mjs'
|
|
33
|
+
: '[name].mjs',
|
|
62
34
|
filename:
|
|
63
35
|
buildTarget !== 'node' && esmx.isProd
|
|
64
|
-
? '[name].[contenthash:8].final.
|
|
65
|
-
: '[name].
|
|
36
|
+
? '[name].[contenthash:8].final.mjs'
|
|
37
|
+
: '[name].mjs',
|
|
66
38
|
cssFilename: esmx.isProd
|
|
67
39
|
? '[name].[contenthash:8].final.css'
|
|
68
40
|
: '[name].css',
|
|
69
41
|
cssChunkFilename: esmx.isProd
|
|
70
|
-
? '
|
|
71
|
-
: '
|
|
42
|
+
? '[name].[contenthash:8].final.css'
|
|
43
|
+
: '[name].css',
|
|
72
44
|
publicPath:
|
|
73
45
|
buildTarget === 'client'
|
|
74
46
|
? 'auto'
|
|
75
47
|
: `${esmx.basePathPlaceholder}${esmx.basePath}`,
|
|
76
48
|
uniqueName: esmx.varName,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
49
|
+
hotUpdateGlobal: HMR_JSONP,
|
|
50
|
+
chunkLoadingGlobal: HMR_JSONP + '_chunk',
|
|
51
|
+
hotUpdateChunkFilename: `${HMR_DIR}/[id].[fullhash].hot-update.mjs`,
|
|
52
|
+
hotUpdateMainFilename: `${HMR_DIR}/[runtime].[fullhash].hot-update.json`,
|
|
80
53
|
path: ((): string => {
|
|
81
54
|
switch (buildTarget) {
|
|
82
55
|
case 'client':
|
|
@@ -86,33 +59,23 @@ export function createRspackConfig(
|
|
|
86
59
|
case 'node':
|
|
87
60
|
return esmx.resolvePath('dist/node');
|
|
88
61
|
}
|
|
89
|
-
})()
|
|
90
|
-
environment: {
|
|
91
|
-
dynamicImport: true,
|
|
92
|
-
dynamicImportInWorker: true,
|
|
93
|
-
module: true,
|
|
94
|
-
nodePrefixForCoreModules: true
|
|
95
|
-
}
|
|
62
|
+
})()
|
|
96
63
|
},
|
|
97
|
-
// 默认插件,不可修改
|
|
98
64
|
plugins: ((): Plugins => {
|
|
99
65
|
return [
|
|
100
|
-
// 进度条插件
|
|
101
66
|
new rspack.ProgressPlugin({
|
|
102
67
|
prefix: buildTarget
|
|
103
68
|
}),
|
|
104
|
-
|
|
105
|
-
isWebApp ? moduleLinkPlugin(esmx.moduleConfig) : false,
|
|
106
|
-
// 热更新插件
|
|
69
|
+
createModuleLinkPlugin(esmx, buildTarget),
|
|
107
70
|
isHot ? new rspack.HotModuleReplacementPlugin() : false
|
|
108
71
|
];
|
|
109
72
|
})(),
|
|
110
73
|
module: {
|
|
111
74
|
parser: {
|
|
112
75
|
javascript: {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
76
|
+
// DEV hot update fix
|
|
77
|
+
dynamicImportMode: esmx.isProd ? 'lazy' : 'eager',
|
|
78
|
+
url: buildTarget === 'client' ? true : 'relative'
|
|
116
79
|
}
|
|
117
80
|
},
|
|
118
81
|
generator: {
|
|
@@ -132,12 +95,11 @@ export function createRspackConfig(
|
|
|
132
95
|
},
|
|
133
96
|
optimization: {
|
|
134
97
|
minimize: options.minimize ?? esmx.isProd,
|
|
135
|
-
avoidEntryIife: esmx.isProd,
|
|
136
|
-
concatenateModules: esmx.isProd,
|
|
137
98
|
emitOnErrors: true,
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
99
|
+
// DEV hot update fix
|
|
100
|
+
splitChunks: esmx.isProd ? undefined : false,
|
|
101
|
+
// DEV hot update fix
|
|
102
|
+
runtimeChunk: esmx.isProd ? undefined : false
|
|
141
103
|
},
|
|
142
104
|
externalsPresets: {
|
|
143
105
|
web: buildTarget === 'client',
|
|
@@ -156,19 +118,51 @@ export function createRspackConfig(
|
|
|
156
118
|
}
|
|
157
119
|
return [];
|
|
158
120
|
})(),
|
|
159
|
-
experiments: {
|
|
160
|
-
outputModule: true,
|
|
161
|
-
parallelCodeSplitting: true,
|
|
162
|
-
rspackFuture: {
|
|
163
|
-
bundlerInfo: { force: false }
|
|
164
|
-
}
|
|
165
|
-
},
|
|
166
121
|
target: buildTarget === 'client' ? 'web' : 'node22.6',
|
|
167
122
|
mode: esmx.isProd ? 'production' : 'development',
|
|
168
123
|
cache: !esmx.isProd
|
|
169
124
|
};
|
|
170
125
|
}
|
|
171
126
|
|
|
172
|
-
function
|
|
173
|
-
|
|
127
|
+
function createModuleLinkPlugin(esmx: Esmx, buildTarget: BuildTarget): Plugin {
|
|
128
|
+
if (buildTarget === 'node') {
|
|
129
|
+
return moduleLinkPlugin({
|
|
130
|
+
name: esmx.name,
|
|
131
|
+
exports: {
|
|
132
|
+
'src/entry.node': {
|
|
133
|
+
rewrite: false,
|
|
134
|
+
file: './src/entry.node'
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
const exports: Record<
|
|
140
|
+
string,
|
|
141
|
+
{
|
|
142
|
+
rewrite: boolean;
|
|
143
|
+
file: string;
|
|
144
|
+
}
|
|
145
|
+
> = {};
|
|
146
|
+
for (const [name, item] of Object.entries(esmx.moduleConfig.exports)) {
|
|
147
|
+
if (item.inputTarget[buildTarget]) {
|
|
148
|
+
exports[name] = {
|
|
149
|
+
rewrite: item.rewrite,
|
|
150
|
+
file: item.inputTarget[buildTarget]
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const preEntries: string[] = [];
|
|
155
|
+
if (buildTarget === 'client' && !esmx.isProd) {
|
|
156
|
+
preEntries.push(
|
|
157
|
+
`webpack-hot-middleware/client?path=/${esmx.name}/hot-middleware`
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return moduleLinkPlugin({
|
|
162
|
+
name: esmx.name,
|
|
163
|
+
injectChunkName: buildTarget === 'server',
|
|
164
|
+
imports: esmx.moduleConfig.imports,
|
|
165
|
+
exports,
|
|
166
|
+
preEntries
|
|
167
|
+
});
|
|
174
168
|
}
|
package/src/hot-fix.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
(() => {
|
|
2
|
+
const HMR_JSONP = '__esmx_rspack_hmr_jsonp__';
|
|
3
|
+
const HMR_JSONP_LIST = '__esmx_rspack_hmr_jsonp_list__';
|
|
4
|
+
|
|
5
|
+
const list: Array<{ url: string; jsonp: Function }> = (window[
|
|
6
|
+
HMR_JSONP_LIST
|
|
7
|
+
] = window[HMR_JSONP_LIST] || []);
|
|
8
|
+
|
|
9
|
+
Object.defineProperty(window, HMR_JSONP, {
|
|
10
|
+
get() {
|
|
11
|
+
return (...args: any[]) => {
|
|
12
|
+
const hotUrl = getStackUrl(new Error().stack || '', 1);
|
|
13
|
+
if (hotUrl) {
|
|
14
|
+
const item = list.find((item) =>
|
|
15
|
+
isSameModule(hotUrl, item.url)
|
|
16
|
+
);
|
|
17
|
+
if (item) {
|
|
18
|
+
return item.jsonp(...args);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
console.log('%chot update not found', 'color: red', args);
|
|
22
|
+
};
|
|
23
|
+
},
|
|
24
|
+
set(jsonp) {
|
|
25
|
+
const url = getStackUrl(new Error().stack || '', 1);
|
|
26
|
+
if (url) {
|
|
27
|
+
list.push({ url, jsonp });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
function isSameModule(hotUrl: string, originalUrl: string): boolean {
|
|
32
|
+
const normalizedHotUrl = hotUrl
|
|
33
|
+
.replace(/\/__hot__\//, '/')
|
|
34
|
+
.replace(/\.\w+\.hot-update\.mjs$/, '.mjs');
|
|
35
|
+
const normalizedOriginalUrl = originalUrl;
|
|
36
|
+
return normalizedHotUrl === normalizedOriginalUrl;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getStackUrl(stack: string, index = 0): string | null {
|
|
40
|
+
const lines = stack.split('\n');
|
|
41
|
+
const stackLines = lines.filter((line) => line.includes('at '));
|
|
42
|
+
if (index < 0 || index >= stackLines.length) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
const line = stackLines[index];
|
|
46
|
+
const withoutAt = line.replace(/^\s*at\s+/, '');
|
|
47
|
+
const urlMatch = withoutAt.match(/\((.*?)\)/);
|
|
48
|
+
const url = urlMatch ? urlMatch[1] : withoutAt;
|
|
49
|
+
return url.replace(/:\d+:\d+$/, '');
|
|
50
|
+
}
|
|
51
|
+
})();
|
package/src/html-app.ts
CHANGED
|
@@ -326,7 +326,7 @@ export async function createRspackHtmlApp(
|
|
|
326
326
|
options = {
|
|
327
327
|
...options,
|
|
328
328
|
target: {
|
|
329
|
-
web: ['chrome>=
|
|
329
|
+
web: ['chrome>=63', 'firefox>=67', 'safari>=11.1'],
|
|
330
330
|
node: ['node>=22.6'],
|
|
331
331
|
...options?.target
|
|
332
332
|
},
|
package/src/pack.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import crypto from 'node:crypto';
|
|
2
|
-
import type { Esmx } from '@esmx/core';
|
|
2
|
+
import type { Esmx, ManifestJson } from '@esmx/core';
|
|
3
3
|
import Arborist from '@npmcli/arborist';
|
|
4
4
|
import pacote from 'pacote';
|
|
5
5
|
|
|
@@ -38,8 +38,12 @@ export async function pack(esmx: Esmx): Promise<boolean> {
|
|
|
38
38
|
|
|
39
39
|
async function buildPackageJson(esmx: Esmx): Promise<Record<string, any>> {
|
|
40
40
|
const [clientJson, serverJson, curJson] = await Promise.all([
|
|
41
|
-
esmx.readJson(
|
|
42
|
-
|
|
41
|
+
esmx.readJson<ManifestJson>(
|
|
42
|
+
esmx.resolvePath('dist/client/manifest.json')
|
|
43
|
+
),
|
|
44
|
+
esmx.readJson<ManifestJson>(
|
|
45
|
+
esmx.resolvePath('dist/server/manifest.json')
|
|
46
|
+
),
|
|
43
47
|
esmx.readJson(esmx.resolvePath('package.json'))
|
|
44
48
|
]);
|
|
45
49
|
const exports: Record<string, any> = {
|
|
@@ -55,13 +59,13 @@ async function buildPackageJson(esmx: Esmx): Promise<Record<string, any>> {
|
|
|
55
59
|
const exportName = `./${name}`;
|
|
56
60
|
if (client && server) {
|
|
57
61
|
exports[exportName] = {
|
|
58
|
-
default: `./server/${server}`,
|
|
59
|
-
browser: `./client/${client}`
|
|
62
|
+
default: `./server/${server.file}`,
|
|
63
|
+
browser: `./client/${client.file}`
|
|
60
64
|
};
|
|
61
65
|
} else if (client) {
|
|
62
|
-
exports[exportName] = `./client/${client}`;
|
|
66
|
+
exports[exportName] = `./client/${client.file}`;
|
|
63
67
|
} else if (server) {
|
|
64
|
-
exports[exportName] = `./server/${server}`;
|
|
68
|
+
exports[exportName] = `./server/${server.file}`;
|
|
65
69
|
}
|
|
66
70
|
});
|
|
67
71
|
|
package/src/utils/rsbuild.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { styleText } from 'node:util';
|
|
2
|
-
import { type
|
|
2
|
+
import { type RspackOptions, rspack } from '@rspack/core';
|
|
3
|
+
|
|
4
|
+
function showError(message: string) {
|
|
5
|
+
console.error(styleText('red', message));
|
|
6
|
+
}
|
|
3
7
|
|
|
4
8
|
export function createRsBuild(options: RspackOptions[]) {
|
|
5
9
|
const multiCompiler = rspack(options);
|
|
@@ -11,19 +15,20 @@ export function createRsBuild(options: RspackOptions[]) {
|
|
|
11
15
|
return new Promise<boolean>((resolve) => {
|
|
12
16
|
multiCompiler.run((err, stats) => {
|
|
13
17
|
if (err) {
|
|
18
|
+
showError(err.message);
|
|
14
19
|
return resolve(false);
|
|
15
20
|
}
|
|
16
21
|
if (stats?.hasErrors()) {
|
|
17
22
|
stats
|
|
18
23
|
.toJson({ errors: true })
|
|
19
24
|
?.errors?.forEach((err) => {
|
|
20
|
-
|
|
25
|
+
showError(err.message);
|
|
21
26
|
});
|
|
22
27
|
return resolve(false);
|
|
23
28
|
}
|
|
24
29
|
multiCompiler.close((err) => {
|
|
25
30
|
if (err) {
|
|
26
|
-
|
|
31
|
+
showError(err.message);
|
|
27
32
|
return resolve(false);
|
|
28
33
|
}
|
|
29
34
|
process.nextTick(() => {
|
|
@@ -36,7 +41,7 @@ export function createRsBuild(options: RspackOptions[]) {
|
|
|
36
41
|
watch() {
|
|
37
42
|
const watching = multiCompiler.watch({}, (err, stats) => {
|
|
38
43
|
if (err) {
|
|
39
|
-
console.
|
|
44
|
+
console.log(styleText('red', err.message));
|
|
40
45
|
return;
|
|
41
46
|
}
|
|
42
47
|
if (stats?.hasErrors()) {
|
|
@@ -69,37 +74,3 @@ export function createRsBuild(options: RspackOptions[]) {
|
|
|
69
74
|
}
|
|
70
75
|
};
|
|
71
76
|
}
|
|
72
|
-
|
|
73
|
-
export class RsBuild {
|
|
74
|
-
private compiler: Compiler;
|
|
75
|
-
public constructor(options: RspackOptions) {
|
|
76
|
-
this.compiler = rspack(options);
|
|
77
|
-
}
|
|
78
|
-
public async build() {
|
|
79
|
-
return new Promise<boolean>((resolve) => {
|
|
80
|
-
this.compiler.run((err, stats) => {
|
|
81
|
-
if (err) {
|
|
82
|
-
return resolve(false);
|
|
83
|
-
}
|
|
84
|
-
if (stats?.hasErrors()) {
|
|
85
|
-
stats.toJson({ errors: true })?.errors?.forEach((err) => {
|
|
86
|
-
console.error(err);
|
|
87
|
-
});
|
|
88
|
-
return resolve(false);
|
|
89
|
-
}
|
|
90
|
-
this.compiler.close((err) => {
|
|
91
|
-
if (err) {
|
|
92
|
-
console.error(err);
|
|
93
|
-
return resolve(false);
|
|
94
|
-
}
|
|
95
|
-
process.nextTick(() => {
|
|
96
|
-
resolve(true);
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
public watch() {
|
|
103
|
-
const watching = this.compiler.watch({}, () => {});
|
|
104
|
-
}
|
|
105
|
-
}
|