@esmx/rspack 3.0.0-rc.18 → 3.0.0-rc.19

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2020 Vanelink
3
+ Copyright (c) 2020 Esmx Team
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,29 +1,50 @@
1
- # @esmx/rspack
2
-
3
- 基于 Rspack 提供高性能的构建能力,支持标准应用和 HTML 应用的开发与构建。
4
-
5
- ## 特性
6
-
7
- - 🚀 **高性能构建** - 基于 Rspack 的极速构建,为应用提供卓越的开发体验
8
- - 💡 **应用支持** - 完整支持标准应用和 HTML 应用的开发与构建
9
- - 🎨 **资源处理** - 智能处理各类资源,支持 JavaScript、CSS、图片等
10
- - 🛠️ **SSR 支持** - 内置服务端渲染支持,轻松构建同构应用
11
- - 🔧 **开发体验** - 支持热更新、智能提示和 TypeScript
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
- 访问 [@esmx/rspack 官方文档](https://www.esmnext.com/api/app/rspack.html) 获取详细的使用指南和 API 文档。
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)
@@ -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,5 @@
1
- import fs from "node:fs";
2
1
  import { pathToFileURL } from "node:url";
3
- import { styleText } from "node:util";
4
2
  import {
5
- PathType,
6
3
  RenderContext,
7
4
  createApp,
8
5
  mergeMiddlewares
@@ -81,29 +78,6 @@ function rewriteRender(esmx) {
81
78
  }
82
79
  function rewriteBuild(esmx, options = {}) {
83
80
  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
81
  const ok = await createRsBuild([
108
82
  generateBuildConfig(esmx, options, "client"),
109
83
  generateBuildConfig(esmx, options, "server"),
@@ -113,10 +87,10 @@ function rewriteBuild(esmx, options = {}) {
113
87
  return false;
114
88
  }
115
89
  esmx.writeSync(
116
- esmx.resolvePath("dist/index.js"),
90
+ esmx.resolvePath("dist/index.mjs"),
117
91
  `
118
92
  async function start() {
119
- const options = await import('./node/src/entry.node.js').then(
93
+ const options = await import('./node/src/entry.node.mjs').then(
120
94
  (mod) => mod.default
121
95
  );
122
96
  const { Esmx } = await import('@esmx/core');
package/dist/config.mjs CHANGED
@@ -4,7 +4,6 @@ import {
4
4
  } from "@rspack/core";
5
5
  import nodeExternals from "webpack-node-externals";
6
6
  export function createRspackConfig(esmx, buildTarget, options) {
7
- const isWebApp = buildTarget === "client" || buildTarget === "server";
8
7
  const isHot = buildTarget === "client" && !esmx.isProd;
9
8
  return {
10
9
  /**
@@ -12,42 +11,23 @@ export function createRspackConfig(esmx, buildTarget, options) {
12
11
  */
13
12
  context: esmx.root,
14
13
  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;
14
+ if (buildTarget === "node") {
15
+ return {
16
+ [`./src/entry.${buildTarget}`]: {
17
+ import: esmx.resolvePath("src/entry.node.ts")
18
+ }
19
+ };
29
20
  }
30
- return {
31
- [`./src/entry.${buildTarget}`]: {
32
- import: importPaths
33
- }
34
- };
35
21
  })(),
36
22
  output: {
37
23
  clean: esmx.isProd,
38
- module: true,
39
- chunkFormat: esmx.isProd ? "module" : void 0,
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",
24
+ chunkFilename: esmx.isProd ? "[name].[contenthash:8].final.mjs" : "[name].mjs",
25
+ filename: buildTarget !== "node" && esmx.isProd ? "[name].[contenthash:8].final.mjs" : "[name].mjs",
46
26
  cssFilename: esmx.isProd ? "[name].[contenthash:8].final.css" : "[name].css",
47
- cssChunkFilename: esmx.isProd ? "chunks/[name].[contenthash:8].final.css" : "chunks/[name].css",
27
+ cssChunkFilename: esmx.isProd ? "[name].[contenthash:8].final.css" : "[name].css",
48
28
  publicPath: buildTarget === "client" ? "auto" : `${esmx.basePathPlaceholder}${esmx.basePath}`,
49
29
  uniqueName: esmx.varName,
50
- hotUpdateChunkFilename: "__hot__/[id].[fullhash].hot-update.js",
30
+ hotUpdateChunkFilename: "__hot__/[id].[fullhash].hot-update.mjs",
51
31
  hotUpdateMainFilename: "__hot__/[runtime].[fullhash].hot-update.json",
52
32
  path: (() => {
53
33
  switch (buildTarget) {
@@ -58,33 +38,21 @@ export function createRspackConfig(esmx, buildTarget, options) {
58
38
  case "node":
59
39
  return esmx.resolvePath("dist/node");
60
40
  }
61
- })(),
62
- environment: {
63
- dynamicImport: true,
64
- dynamicImportInWorker: true,
65
- module: true,
66
- nodePrefixForCoreModules: true
67
- }
41
+ })()
68
42
  },
69
- // 默认插件,不可修改
70
43
  plugins: (() => {
71
44
  return [
72
- // 进度条插件
73
45
  new rspack.ProgressPlugin({
74
46
  prefix: buildTarget
75
47
  }),
76
- // 模块链接插件
77
- isWebApp ? moduleLinkPlugin(esmx.moduleConfig) : false,
78
- // 热更新插件
48
+ createModuleLinkPlugin(esmx, buildTarget),
79
49
  isHot ? new rspack.HotModuleReplacementPlugin() : false
80
50
  ];
81
51
  })(),
82
52
  module: {
83
53
  parser: {
84
54
  javascript: {
85
- url: buildTarget === "client" ? true : "relative",
86
- importMeta: false,
87
- strictExportPresence: true
55
+ url: buildTarget === "client" ? true : "relative"
88
56
  }
89
57
  },
90
58
  generator: {
@@ -104,8 +72,6 @@ export function createRspackConfig(esmx, buildTarget, options) {
104
72
  },
105
73
  optimization: {
106
74
  minimize: options.minimize ?? esmx.isProd,
107
- avoidEntryIife: esmx.isProd,
108
- concatenateModules: esmx.isProd,
109
75
  emitOnErrors: true,
110
76
  splitChunks: {
111
77
  chunks: "async"
@@ -128,18 +94,29 @@ export function createRspackConfig(esmx, buildTarget, options) {
128
94
  }
129
95
  return [];
130
96
  })(),
131
- experiments: {
132
- outputModule: true,
133
- parallelCodeSplitting: true,
134
- rspackFuture: {
135
- bundlerInfo: { force: false }
136
- }
137
- },
138
97
  target: buildTarget === "client" ? "web" : "node22.6",
139
98
  mode: esmx.isProd ? "production" : "development",
140
99
  cache: !esmx.isProd
141
100
  };
142
101
  }
143
- function resolve(name) {
144
- return new URL(import.meta.resolve(name)).pathname;
102
+ function createModuleLinkPlugin(esmx, buildTarget) {
103
+ if (buildTarget === "node") {
104
+ return;
105
+ }
106
+ const exports = {};
107
+ for (const [name, item] of Object.entries(esmx.moduleConfig.exports)) {
108
+ if (item.inputTarget[buildTarget]) {
109
+ exports[name] = {
110
+ rewrite: item.rewrite,
111
+ file: item.inputTarget[buildTarget]
112
+ };
113
+ }
114
+ }
115
+ return moduleLinkPlugin({
116
+ name: esmx.name,
117
+ ext: "mjs",
118
+ injectChunkName: buildTarget === "server",
119
+ imports: esmx.moduleConfig.imports,
120
+ exports
121
+ });
145
122
  }
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>=87", "edge>=88", "firefox>=78", "safari>=14"],
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(esmx.resolvePath("dist/client/manifest.json")),
34
- esmx.readJson(esmx.resolvePath("dist/server/manifest.json")),
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 = {
@@ -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
- console.log(styleText("red", err2.message));
21
+ showError(err2.message);
18
22
  });
19
23
  return resolve(false);
20
24
  }
21
25
  multiCompiler.close((err2) => {
22
26
  if (err2) {
23
- console.log(styleText("red", err2.message));
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.error(err);
40
+ console.log(styleText("red", err.message));
37
41
  return;
38
42
  }
39
43
  if (stats?.hasErrors()) {
package/package.json CHANGED
@@ -63,10 +63,10 @@
63
63
  }
64
64
  },
65
65
  "dependencies": {
66
- "@esmx/import": "3.0.0-rc.18",
67
- "@esmx/rspack-module-link-plugin": "3.0.0-rc.18",
66
+ "@esmx/import": "3.0.0-rc.19",
67
+ "@esmx/rspack-module-link-plugin": "3.0.0-rc.19",
68
68
  "@npmcli/arborist": "^9.0.1",
69
- "@rspack/core": "1.3.2",
69
+ "@rspack/core": "1.4.0-rc.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.18",
83
- "@esmx/lint": "3.0.0-rc.18",
84
- "@gez/lint": "3.0.0-rc.9",
85
- "@types/node": "22.13.10",
82
+ "@esmx/core": "3.0.0-rc.19",
83
+ "@esmx/lint": "3.0.0-rc.19",
84
+ "@types/node": "22.15.18",
86
85
  "@types/npmcli__arborist": "^5.6.11",
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.0.8",
91
- "stylelint": "16.15.0",
89
+ "@vitest/coverage-v8": "3.1.3",
90
+ "stylelint": "16.19.1",
92
91
  "typescript": "5.8.2",
93
- "unbuild": "2.0.0",
94
- "vitest": "3.0.8"
92
+ "unbuild": "3.5.0",
93
+ "vitest": "3.1.3"
95
94
  },
96
- "version": "3.0.0-rc.18",
95
+ "version": "3.0.0-rc.19",
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": "79ceb323f985dd88dbd7f1349f61f341b6d522c4"
114
+ "gitHead": "83a9cfac4a91b2b54ac576e120bb4541f4cce9d6"
116
115
  }
package/src/app.ts CHANGED
@@ -1,11 +1,8 @@
1
- import fs from 'node:fs';
2
1
  import { pathToFileURL } from 'node:url';
3
- import { styleText } from 'node:util';
4
2
  import {
5
3
  type App,
6
4
  type Esmx,
7
5
  type Middleware,
8
- PathType,
9
6
  RenderContext,
10
7
  type RenderContextOptions,
11
8
  type ServerRenderHandle,
@@ -270,29 +267,6 @@ function rewriteRender(esmx: Esmx) {
270
267
 
271
268
  function rewriteBuild(esmx: Esmx, options: RspackAppOptions = {}) {
272
269
  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
270
  const ok = await createRsBuild([
297
271
  generateBuildConfig(esmx, options, 'client'),
298
272
  generateBuildConfig(esmx, options, 'server'),
@@ -302,10 +276,10 @@ function rewriteBuild(esmx: Esmx, options: RspackAppOptions = {}) {
302
276
  return false;
303
277
  }
304
278
  esmx.writeSync(
305
- esmx.resolvePath('dist/index.js'),
279
+ esmx.resolvePath('dist/index.mjs'),
306
280
  `
307
281
  async function start() {
308
- const options = await import('./node/src/entry.node.js').then(
282
+ const options = await import('./node/src/entry.node.mjs').then(
309
283
  (mod) => mod.default
310
284
  );
311
285
  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
@@ -18,7 +19,6 @@ export function createRspackConfig(
18
19
  buildTarget: BuildTarget,
19
20
  options: RspackAppOptions
20
21
  ): RspackOptions {
21
- const isWebApp = buildTarget === 'client' || buildTarget === 'server';
22
22
  const isHot = buildTarget === 'client' && !esmx.isProd;
23
23
  return {
24
24
  /**
@@ -26,55 +26,35 @@ export function createRspackConfig(
26
26
  */
27
27
  context: esmx.root,
28
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;
29
+ if (buildTarget === 'node') {
30
+ return {
31
+ [`./src/entry.${buildTarget}`]: {
32
+ import: esmx.resolvePath('src/entry.node.ts')
33
+ }
34
+ };
44
35
  }
45
- return {
46
- [`./src/entry.${buildTarget}`]: {
47
- import: importPaths
48
- }
49
- };
50
36
  })(),
51
37
  output: {
52
38
  clean: esmx.isProd,
53
- module: true,
54
- chunkFormat: esmx.isProd ? 'module' : undefined,
55
- chunkLoading: esmx.isProd ? 'import' : undefined,
56
39
  chunkFilename: esmx.isProd
57
- ? 'chunks/[name].[contenthash:8].final.js'
58
- : 'chunks/[name].js',
59
- library: {
60
- type: esmx.isProd ? 'modern-module' : 'module'
61
- },
40
+ ? '[name].[contenthash:8].final.mjs'
41
+ : '[name].mjs',
62
42
  filename:
63
43
  buildTarget !== 'node' && esmx.isProd
64
- ? '[name].[contenthash:8].final.js'
65
- : '[name].js',
44
+ ? '[name].[contenthash:8].final.mjs'
45
+ : '[name].mjs',
66
46
  cssFilename: esmx.isProd
67
47
  ? '[name].[contenthash:8].final.css'
68
48
  : '[name].css',
69
49
  cssChunkFilename: esmx.isProd
70
- ? 'chunks/[name].[contenthash:8].final.css'
71
- : 'chunks/[name].css',
50
+ ? '[name].[contenthash:8].final.css'
51
+ : '[name].css',
72
52
  publicPath:
73
53
  buildTarget === 'client'
74
54
  ? 'auto'
75
55
  : `${esmx.basePathPlaceholder}${esmx.basePath}`,
76
56
  uniqueName: esmx.varName,
77
- hotUpdateChunkFilename: '__hot__/[id].[fullhash].hot-update.js',
57
+ hotUpdateChunkFilename: '__hot__/[id].[fullhash].hot-update.mjs',
78
58
  hotUpdateMainFilename:
79
59
  '__hot__/[runtime].[fullhash].hot-update.json',
80
60
  path: ((): string => {
@@ -86,33 +66,21 @@ export function createRspackConfig(
86
66
  case 'node':
87
67
  return esmx.resolvePath('dist/node');
88
68
  }
89
- })(),
90
- environment: {
91
- dynamicImport: true,
92
- dynamicImportInWorker: true,
93
- module: true,
94
- nodePrefixForCoreModules: true
95
- }
69
+ })()
96
70
  },
97
- // 默认插件,不可修改
98
71
  plugins: ((): Plugins => {
99
72
  return [
100
- // 进度条插件
101
73
  new rspack.ProgressPlugin({
102
74
  prefix: buildTarget
103
75
  }),
104
- // 模块链接插件
105
- isWebApp ? moduleLinkPlugin(esmx.moduleConfig) : false,
106
- // 热更新插件
76
+ createModuleLinkPlugin(esmx, buildTarget),
107
77
  isHot ? new rspack.HotModuleReplacementPlugin() : false
108
78
  ];
109
79
  })(),
110
80
  module: {
111
81
  parser: {
112
82
  javascript: {
113
- url: buildTarget === 'client' ? true : 'relative',
114
- importMeta: false,
115
- strictExportPresence: true
83
+ url: buildTarget === 'client' ? true : 'relative'
116
84
  }
117
85
  },
118
86
  generator: {
@@ -132,8 +100,6 @@ export function createRspackConfig(
132
100
  },
133
101
  optimization: {
134
102
  minimize: options.minimize ?? esmx.isProd,
135
- avoidEntryIife: esmx.isProd,
136
- concatenateModules: esmx.isProd,
137
103
  emitOnErrors: true,
138
104
  splitChunks: {
139
105
  chunks: 'async'
@@ -156,19 +122,36 @@ export function createRspackConfig(
156
122
  }
157
123
  return [];
158
124
  })(),
159
- experiments: {
160
- outputModule: true,
161
- parallelCodeSplitting: true,
162
- rspackFuture: {
163
- bundlerInfo: { force: false }
164
- }
165
- },
166
125
  target: buildTarget === 'client' ? 'web' : 'node22.6',
167
126
  mode: esmx.isProd ? 'production' : 'development',
168
127
  cache: !esmx.isProd
169
128
  };
170
129
  }
171
130
 
172
- function resolve(name: string) {
173
- return new URL(import.meta.resolve(name)).pathname;
131
+ function createModuleLinkPlugin(esmx: Esmx, buildTarget: BuildTarget): Plugin {
132
+ if (buildTarget === 'node') {
133
+ return;
134
+ }
135
+ const exports: Record<
136
+ string,
137
+ {
138
+ rewrite: boolean;
139
+ file: string;
140
+ }
141
+ > = {};
142
+ for (const [name, item] of Object.entries(esmx.moduleConfig.exports)) {
143
+ if (item.inputTarget[buildTarget]) {
144
+ exports[name] = {
145
+ rewrite: item.rewrite,
146
+ file: item.inputTarget[buildTarget]
147
+ };
148
+ }
149
+ }
150
+ return moduleLinkPlugin({
151
+ name: esmx.name,
152
+ ext: 'mjs',
153
+ injectChunkName: buildTarget === 'server',
154
+ imports: esmx.moduleConfig.imports,
155
+ exports
156
+ });
174
157
  }
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>=87', 'edge>=88', 'firefox>=78', 'safari>=14'],
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(esmx.resolvePath('dist/client/manifest.json')),
42
- esmx.readJson(esmx.resolvePath('dist/server/manifest.json')),
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
 
@@ -1,6 +1,10 @@
1
1
  import { styleText } from 'node:util';
2
2
  import { type Compiler, type RspackOptions, rspack } from '@rspack/core';
3
3
 
4
+ function showError(message: string) {
5
+ console.error(styleText('red', message));
6
+ }
7
+
4
8
  export function createRsBuild(options: RspackOptions[]) {
5
9
  const multiCompiler = rspack(options);
6
10
  return {
@@ -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
- console.log(styleText('red', err.message));
25
+ showError(err.message);
21
26
  });
22
27
  return resolve(false);
23
28
  }
24
29
  multiCompiler.close((err) => {
25
30
  if (err) {
26
- console.log(styleText('red', err.message));
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.error(err);
44
+ console.log(styleText('red', err.message));
40
45
  return;
41
46
  }
42
47
  if (stats?.hasErrors()) {