@lark-apaas/fullstack-rspack-preset 1.0.57-alpha.0 → 1.0.57-alpha.1
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/lib/preset.js
CHANGED
|
@@ -21,6 +21,7 @@ const css_legacy_plugin_1 = __importDefault(require("./rspack-plugins/css-legacy
|
|
|
21
21
|
const polyfill_plugin_1 = __importDefault(require("./rspack-plugins/polyfill-plugin"));
|
|
22
22
|
const static_assets_plugin_1 = __importDefault(require("./rspack-plugins/static-assets-plugin"));
|
|
23
23
|
const source_map_upload_plugin_1 = __importDefault(require("./rspack-plugins/source-map-upload-plugin"));
|
|
24
|
+
const capabilities_plugin_1 = require("./rspack-plugins/capabilities-plugin");
|
|
24
25
|
const dev_server_snapdom_proxy_1 = require("./utils/dev-server-snapdom-proxy");
|
|
25
26
|
function sendBackendUnavailable502(_err, _req, res) {
|
|
26
27
|
if (res.headersSent)
|
|
@@ -221,6 +222,13 @@ function createRecommendRspackConfig(options) {
|
|
|
221
222
|
],
|
|
222
223
|
},
|
|
223
224
|
plugins: [
|
|
225
|
+
// virtual:capabilities —— client-toolkit 经 client-capability 强依赖的虚拟模块。
|
|
226
|
+
// 即便业务工程没有 capability JSON 也必须把虚拟模块注册成空 map,否则下游
|
|
227
|
+
// node_modules/@lark-apaas/client-capability/dist/index.js 的
|
|
228
|
+
// `import 'virtual:capabilities'` 在 rspack 解析阶段直接 fail。
|
|
229
|
+
// 必须放在 RuntimeInjectionPlugin 前面 —— RuntimeInjectionPlugin 注入的
|
|
230
|
+
// client-toolkit/runtime 入口会间接 import 到 client-capability。
|
|
231
|
+
new capabilities_plugin_1.CapabilitiesPlugin({ rootDir }),
|
|
224
232
|
// 运行时注入插件 - 自动将 @lark-apaas/client-toolkit/runtime 注入到所有入口之前
|
|
225
233
|
new runtime_injection_plugin_1.default(),
|
|
226
234
|
// basename 运行时注入 - 改写入口文件 process.env.CLIENT_BASE_PATH 为运行时读 window.__BASENAME__
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capabilities Plugin for Rspack
|
|
3
|
+
*
|
|
4
|
+
* 解析 `virtual:capabilities` 虚拟模块——`@lark-apaas/client-capability` SDK
|
|
5
|
+
* (经 client-toolkit 间接消费)把 `virtual:capabilities` 标 tsup external 保留
|
|
6
|
+
* 在 dist 里,下游构建工具必须自己提供解析,否则 rspack build / dev 直接 fail:
|
|
7
|
+
*
|
|
8
|
+
* Module not found: Can't resolve 'virtual:capabilities' in
|
|
9
|
+
* node_modules/@lark-apaas/client-capability/dist/index.js
|
|
10
|
+
*
|
|
11
|
+
* 实现策略(参考同目录 static-assets-plugin 的虚拟模块模式):
|
|
12
|
+
* - 扫 <rootDir>/server/capabilities/*.json + <rootDir>/shared/capabilities/*.json
|
|
13
|
+
* 生成 capability map(都不存在时空 map,SDK 在 dev 预览 / 沙箱也能正常加载)
|
|
14
|
+
* - 写虚拟模块文件到 node_modules/.cache/capabilities-virtual/index.js
|
|
15
|
+
* - 通过 `compiler.hooks.normalModuleFactory + beforeResolve` 拦截
|
|
16
|
+
* `virtual:capabilities` import,把 resolveData.request 改写为虚拟模块文件路径
|
|
17
|
+
*
|
|
18
|
+
* 跟 vite 版本的语义保持一致:DEFAULT_DIRS 顺序、capability 合并规则(后 id 覆盖前 id)、
|
|
19
|
+
* 没有 id 的 JSON 跳过 + warn、JSON 解析失败跳过 + warn。
|
|
20
|
+
*/
|
|
21
|
+
import type { Compiler } from '@rspack/core';
|
|
22
|
+
export interface CapabilitiesPluginOptions {
|
|
23
|
+
/** 覆盖扫描目录(相对项目根)。不传按 DEFAULT_DIRS 依次扫描。 */
|
|
24
|
+
dir?: string;
|
|
25
|
+
/** 项目根目录,不传走 compiler.options.context || process.cwd() */
|
|
26
|
+
rootDir?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare class CapabilitiesPlugin {
|
|
29
|
+
private options;
|
|
30
|
+
constructor(options?: CapabilitiesPluginOptions);
|
|
31
|
+
private listDirs;
|
|
32
|
+
private loadMap;
|
|
33
|
+
apply(compiler: Compiler): void;
|
|
34
|
+
}
|
|
35
|
+
export default CapabilitiesPlugin;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Capabilities Plugin for Rspack
|
|
4
|
+
*
|
|
5
|
+
* 解析 `virtual:capabilities` 虚拟模块——`@lark-apaas/client-capability` SDK
|
|
6
|
+
* (经 client-toolkit 间接消费)把 `virtual:capabilities` 标 tsup external 保留
|
|
7
|
+
* 在 dist 里,下游构建工具必须自己提供解析,否则 rspack build / dev 直接 fail:
|
|
8
|
+
*
|
|
9
|
+
* Module not found: Can't resolve 'virtual:capabilities' in
|
|
10
|
+
* node_modules/@lark-apaas/client-capability/dist/index.js
|
|
11
|
+
*
|
|
12
|
+
* 实现策略(参考同目录 static-assets-plugin 的虚拟模块模式):
|
|
13
|
+
* - 扫 <rootDir>/server/capabilities/*.json + <rootDir>/shared/capabilities/*.json
|
|
14
|
+
* 生成 capability map(都不存在时空 map,SDK 在 dev 预览 / 沙箱也能正常加载)
|
|
15
|
+
* - 写虚拟模块文件到 node_modules/.cache/capabilities-virtual/index.js
|
|
16
|
+
* - 通过 `compiler.hooks.normalModuleFactory + beforeResolve` 拦截
|
|
17
|
+
* `virtual:capabilities` import,把 resolveData.request 改写为虚拟模块文件路径
|
|
18
|
+
*
|
|
19
|
+
* 跟 vite 版本的语义保持一致:DEFAULT_DIRS 顺序、capability 合并规则(后 id 覆盖前 id)、
|
|
20
|
+
* 没有 id 的 JSON 跳过 + warn、JSON 解析失败跳过 + warn。
|
|
21
|
+
*/
|
|
22
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
25
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
26
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
27
|
+
}
|
|
28
|
+
Object.defineProperty(o, k2, desc);
|
|
29
|
+
}) : (function(o, m, k, k2) {
|
|
30
|
+
if (k2 === undefined) k2 = k;
|
|
31
|
+
o[k2] = m[k];
|
|
32
|
+
}));
|
|
33
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
34
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
35
|
+
}) : function(o, v) {
|
|
36
|
+
o["default"] = v;
|
|
37
|
+
});
|
|
38
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
39
|
+
var ownKeys = function(o) {
|
|
40
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
41
|
+
var ar = [];
|
|
42
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
43
|
+
return ar;
|
|
44
|
+
};
|
|
45
|
+
return ownKeys(o);
|
|
46
|
+
};
|
|
47
|
+
return function (mod) {
|
|
48
|
+
if (mod && mod.__esModule) return mod;
|
|
49
|
+
var result = {};
|
|
50
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
51
|
+
__setModuleDefault(result, mod);
|
|
52
|
+
return result;
|
|
53
|
+
};
|
|
54
|
+
})();
|
|
55
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
56
|
+
exports.CapabilitiesPlugin = void 0;
|
|
57
|
+
const fs = __importStar(require("node:fs"));
|
|
58
|
+
const path = __importStar(require("node:path"));
|
|
59
|
+
const VIRTUAL_ID = 'virtual:capabilities';
|
|
60
|
+
const PLUGIN_NAME = 'MiaodaCapabilitiesPlugin';
|
|
61
|
+
// fullstack 模板把 capability JSON 放在 `server/capabilities`。
|
|
62
|
+
// 同时兼容 jsPage 风格 `shared/capabilities`。
|
|
63
|
+
const DEFAULT_DIRS = ['server/capabilities', 'shared/capabilities'];
|
|
64
|
+
class CapabilitiesPlugin {
|
|
65
|
+
constructor(options = {}) {
|
|
66
|
+
this.options = options;
|
|
67
|
+
}
|
|
68
|
+
listDirs(rootDir) {
|
|
69
|
+
if (this.options.dir)
|
|
70
|
+
return [path.resolve(rootDir, this.options.dir)];
|
|
71
|
+
return DEFAULT_DIRS.map((d) => path.resolve(rootDir, d));
|
|
72
|
+
}
|
|
73
|
+
loadMap(rootDir) {
|
|
74
|
+
const map = {};
|
|
75
|
+
for (const abs of this.listDirs(rootDir)) {
|
|
76
|
+
if (!fs.existsSync(abs))
|
|
77
|
+
continue;
|
|
78
|
+
for (const f of fs.readdirSync(abs)) {
|
|
79
|
+
if (!f.endsWith('.json'))
|
|
80
|
+
continue;
|
|
81
|
+
try {
|
|
82
|
+
const cfg = JSON.parse(fs.readFileSync(path.join(abs, f), 'utf-8'));
|
|
83
|
+
if (cfg?.id)
|
|
84
|
+
map[cfg.id] = cfg;
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
console.warn(`[miaoda-capabilities] skip invalid json: ${path.join(abs, f)}: ${e instanceof Error ? e.message : String(e)}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return map;
|
|
92
|
+
}
|
|
93
|
+
apply(compiler) {
|
|
94
|
+
const rootDir = this.options.rootDir || compiler.options.context || process.cwd();
|
|
95
|
+
// 临时虚拟模块目录(跟 static-assets-plugin 同款模式)
|
|
96
|
+
const virtualModulesDir = path.join(rootDir, 'node_modules', '.cache', 'capabilities-virtual');
|
|
97
|
+
if (!fs.existsSync(virtualModulesDir)) {
|
|
98
|
+
fs.mkdirSync(virtualModulesDir, { recursive: true });
|
|
99
|
+
}
|
|
100
|
+
const virtualFile = path.join(virtualModulesDir, 'index.js');
|
|
101
|
+
// 构建期写一次虚拟模块内容;dev 期 capability JSON 变更触发 watch 重写。
|
|
102
|
+
// 虚拟文件内容输出 ESM `export default ...` —— 跟 vite 版本严格对齐,避免
|
|
103
|
+
// 未来 client-capability 改用 `import * as caps` 等 NS 形态时,CJS/ESM
|
|
104
|
+
// 互操作产生的差异(CJS 会嵌一层 default)。rspack 默认把 .js 当 module 类型
|
|
105
|
+
// 解析,ESM 语法可直接消费。
|
|
106
|
+
const writeVirtualFile = () => {
|
|
107
|
+
const map = this.loadMap(rootDir);
|
|
108
|
+
const content = `export default ${JSON.stringify(map)};\n`;
|
|
109
|
+
// 仅当内容变化时写盘,避免无意义触发 watcher
|
|
110
|
+
let existing = null;
|
|
111
|
+
try {
|
|
112
|
+
existing = fs.readFileSync(virtualFile, 'utf-8');
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
existing = null;
|
|
116
|
+
}
|
|
117
|
+
if (existing !== content) {
|
|
118
|
+
fs.writeFileSync(virtualFile, content);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
writeVirtualFile();
|
|
122
|
+
// rootDir fallback 静默退化排查难,启动期检查一次实际有没有扫到 capability 目录
|
|
123
|
+
const foundDirs = this.listDirs(rootDir).filter((d) => fs.existsSync(d));
|
|
124
|
+
if (foundDirs.length === 0) {
|
|
125
|
+
console.info(`[miaoda-capabilities] no capability dirs found under ${rootDir}, registering empty map. Scanned: ${this.listDirs(rootDir).join(', ')}`);
|
|
126
|
+
}
|
|
127
|
+
// 拦截 `virtual:capabilities` import 改写到虚拟文件
|
|
128
|
+
compiler.hooks.normalModuleFactory.tap(PLUGIN_NAME, (factory) => {
|
|
129
|
+
factory.hooks.beforeResolve.tap(PLUGIN_NAME, (resolveData) => {
|
|
130
|
+
if (resolveData.request === VIRTUAL_ID) {
|
|
131
|
+
resolveData.request = virtualFile;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
// dev 期监听 capability JSON 变更:每次 compile 把 capability 目录加入
|
|
136
|
+
// contextDependencies(rspack watcher 会观察其下文件创建 / 修改 / 删除)。
|
|
137
|
+
// 不在 afterEnvironment 一次性快照 —— 那样 startup 时还没建的目录永远抓不到。
|
|
138
|
+
// 每次 compile 重新 listDirs() 让新建目录也能被加入监听。
|
|
139
|
+
compiler.hooks.afterCompile.tap(PLUGIN_NAME, (compilation) => {
|
|
140
|
+
for (const dir of this.listDirs(rootDir)) {
|
|
141
|
+
// contextDependencies 接受不存在的路径,rspack 会观察父目录的创建事件
|
|
142
|
+
compilation.contextDependencies.add(dir);
|
|
143
|
+
}
|
|
144
|
+
compilation.fileDependencies.add(virtualFile);
|
|
145
|
+
});
|
|
146
|
+
// 每次 watchRun 前重写虚拟文件(覆盖 dev 期新增 / 修改 capability)
|
|
147
|
+
compiler.hooks.watchRun.tap(PLUGIN_NAME, () => {
|
|
148
|
+
writeVirtualFile();
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
exports.CapabilitiesPlugin = CapabilitiesPlugin;
|
|
153
|
+
exports.default = CapabilitiesPlugin;
|