@esmx/rspack 3.0.0-rc.10 → 3.0.0-rc.103
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 +21 -0
- package/README.md +48 -20
- package/README.zh-CN.md +57 -0
- package/dist/index.d.ts +2 -4
- package/dist/index.mjs +4 -4
- package/dist/module-link/config.d.ts +5 -0
- package/dist/module-link/config.mjs +100 -0
- package/dist/module-link/config1.d.ts +3 -0
- package/dist/module-link/config1.mjs +16 -0
- package/dist/module-link/config2.d.ts +3 -0
- package/dist/module-link/config2.mjs +17 -0
- package/dist/module-link/index.d.ts +4 -0
- package/dist/module-link/index.mjs +8 -0
- package/dist/module-link/manifest-plugin.d.ts +14 -0
- package/dist/module-link/manifest-plugin.mjs +141 -0
- package/dist/module-link/parse.d.ts +2 -0
- package/dist/module-link/parse.mjs +24 -0
- package/dist/module-link/types.d.ts +25 -0
- package/dist/rspack/app.d.ts +183 -0
- package/dist/{app.mjs → rspack/app.mjs} +18 -46
- package/dist/rspack/build-target.d.ts +7 -0
- package/dist/rspack/build-target.mjs +0 -0
- package/dist/{config.d.ts → rspack/chain-config.d.ts} +3 -4
- package/dist/rspack/chain-config.mjs +113 -0
- package/dist/rspack/index.d.ts +3 -0
- package/dist/rspack/index.mjs +4 -0
- package/dist/rspack/loader.d.ts +9 -0
- package/dist/{loader.mjs → rspack/loader.mjs} +2 -22
- package/dist/rspack/pack.d.ts +9 -0
- package/dist/{pack.mjs → rspack/pack.mjs} +33 -25
- package/dist/rspack/pack.test.d.ts +1 -0
- package/dist/rspack/pack.test.mjs +180 -0
- package/dist/rspack/utils/rsbuild.d.ts +6 -0
- package/dist/{utils → rspack/utils}/rsbuild.mjs +7 -37
- package/dist/rspack-html/index.d.ts +168 -0
- package/dist/rspack-html/index.mjs +160 -0
- package/dist/rspack-html/target-setting.d.ts +17 -0
- package/dist/rspack-html/target-setting.mjs +31 -0
- package/dist/rspack-html/target-setting.test.d.ts +1 -0
- package/dist/rspack-html/target-setting.test.mjs +105 -0
- package/package.json +34 -28
- package/src/index.ts +7 -6
- package/src/module-link/config.ts +157 -0
- package/src/module-link/config1.ts +24 -0
- package/src/module-link/config2.ts +28 -0
- package/src/module-link/index.ts +19 -0
- package/src/module-link/manifest-plugin.ts +179 -0
- package/src/module-link/parse.ts +31 -0
- package/src/module-link/types.ts +31 -0
- package/src/{app.ts → rspack/app.ts} +104 -107
- package/src/rspack/build-target.ts +7 -0
- package/src/rspack/chain-config.ts +165 -0
- package/src/rspack/index.ts +8 -0
- package/src/{loader.ts → rspack/loader.ts} +3 -22
- package/src/rspack/pack.test.ts +215 -0
- package/src/rspack/pack.ts +101 -0
- package/src/{utils → rspack/utils}/rsbuild.ts +11 -40
- package/src/rspack-html/index.ts +495 -0
- package/src/rspack-html/target-setting.test.ts +123 -0
- package/src/rspack-html/target-setting.ts +52 -0
- package/dist/app.d.ts +0 -160
- package/dist/build-target.d.ts +0 -8
- package/dist/config.mjs +0 -142
- package/dist/html-app.d.ts +0 -299
- package/dist/html-app.mjs +0 -214
- package/dist/loader.d.ts +0 -30
- package/dist/pack.d.ts +0 -2
- package/dist/utils/rsbuild.d.ts +0 -12
- package/src/build-target.ts +0 -8
- package/src/config.ts +0 -171
- package/src/html-app.ts +0 -560
- package/src/pack.ts +0 -79
- /package/dist/{build-target.mjs → module-link/types.mjs} +0 -0
- /package/dist/{utils → rspack/utils}/index.d.ts +0 -0
- /package/dist/{utils → rspack/utils}/index.mjs +0 -0
- /package/src/{utils → rspack/utils}/index.ts +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 Esmx Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,29 +1,57 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="https://esmx.dev/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://esmx.dev/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 SSR and Module Linking 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
|
|
41
|
+
# npm
|
|
42
|
+
npm install @esmx/rspack -D
|
|
43
|
+
|
|
44
|
+
# pnpm
|
|
16
45
|
pnpm add @esmx/rspack -D
|
|
17
|
-
|
|
46
|
+
|
|
47
|
+
# yarn
|
|
18
48
|
yarn add @esmx/rspack -D
|
|
19
|
-
# 或
|
|
20
|
-
npm install @esmx/rspack -D
|
|
21
49
|
```
|
|
22
50
|
|
|
23
|
-
##
|
|
51
|
+
## 📚 Documentation
|
|
24
52
|
|
|
25
|
-
|
|
53
|
+
Visit the [official documentation](https://esmx.dev/api/app/rspack.html) for detailed usage guides and API reference.
|
|
26
54
|
|
|
27
|
-
##
|
|
55
|
+
## 📄 License
|
|
28
56
|
|
|
29
|
-
MIT
|
|
57
|
+
MIT © [Esmx Team](https://github.com/esmnext/esmx)
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="https://esmx.dev/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://esmx.dev/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
|
|
42
|
+
npm install @esmx/rspack -D
|
|
43
|
+
|
|
44
|
+
# pnpm
|
|
45
|
+
pnpm add @esmx/rspack -D
|
|
46
|
+
|
|
47
|
+
# yarn
|
|
48
|
+
yarn add @esmx/rspack -D
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 📚 文档
|
|
52
|
+
|
|
53
|
+
访问[官方文档](https://esmx.dev/api/app/rspack.html)获取详细的使用指南和 API 参考。
|
|
54
|
+
|
|
55
|
+
## 📄 许可证
|
|
56
|
+
|
|
57
|
+
MIT © [Esmx Team](https://github.com/esmnext/esmx)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
export { type RspackAppConfigContext, type RspackAppOptions
|
|
2
|
-
export { createRspackHtmlApp, type RspackHtmlAppOptions } from './html
|
|
3
|
-
export type { BuildTarget } from './build-target';
|
|
4
|
-
export { RSPACK_LOADER } from './loader';
|
|
1
|
+
export { type BuildTarget, createRspackApp, RSPACK_LOADER, type RspackAppChainContext, type RspackAppConfigContext, type RspackAppOptions } from './rspack';
|
|
2
|
+
export { createRspackHtmlApp, type RspackHtmlAppOptions } from './rspack-html';
|
|
5
3
|
import * as rspack from '@rspack/core';
|
|
6
4
|
export { rspack };
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export {
|
|
2
|
-
createRspackApp
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export {
|
|
2
|
+
createRspackApp,
|
|
3
|
+
RSPACK_LOADER
|
|
4
|
+
} from "./rspack/index.mjs";
|
|
5
|
+
export { createRspackHtmlApp } from "./rspack-html/index.mjs";
|
|
6
6
|
import * as rspack from "@rspack/core";
|
|
7
7
|
export { rspack };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type RspackChain from 'rspack-chain';
|
|
2
|
+
import type { ParsedModuleLinkPluginOptions } from './types';
|
|
3
|
+
export declare function applyEntryConfig(chain: RspackChain, opts: ParsedModuleLinkPluginOptions): void;
|
|
4
|
+
export declare function applyModuleConfig(chain: RspackChain): void;
|
|
5
|
+
export declare function applyExternalsConfig(chain: RspackChain, opts: ParsedModuleLinkPluginOptions): void;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
export function applyEntryConfig(chain, opts) {
|
|
2
|
+
if (chain.entryPoints.has("main")) {
|
|
3
|
+
const mainEntry = chain.entry("main");
|
|
4
|
+
if (mainEntry.values().length === 0) {
|
|
5
|
+
chain.entryPoints.clear();
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
for (const value of Object.values(opts.exports)) {
|
|
9
|
+
if (value.file) {
|
|
10
|
+
const entry = chain.entry(value.name);
|
|
11
|
+
for (const preEntry of opts.preEntries) {
|
|
12
|
+
entry.add(preEntry);
|
|
13
|
+
}
|
|
14
|
+
entry.add(value.file);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function applyModuleConfig(chain) {
|
|
19
|
+
chain.output.set("module", true).set("chunkFormat", "module").set("chunkLoading", "import").set("workerChunkLoading", "import");
|
|
20
|
+
chain.output.library({
|
|
21
|
+
type: "module"
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
export function applyExternalsConfig(chain, opts) {
|
|
25
|
+
const existingExternals = chain.get("externals") || [];
|
|
26
|
+
const externals = Array.isArray(existingExternals) ? [...existingExternals] : [existingExternals];
|
|
27
|
+
const compilerContext = chain.get("context") ?? process.cwd();
|
|
28
|
+
const externalFunc = createExternalsFunction(opts, compilerContext);
|
|
29
|
+
externals.push(externalFunc);
|
|
30
|
+
chain.externals(externals);
|
|
31
|
+
}
|
|
32
|
+
function createExternalsFunction(opts, compilerContext) {
|
|
33
|
+
const importMap = /* @__PURE__ */ new Map();
|
|
34
|
+
let initPromise = null;
|
|
35
|
+
const init = (resolvePath) => {
|
|
36
|
+
if (initPromise) return initPromise;
|
|
37
|
+
initPromise = (async () => {
|
|
38
|
+
await Promise.all(
|
|
39
|
+
Object.values(opts.exports).map(async (value) => {
|
|
40
|
+
const identifier = value.pkg ? value.name : value.identifier;
|
|
41
|
+
importMap.set(identifier, identifier);
|
|
42
|
+
importMap.set(value.name, identifier);
|
|
43
|
+
const resolvedPath = await resolvePath(value.file);
|
|
44
|
+
if (resolvedPath) {
|
|
45
|
+
importMap.set(resolvedPath, identifier);
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
);
|
|
49
|
+
for (const key of Object.keys(opts.imports)) {
|
|
50
|
+
importMap.set(key, key);
|
|
51
|
+
}
|
|
52
|
+
})();
|
|
53
|
+
return initPromise;
|
|
54
|
+
};
|
|
55
|
+
const match = async (request, context, resolvePath) => {
|
|
56
|
+
if (!request) return null;
|
|
57
|
+
if (opts.deps.length > 0) {
|
|
58
|
+
const matchedDep = opts.deps.find(
|
|
59
|
+
(dep) => request === dep || request.startsWith(`${dep}/`)
|
|
60
|
+
);
|
|
61
|
+
if (matchedDep) {
|
|
62
|
+
return request;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
let importName = importMap.get(request);
|
|
66
|
+
if (!importName) {
|
|
67
|
+
const resolvedPath = await resolvePath(request, context);
|
|
68
|
+
if (resolvedPath) {
|
|
69
|
+
importName = importMap.get(resolvedPath);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return importName || null;
|
|
73
|
+
};
|
|
74
|
+
const FILE_EXT_REGEX = /\.worker\.(js|mjs|cjs|jsx|mjsx|cjsx|ts|mts|cts|tsx|mtsx|ctsx)$/i;
|
|
75
|
+
return async (data) => {
|
|
76
|
+
if (!data.request || !data.context || !data.contextInfo?.issuer || FILE_EXT_REGEX.test(data.contextInfo.issuer))
|
|
77
|
+
return;
|
|
78
|
+
const defaultContext = compilerContext;
|
|
79
|
+
const resolvePath = async (request, context = defaultContext) => {
|
|
80
|
+
if (!data.getResolve) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
const resolveFunc = data.getResolve();
|
|
84
|
+
return new Promise((resolve) => {
|
|
85
|
+
resolveFunc(context, request, (err, res) => {
|
|
86
|
+
resolve(typeof res === "string" ? res : null);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
await init(resolvePath);
|
|
91
|
+
const matchedIdentifier = await match(
|
|
92
|
+
data.request,
|
|
93
|
+
data.context,
|
|
94
|
+
resolvePath
|
|
95
|
+
);
|
|
96
|
+
if (matchedIdentifier) {
|
|
97
|
+
return `module-import ${matchedIdentifier}`;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
applyEntryConfig,
|
|
3
|
+
applyExternalsConfig,
|
|
4
|
+
applyModuleConfig
|
|
5
|
+
} from "./config.mjs";
|
|
6
|
+
export function applyChainConfig1(chain, opts) {
|
|
7
|
+
applyEntryConfig(chain, opts);
|
|
8
|
+
applyExternalsConfig(chain, opts);
|
|
9
|
+
applyModuleConfig(chain);
|
|
10
|
+
if (chain.get("mode") === "production") {
|
|
11
|
+
chain.output.library({
|
|
12
|
+
type: "modern-module"
|
|
13
|
+
});
|
|
14
|
+
chain.optimization.set("avoidEntryIife", true);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { rspack } from "@rspack/core";
|
|
2
|
+
import {
|
|
3
|
+
applyEntryConfig,
|
|
4
|
+
applyExternalsConfig,
|
|
5
|
+
applyModuleConfig
|
|
6
|
+
} from "./config.mjs";
|
|
7
|
+
export function applyChainConfig2(chain, opts) {
|
|
8
|
+
applyEntryConfig(chain, opts);
|
|
9
|
+
applyExternalsConfig(chain, opts);
|
|
10
|
+
if (chain.get("mode") === "production") {
|
|
11
|
+
chain.output.set("module", true);
|
|
12
|
+
chain.plugin("esm-library").use(new rspack.experiments.EsmLibraryPlugin());
|
|
13
|
+
chain.optimization.set("runtimeChunk", "single");
|
|
14
|
+
} else {
|
|
15
|
+
applyModuleConfig(chain);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { applyChainConfig1 } from "./config1.mjs";
|
|
2
|
+
import { ManifestPlugin } from "./manifest-plugin.mjs";
|
|
3
|
+
import { parseOptions } from "./parse.mjs";
|
|
4
|
+
export function initModuleLink(chain, options) {
|
|
5
|
+
const opts = parseOptions(options);
|
|
6
|
+
applyChainConfig1(chain, opts);
|
|
7
|
+
chain.plugin("module-link-manifest").use(ManifestPlugin, [opts]);
|
|
8
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Compiler, StatsCompilation } from '@rspack/core';
|
|
2
|
+
import type { ManifestJsonExports, ParsedModuleLinkPluginOptions } from './types';
|
|
3
|
+
export declare const RSPACK_PLUGIN_NAME = "rspack-module-link-plugin";
|
|
4
|
+
export declare class ManifestPlugin {
|
|
5
|
+
private opts;
|
|
6
|
+
constructor(opts: ParsedModuleLinkPluginOptions);
|
|
7
|
+
apply(compiler: Compiler): void;
|
|
8
|
+
}
|
|
9
|
+
export declare function getExports(opts: ParsedModuleLinkPluginOptions, stats: StatsCompilation): ManifestJsonExports;
|
|
10
|
+
export declare function generateIdentifier({ root, name, filePath }: {
|
|
11
|
+
root: string;
|
|
12
|
+
name: string;
|
|
13
|
+
filePath: string;
|
|
14
|
+
}): string;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import upath from "upath";
|
|
2
|
+
export const RSPACK_PLUGIN_NAME = "rspack-module-link-plugin";
|
|
3
|
+
export class ManifestPlugin {
|
|
4
|
+
constructor(opts) {
|
|
5
|
+
this.opts = opts;
|
|
6
|
+
}
|
|
7
|
+
apply(compiler) {
|
|
8
|
+
const opts = this.opts;
|
|
9
|
+
const { Compilation } = compiler.rspack;
|
|
10
|
+
compiler.hooks.thisCompilation.tap(
|
|
11
|
+
RSPACK_PLUGIN_NAME,
|
|
12
|
+
(compilation) => {
|
|
13
|
+
let manifestJson = {
|
|
14
|
+
name: opts.name,
|
|
15
|
+
exports: {},
|
|
16
|
+
scopes: opts.scopes,
|
|
17
|
+
files: [],
|
|
18
|
+
chunks: {}
|
|
19
|
+
};
|
|
20
|
+
compilation.hooks.processAssets.tap(
|
|
21
|
+
{
|
|
22
|
+
name: RSPACK_PLUGIN_NAME,
|
|
23
|
+
stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL
|
|
24
|
+
},
|
|
25
|
+
(assets) => {
|
|
26
|
+
const stats = compilation.getStats().toJson({
|
|
27
|
+
hash: true,
|
|
28
|
+
entrypoints: true
|
|
29
|
+
});
|
|
30
|
+
const exports = getExports(opts, stats);
|
|
31
|
+
const resources = Object.keys(assets).map(transFileName).filter((file) => !file.includes("hot-update"));
|
|
32
|
+
manifestJson = {
|
|
33
|
+
name: opts.name,
|
|
34
|
+
exports,
|
|
35
|
+
scopes: opts.scopes,
|
|
36
|
+
files: resources,
|
|
37
|
+
chunks: getChunks(opts, compilation)
|
|
38
|
+
};
|
|
39
|
+
const { RawSource } = compiler.rspack.sources;
|
|
40
|
+
compilation.emitAsset(
|
|
41
|
+
"manifest.json",
|
|
42
|
+
new RawSource(JSON.stringify(manifestJson, null, 4))
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
if (opts.injectChunkName) {
|
|
47
|
+
compilation.hooks.processAssets.tap(
|
|
48
|
+
{
|
|
49
|
+
name: RSPACK_PLUGIN_NAME,
|
|
50
|
+
stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
|
|
51
|
+
},
|
|
52
|
+
(assets) => {
|
|
53
|
+
const { RawSource } = compiler.rspack.sources;
|
|
54
|
+
for (const [key, value] of Object.entries(
|
|
55
|
+
manifestJson.chunks
|
|
56
|
+
)) {
|
|
57
|
+
const asset = assets[value.js];
|
|
58
|
+
if (!asset) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const source = new RawSource(
|
|
62
|
+
`import.meta.chunkName = import.meta.chunkName ?? ${JSON.stringify(key)};
|
|
63
|
+
${asset.source()}`
|
|
64
|
+
);
|
|
65
|
+
compilation.updateAsset(value.js, source);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function transFileName(fileName) {
|
|
75
|
+
return fileName.replace(/^.\//, "");
|
|
76
|
+
}
|
|
77
|
+
export function getExports(opts, stats) {
|
|
78
|
+
const entrypoints = stats.entrypoints || {};
|
|
79
|
+
const exports = {};
|
|
80
|
+
for (const [key, value] of Object.entries(entrypoints)) {
|
|
81
|
+
const asset = value.assets?.find((item) => {
|
|
82
|
+
return item.name.endsWith(opts.ext) && item.name.startsWith(key) && !item.name.includes("hot-update");
|
|
83
|
+
});
|
|
84
|
+
if (!asset) continue;
|
|
85
|
+
if (key in opts.exports) {
|
|
86
|
+
exports[key] = {
|
|
87
|
+
...opts.exports[key],
|
|
88
|
+
file: asset.name
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return exports;
|
|
93
|
+
}
|
|
94
|
+
function getChunks(opts, compilation) {
|
|
95
|
+
const stats = compilation.getStats().toJson({
|
|
96
|
+
all: false,
|
|
97
|
+
chunks: true,
|
|
98
|
+
modules: true,
|
|
99
|
+
chunkModules: true,
|
|
100
|
+
ids: true
|
|
101
|
+
});
|
|
102
|
+
const buildChunks = {};
|
|
103
|
+
if (!stats.chunks) return buildChunks;
|
|
104
|
+
for (const chunk of stats.chunks) {
|
|
105
|
+
const module = chunk.modules?.sort((a, b) => {
|
|
106
|
+
return (a.index ?? -1) - (b?.index ?? -1);
|
|
107
|
+
})?.find((module2) => {
|
|
108
|
+
return module2.moduleType?.includes("javascript/");
|
|
109
|
+
});
|
|
110
|
+
if (!module?.nameForCondition) continue;
|
|
111
|
+
const js = chunk.files?.find((file) => file.endsWith(opts.ext));
|
|
112
|
+
if (!js) continue;
|
|
113
|
+
const root = compilation.options.context ?? process.cwd();
|
|
114
|
+
const name = generateIdentifier({
|
|
115
|
+
root,
|
|
116
|
+
name: opts.name,
|
|
117
|
+
filePath: module.nameForCondition
|
|
118
|
+
});
|
|
119
|
+
const css = chunk.files?.filter((file) => file.endsWith(".css")) ?? [];
|
|
120
|
+
const resources = chunk.auxiliaryFiles ?? [];
|
|
121
|
+
buildChunks[name] = {
|
|
122
|
+
name,
|
|
123
|
+
js,
|
|
124
|
+
css,
|
|
125
|
+
resources
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
return buildChunks;
|
|
129
|
+
}
|
|
130
|
+
export function generateIdentifier({
|
|
131
|
+
root,
|
|
132
|
+
name,
|
|
133
|
+
filePath
|
|
134
|
+
}) {
|
|
135
|
+
const unixFilePath = upath.toUnix(filePath);
|
|
136
|
+
if (!root) {
|
|
137
|
+
return `${name}@${unixFilePath}`;
|
|
138
|
+
}
|
|
139
|
+
const file = upath.relative(upath.toUnix(root), unixFilePath);
|
|
140
|
+
return `${name}@${file}`;
|
|
141
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export function parseOptions(options) {
|
|
2
|
+
const exports = {};
|
|
3
|
+
if (options.exports) {
|
|
4
|
+
for (const [name, item] of Object.entries(options.exports)) {
|
|
5
|
+
exports[name] = {
|
|
6
|
+
name,
|
|
7
|
+
pkg: !!item.pkg,
|
|
8
|
+
file: item.file,
|
|
9
|
+
identifier: `${options.name}/${name}`
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
const deps = (options.deps ?? []).filter((name) => name !== options.name);
|
|
14
|
+
return {
|
|
15
|
+
name: options.name,
|
|
16
|
+
ext: options.ext ? `.${options.ext}` : ".mjs",
|
|
17
|
+
exports,
|
|
18
|
+
imports: options.imports ?? {},
|
|
19
|
+
scopes: options.scopes ?? {},
|
|
20
|
+
injectChunkName: options.injectChunkName ?? false,
|
|
21
|
+
preEntries: options.preEntries ?? [],
|
|
22
|
+
deps
|
|
23
|
+
};
|
|
24
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ManifestJsonExports } from '@esmx/core';
|
|
2
|
+
export type { ManifestJson, ManifestJsonChunk, ManifestJsonChunks, ManifestJsonExport, ManifestJsonExports } from '@esmx/core';
|
|
3
|
+
export interface ModuleLinkPluginOptions {
|
|
4
|
+
name: string;
|
|
5
|
+
ext?: string;
|
|
6
|
+
imports?: Record<string, string>;
|
|
7
|
+
scopes?: Record<string, Record<string, string>>;
|
|
8
|
+
exports?: Record<string, {
|
|
9
|
+
pkg?: boolean;
|
|
10
|
+
file: string;
|
|
11
|
+
}>;
|
|
12
|
+
injectChunkName?: boolean;
|
|
13
|
+
preEntries?: string[];
|
|
14
|
+
deps?: string[];
|
|
15
|
+
}
|
|
16
|
+
export interface ParsedModuleLinkPluginOptions {
|
|
17
|
+
name: string;
|
|
18
|
+
ext: string;
|
|
19
|
+
exports: ManifestJsonExports;
|
|
20
|
+
imports: Record<string, string>;
|
|
21
|
+
scopes: Record<string, Record<string, string>>;
|
|
22
|
+
injectChunkName: boolean;
|
|
23
|
+
preEntries: string[];
|
|
24
|
+
deps: string[];
|
|
25
|
+
}
|