@yannick-z/modulo 0.3.1 → 0.3.3

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/dist/839.js ADDED
@@ -0,0 +1,437 @@
1
+ import { pluginLess } from "@rsbuild/plugin-less";
2
+ import { createRslib, defineConfig } from "@rslib/core";
3
+ import { pluginReact } from "@rsbuild/plugin-react";
4
+ import { pluginVue2 } from "@rsbuild/plugin-vue2";
5
+ import semver from "semver";
6
+ import { createRsbuild, defineConfig as core_defineConfig } from "@rsbuild/core";
7
+ import { createRequire } from "node:module";
8
+ import { get_directories, exists, fileURLToPath, get_packagejson, get_global_config, PANIC_IF, find_entry_file } from "./938.js";
9
+ import { debug_log, node_path, relative, node_fs, dirname, resolve, picocolors } from "./131.js";
10
+ function get_framework_name() {
11
+ const { dependencies } = get_packagejson();
12
+ PANIC_IF(!("vue" in dependencies || "react" in dependencies), "package.json中未识别到支持的ui库信息, 当前只支持vue和react");
13
+ return "vue" in dependencies ? "vue" : "react";
14
+ }
15
+ function framework_plugin(global_config, options) {
16
+ const { dependencies } = get_packagejson();
17
+ const framework_name = get_framework_name();
18
+ const version = dependencies[framework_name];
19
+ const allowed_versions = [
20
+ global_config.ui_lib.vue2,
21
+ global_config.ui_lib.react19
22
+ ];
23
+ const is_valid = allowed_versions.some((allowed)=>{
24
+ const min_version = semver.minVersion(version);
25
+ return min_version && semver.satisfies(min_version, `^${allowed}`);
26
+ });
27
+ PANIC_IF(!is_valid, `package.json中只允许使用固定版本号, 并且只支持vue-2.7.16, react-19.2.4 (当前版本: ${version})`);
28
+ return "vue" === framework_name ? pluginVue2(options) : pluginReact(options);
29
+ }
30
+ function collect_modules(args, kind, global_config) {
31
+ const framework_name = get_framework_name();
32
+ const module_path = global_config.input[`${kind}s`];
33
+ const isExist = exists(module_path);
34
+ debug_log(picocolors.blue("check module_path"), module_path, isExist ? "exists" : "NOT exists");
35
+ if (!isExist) return;
36
+ const baseCandidates = [
37
+ "index",
38
+ "main"
39
+ ];
40
+ const extensions = [
41
+ ".ts",
42
+ ".tsx",
43
+ ".js",
44
+ ".jsx"
45
+ ];
46
+ if ("vue" === framework_name) extensions.unshift(".vue");
47
+ const module_entries = get_directories(module_path).map((dirName)=>{
48
+ const dir_path = resolve(module_path, dirName);
49
+ const candidates = [
50
+ ...baseCandidates,
51
+ dirName
52
+ ];
53
+ const entry_file_path = find_entry_file(dir_path, candidates, extensions);
54
+ debug_log("found entry", dirName, entry_file_path || "NOT FOUND");
55
+ return [
56
+ dirName,
57
+ entry_file_path
58
+ ];
59
+ }).filter((entry)=>!!entry[1]);
60
+ return module_entries.length > 0 ? Object.fromEntries(module_entries) : void 0;
61
+ }
62
+ function omit_root_path(path) {
63
+ const rel = relative(process.cwd(), path);
64
+ return rel.startsWith("/") ? rel : `/${rel}`;
65
+ }
66
+ function omit_root_path_for_entries(entries) {
67
+ return Object.fromEntries(Object.entries(entries).map(([key, value])=>[
68
+ key,
69
+ omit_root_path(value)
70
+ ]));
71
+ }
72
+ function is_string(data) {
73
+ return "string" == typeof data;
74
+ }
75
+ function is_record(data) {
76
+ return !!data && "object" == typeof data;
77
+ }
78
+ function is_env_external(data) {
79
+ return is_record(data) && is_string(data.dev) && is_string(data.prd);
80
+ }
81
+ function getExternalUrl(args, url) {
82
+ let resolvedUrl = url;
83
+ while(!is_string(resolvedUrl))if (!is_env_external(resolvedUrl)) return;
84
+ else resolvedUrl = resolvedUrl[args.pack.env];
85
+ return resolvedUrl;
86
+ }
87
+ function getExternalsAndImportMap(args, externalLibs, externalsType = "importmap") {
88
+ return Object.entries(externalLibs).reduce(({ externals, importMap }, [libName, data])=>{
89
+ let externalLib;
90
+ externalLib = is_string(data) ? {
91
+ url: data
92
+ } : is_env_external(data) ? {
93
+ url: data
94
+ } : data;
95
+ const url = getExternalUrl(args, externalLib.url);
96
+ if ("script" === externalsType) {
97
+ const globalVar = externalLib.global || libName;
98
+ const importName = externalLib.importName || libName;
99
+ (Array.isArray(importName) ? importName : [
100
+ importName
101
+ ]).forEach((name)=>{
102
+ externals[name] = globalVar;
103
+ });
104
+ if (url) importMap[libName] = url;
105
+ } else {
106
+ const importName = externalLib.importName || libName;
107
+ (Array.isArray(importName) ? importName : [
108
+ importName
109
+ ]).forEach((name)=>{
110
+ externals[name] = libName;
111
+ });
112
+ if (url) importMap[libName] = url;
113
+ }
114
+ return {
115
+ externals,
116
+ importMap
117
+ };
118
+ }, {
119
+ externals: {},
120
+ importMap: {}
121
+ });
122
+ }
123
+ let printed = false;
124
+ function prepare_config(args, kind, config) {
125
+ console.log(picocolors.blueBright(`\n**** 开始构建 【${kind}】 ****`));
126
+ const entries = collect_modules(args, kind, config);
127
+ if (entries) console.log(`${picocolors.blue(`\n${kind} entries:`)}\n${JSON.stringify(omit_root_path_for_entries(entries), null, 2)}\n`);
128
+ else console.log(picocolors.red(`\n没有要构建的${kind},跳过\n`));
129
+ const { externals, importMap } = getExternalsAndImportMap(args, config.externals, config.externalsType);
130
+ printed || console.log(`${picocolors.blue("\nexternals:")}\n${JSON.stringify(externals, null, 2)}\n`);
131
+ let importMapsTag;
132
+ importMapsTag = "script" === config.externalsType ? Object.values(importMap).map((url)=>({
133
+ tag: "script",
134
+ attrs: {
135
+ src: url
136
+ },
137
+ append: false,
138
+ head: true
139
+ })) : [
140
+ {
141
+ append: false,
142
+ head: true,
143
+ tag: "script",
144
+ attrs: {
145
+ type: "importmap"
146
+ },
147
+ children: `{
148
+ "imports": ${JSON.stringify(importMap, null, 2)}
149
+ }`
150
+ }
151
+ ];
152
+ printed || console.log(`${picocolors.blue("\nimportmaps/scripts:")}\n${JSON.stringify(importMap, null, 2)}\n`);
153
+ printed = true;
154
+ return {
155
+ entries,
156
+ externals,
157
+ importMapsTag
158
+ };
159
+ }
160
+ async function lib_pack(args) {
161
+ const config = await get_global_config(args);
162
+ const packagejson = get_packagejson();
163
+ const { entries, externals } = prepare_config(args, "module", config);
164
+ if (!entries) return;
165
+ const rslibConfig = defineConfig({
166
+ root: process.cwd(),
167
+ source: {
168
+ define: config.define,
169
+ entry: entries
170
+ },
171
+ plugins: [
172
+ framework_plugin(config),
173
+ pluginLess()
174
+ ],
175
+ resolve: {
176
+ alias: config.alias
177
+ },
178
+ lib: [
179
+ {
180
+ format: "esm",
181
+ syntax: "esnext",
182
+ dts: false,
183
+ output: {
184
+ assetPrefix: `${config.url.base}/modules`,
185
+ externals,
186
+ distPath: {
187
+ root: config.output.modules,
188
+ js: "esm",
189
+ jsAsync: "esm",
190
+ css: "esm"
191
+ },
192
+ minify: config.minify
193
+ }
194
+ },
195
+ {
196
+ format: "umd",
197
+ output: {
198
+ assetPrefix: `${config.url.base}/modules`,
199
+ externals,
200
+ distPath: {
201
+ root: config.output.modules,
202
+ js: "umd",
203
+ jsAsync: "umd",
204
+ css: "umd"
205
+ },
206
+ minify: config.minify
207
+ },
208
+ syntax: "es6",
209
+ umdName: `${packagejson.name}-modules-[name]`
210
+ }
211
+ ],
212
+ output: {
213
+ legalComments: "none",
214
+ target: "web"
215
+ },
216
+ performance: {
217
+ bundleAnalyze: config.analyze ? {
218
+ analyzerMode: "disabled",
219
+ generateStatsFile: true
220
+ } : void 0,
221
+ chunkSplit: {
222
+ strategy: "all-in-one"
223
+ }
224
+ }
225
+ });
226
+ const rslibInstance = await createRslib({
227
+ config: rslibConfig
228
+ });
229
+ await rslibInstance.build({
230
+ watch: "build" === args.cmd && !!args.pack.watch
231
+ });
232
+ if ("build" === args.cmd) console.log(picocolors.green("\n**** 构建【module】完成 ****\n"));
233
+ }
234
+ let packageRoot = "";
235
+ function get_package_root() {
236
+ if (!packageRoot) {
237
+ const __filename = fileURLToPath(import.meta.url);
238
+ const __dirname = dirname(__filename);
239
+ let currentDir = node_path.resolve(__dirname);
240
+ const root = node_path.parse(currentDir).root;
241
+ while(currentDir !== root){
242
+ const potentialPkgJson = node_path.join(currentDir, "package.json");
243
+ if (node_fs.existsSync(potentialPkgJson)) break;
244
+ currentDir = node_path.dirname(currentDir);
245
+ }
246
+ debug_log("packageRoot", currentDir);
247
+ packageRoot = currentDir;
248
+ }
249
+ return packageRoot;
250
+ }
251
+ function find_workspace_root(cwd) {
252
+ let currentDir = node_path.resolve(cwd);
253
+ const root = node_path.parse(currentDir).root;
254
+ while(currentDir !== root){
255
+ const pnpmWorkspace = node_path.join(currentDir, "pnpm-workspace.yaml");
256
+ const packageJsonPath = node_path.join(currentDir, "package.json");
257
+ if (node_fs.existsSync(pnpmWorkspace)) return currentDir;
258
+ if (node_fs.existsSync(packageJsonPath)) try {
259
+ const pkg = JSON.parse(node_fs.readFileSync(packageJsonPath, "utf-8"));
260
+ if (pkg.workspaces) return currentDir;
261
+ } catch {}
262
+ currentDir = node_path.dirname(currentDir);
263
+ }
264
+ }
265
+ const auto_external_plugin_require = createRequire(import.meta.url);
266
+ class AutoExternalPlugin {
267
+ externalLibNames;
268
+ usedExternals;
269
+ args;
270
+ config;
271
+ constructor(args, config){
272
+ this.args = args;
273
+ this.config = config;
274
+ this.externalLibNames = Object.keys(config.externals);
275
+ this.usedExternals = new Set();
276
+ }
277
+ apply(compiler) {
278
+ compiler.hooks.compilation.tap("AutoExternalPlugin", (compilation)=>{
279
+ compilation.hooks.finishModules.tap("AutoExternalPlugin", (modules)=>{
280
+ for (const module of modules){
281
+ const constructorName = module.constructor.name;
282
+ const request = module.request;
283
+ const userRequest = module.userRequest;
284
+ const resource = module.resource;
285
+ const externalType = module.externalType;
286
+ if ('ExternalModule' === constructorName || externalType) {
287
+ const libName = request || userRequest;
288
+ if (libName && this.externalLibNames.includes(libName)) {
289
+ this.usedExternals.add(libName);
290
+ continue;
291
+ }
292
+ }
293
+ if (resource && resource.includes("node_modules")) {
294
+ for (const libName of this.externalLibNames)if (resource.includes(`/node_modules/${libName}/`) || resource.includes(`\\node_modules\\${libName}\\`)) this.usedExternals.add(libName);
295
+ } else if (resource && resource.includes("/node_modules/.pnpm/")) {
296
+ for (const libName of this.externalLibNames)if (resource.includes(`/node_modules/.pnpm/${libName}@`) || resource.includes(`/node_modules/.pnpm/${libName}+`) || resource.includes(`/node_modules/${libName}/`)) this.usedExternals.add(libName);
297
+ }
298
+ }
299
+ });
300
+ compiler.hooks.emit.tapAsync("AutoExternalPlugin", (compilation, cb)=>{
301
+ if (process.env.DEBUG) console.log('[AutoExternalPlugin] emit hook triggered');
302
+ const assetNames = Object.keys(compilation.assets);
303
+ if (process.env.DEBUG) console.log('[AutoExternalPlugin] Assets:', assetNames);
304
+ cb();
305
+ });
306
+ let HtmlWebpackPlugin;
307
+ const htmlPluginInstance = compiler.options.plugins.find((p)=>p && ("HtmlWebpackPlugin" === p.constructor.name || "HtmlRspackPlugin" === p.constructor.name));
308
+ if (htmlPluginInstance) HtmlWebpackPlugin = htmlPluginInstance.constructor;
309
+ if (!HtmlWebpackPlugin) HtmlWebpackPlugin = compiler.webpack.HtmlRspackPlugin || compiler.webpack.HtmlWebpackPlugin;
310
+ if (!HtmlWebpackPlugin) try {
311
+ HtmlWebpackPlugin = auto_external_plugin_require('@rspack/plugin-html').HtmlRspackPlugin;
312
+ } catch (e) {}
313
+ if (!HtmlWebpackPlugin) return;
314
+ if ('function' != typeof HtmlWebpackPlugin.getHooks) return;
315
+ const hooks = HtmlWebpackPlugin.getHooks(compilation);
316
+ hooks.alterAssetTags.tapAsync("AutoExternalPlugin", (data, cb)=>{
317
+ if (data.assetTags && data.assetTags.scripts) this.processTags(data, "assetTags.scripts");
318
+ cb(null, data);
319
+ });
320
+ });
321
+ }
322
+ processTags(data, targetProp) {
323
+ if (!this.config.autoExternal) return data;
324
+ const { importMap } = getExternalsAndImportMap(this.args, this.config.externals, this.config.externalsType);
325
+ const filteredImportMap = Object.fromEntries(Object.entries(importMap).filter(([key])=>this.usedExternals.has(key)));
326
+ if (0 === Object.keys(filteredImportMap).length) return data;
327
+ let tags = [];
328
+ tags = "script" === this.config.externalsType ? Object.values(filteredImportMap).map((url)=>({
329
+ tagName: "script",
330
+ voidTag: false,
331
+ attributes: {
332
+ src: url
333
+ }
334
+ })) : [
335
+ {
336
+ tagName: "script",
337
+ voidTag: false,
338
+ attributes: {
339
+ type: "importmap"
340
+ },
341
+ innerHTML: JSON.stringify({
342
+ imports: filteredImportMap
343
+ }, null, 2)
344
+ }
345
+ ];
346
+ if ('headTags' === targetProp) data.headTags.unshift(...tags);
347
+ else if ("assetTags.scripts" === targetProp) data.assetTags.scripts.unshift(...tags);
348
+ else if ('head' === targetProp) data.head.unshift(...tags);
349
+ return data;
350
+ }
351
+ }
352
+ async function page_pack(args) {
353
+ const config = await get_global_config(args);
354
+ const { entries, externals } = prepare_config(args, "page", config);
355
+ if (!entries) return;
356
+ const workspaceRoot = find_workspace_root(process.cwd());
357
+ const rsbuildConfig = core_defineConfig({
358
+ source: {
359
+ define: config.define,
360
+ entry: entries
361
+ },
362
+ plugins: [
363
+ framework_plugin(config),
364
+ pluginLess()
365
+ ],
366
+ tools: {
367
+ rspack: {
368
+ experiments: {
369
+ outputModule: "importmap" === config.externalsType ? true : void 0
370
+ },
371
+ plugins: [
372
+ new AutoExternalPlugin(args, config)
373
+ ]
374
+ }
375
+ },
376
+ output: {
377
+ assetPrefix: config.url.cdn || config.url.base,
378
+ distPath: {
379
+ root: config.output.dist
380
+ },
381
+ externals,
382
+ filenameHash: config.output.filenameHash,
383
+ legalComments: "none",
384
+ minify: config.minify
385
+ },
386
+ html: {
387
+ meta: config.html.meta,
388
+ mountId: config.html.root,
389
+ scriptLoading: "importmap" === config.externalsType ? void 0 : "module",
390
+ tags: config.html.tags,
391
+ template: config.html.template || resolve(get_package_root(), "template/index.html"),
392
+ templateParameters: {
393
+ base_prefix: config.url.base
394
+ },
395
+ title: config.html.title
396
+ },
397
+ resolve: {
398
+ alias: config.alias
399
+ },
400
+ server: {
401
+ publicDir: workspaceRoot ? {
402
+ name: workspaceRoot,
403
+ copyOnBuild: false,
404
+ watch: false
405
+ } : void 0,
406
+ open: config.dev_server.open ? config.dev_server.open.map((name)=>config.url.base + (name.endsWith("html") ? `/${name}` : `/${name}.html`)) : false,
407
+ port: config.dev_server.port,
408
+ proxy: config.dev_server.proxy
409
+ },
410
+ performance: {
411
+ chunkSplit: {
412
+ strategy: "split-by-experience"
413
+ }
414
+ }
415
+ });
416
+ console.log("Dev Server Config:", JSON.stringify(rsbuildConfig.server, null, 2));
417
+ const rsbuild = await createRsbuild({
418
+ rsbuildConfig
419
+ });
420
+ if ("dev" === args.cmd) await rsbuild.startDevServer();
421
+ else if ("preview" === args.cmd) await rsbuild.preview();
422
+ else await rsbuild.build({
423
+ watch: args.pack.watch
424
+ });
425
+ if ("build" === args.cmd) console.log(picocolors.green("\n**** 构建【page】完成 ****"));
426
+ }
427
+ async function pack_code(args) {
428
+ const { target } = args;
429
+ if ("preview" === args.cmd) return void await page_pack(args);
430
+ if ("all" === target && "dev" === args.cmd) return void await Promise.all([
431
+ page_pack(args),
432
+ lib_pack(args)
433
+ ]);
434
+ if ("page" === target || "all" === target) await page_pack(args);
435
+ if ("module" === target || "all" === target) await lib_pack(args);
436
+ }
437
+ export { pack_code };