@yannick-z/modulo 0.2.0 → 0.3.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/.vscode/extensions.json +3 -0
- package/README.md +57 -60
- package/bin/modulo.js +29 -19
- package/biome.json +34 -0
- package/package.json +36 -35
- package/rslib.config.ts +19 -19
- package/src/args/get-framework-name.ts +7 -7
- package/src/args/index.ts +16 -74
- package/src/args/preset.ts +16 -16
- package/src/cli/init.ts +10 -6
- package/src/cli/pack-code.ts +20 -9
- package/src/config/example/example-config.ts +50 -39
- package/src/config/example/example-externals.ts +21 -37
- package/src/config/index.ts +186 -16
- package/src/config/presets.ts +100 -0
- package/src/config/type.ts +34 -12
- package/src/index.ts +104 -10
- package/src/initiator/create-config-file.ts +52 -36
- package/src/initiator/create-project.ts +249 -0
- package/src/initiator/modify-scripts.ts +42 -42
- package/src/packer/auto-external-plugin.ts +205 -0
- package/src/packer/collect-modules.ts +58 -69
- package/src/packer/get-externals-and-tags.ts +82 -55
- package/src/packer/lib.ts +78 -70
- package/src/packer/page.ts +105 -82
- package/src/packer/prepare.ts +63 -57
- package/src/tools/cli.ts +21 -0
- package/src/tools/file.ts +84 -14
- package/src/tools/find-path-root.ts +52 -25
- package/src/tools/get-framework-name.ts +7 -7
- package/src/tools/get-ui-plugin.ts +27 -13
- package/src/tools/json.ts +63 -9
- package/src/tools/log.ts +58 -0
- package/src/tools/merge-user-config.ts +17 -17
- package/src/tools/omit-root-path.ts +17 -7
- package/src/tools/panic.ts +12 -8
- package/src/tools/string.ts +13 -2
- package/src/type/guard.ts +22 -3
- package/tsconfig.json +9 -9
- package/dist/index.js +0 -773
- package/src/args/cmd.ts +0 -16
- package/src/args/mode.ts +0 -38
- package/src/args/node_env.ts +0 -15
- package/src/args/target.ts +0 -44
- package/src/config/externals.ts +0 -70
- package/src/config/generate_config.ts +0 -105
- package/src/config/preset/alias.ts +0 -3
- package/src/config/preset/dev-server.ts +0 -6
- package/src/config/preset/dirs.ts +0 -12
- package/src/config/preset/html.ts +0 -19
- package/src/config/preset/index.ts +0 -23
- package/src/config/preset/libs.ts +0 -5
- package/src/config/preset/minify.ts +0 -24
- package/src/config/preset/url.ts +0 -4
- package/src/tools/debug-log.ts +0 -37
package/src/packer/page.ts
CHANGED
|
@@ -4,95 +4,118 @@ import { pluginLess } from "@rsbuild/plugin-less";
|
|
|
4
4
|
import picocolors from "picocolors";
|
|
5
5
|
import type { ModuloArgs_Pack } from "../args/index.ts";
|
|
6
6
|
import { get_global_config } from "../config/index.ts";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
get_package_root,
|
|
9
|
+
find_workspace_root,
|
|
10
|
+
} from "../tools/find-path-root.ts";
|
|
8
11
|
import { framework_plugin } from "../tools/get-ui-plugin.ts";
|
|
9
|
-
import { pluginUmd } from "@rsbuild/plugin-umd";
|
|
10
12
|
import { prepare_config } from "./prepare.ts";
|
|
13
|
+
import { AutoExternalPlugin } from "./auto-external-plugin.ts";
|
|
11
14
|
|
|
15
|
+
/**
|
|
16
|
+
* 执行页面(page)打包
|
|
17
|
+
*
|
|
18
|
+
* 使用 Rsbuild 构建单页应用或多页应用。
|
|
19
|
+
*
|
|
20
|
+
* @param args CLI 参数
|
|
21
|
+
*/
|
|
12
22
|
export async function page_pack(args: ModuloArgs_Pack) {
|
|
13
|
-
|
|
23
|
+
const config = await get_global_config(args);
|
|
14
24
|
|
|
15
|
-
|
|
16
|
-
args,
|
|
17
|
-
"page",
|
|
18
|
-
config
|
|
19
|
-
);
|
|
25
|
+
const { entries, externals } = prepare_config(args, "page", config);
|
|
20
26
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
27
|
+
if (!entries) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
24
30
|
|
|
25
|
-
|
|
26
|
-
source: {
|
|
27
|
-
define: config.define,
|
|
28
|
-
entry: entries,
|
|
29
|
-
},
|
|
30
|
-
plugins: [
|
|
31
|
-
framework_plugin(args),
|
|
32
|
-
pluginLess(),
|
|
33
|
-
pluginUmd({
|
|
34
|
-
name: "modulo-page",
|
|
35
|
-
}),
|
|
36
|
-
],
|
|
37
|
-
tools: {
|
|
38
|
-
rspack: {
|
|
39
|
-
experiments: {
|
|
40
|
-
outputModule: args.pack.esm,
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
htmlPlugin: true,
|
|
44
|
-
},
|
|
45
|
-
output: {
|
|
46
|
-
assetPrefix: config.url.cdn || config.url.base,
|
|
47
|
-
distPath: {
|
|
48
|
-
root: config.output.dist,
|
|
49
|
-
},
|
|
50
|
-
externals,
|
|
51
|
-
filenameHash: config.output.filenameHash,
|
|
52
|
-
legalComments: "none",
|
|
53
|
-
minify: config.minify,
|
|
54
|
-
},
|
|
55
|
-
html: {
|
|
56
|
-
meta: config.html.meta,
|
|
57
|
-
mountId: config.html.root,
|
|
58
|
-
scriptLoading: args.pack.esm ? "module" : "defer",
|
|
59
|
-
tags: [importmaps_tag, ...config.html.tags],
|
|
60
|
-
template:
|
|
61
|
-
config.html.template ||
|
|
62
|
-
resolve(get_package_root(), "template/index.html"),
|
|
63
|
-
templateParameters: {
|
|
64
|
-
base_prefix: config.url.base,
|
|
65
|
-
},
|
|
66
|
-
title: config.html.title,
|
|
67
|
-
},
|
|
68
|
-
resolve: {
|
|
69
|
-
alias: config.alias,
|
|
70
|
-
},
|
|
71
|
-
server: {
|
|
72
|
-
base: config.url.base,
|
|
73
|
-
open: config.dev_server.open
|
|
74
|
-
? config.dev_server.open.map(
|
|
75
|
-
(name: string) =>
|
|
76
|
-
config.url.base +
|
|
77
|
-
(name.endsWith("html") ? `/${name}` : `/${name}.html`)
|
|
78
|
-
)
|
|
79
|
-
: false,
|
|
80
|
-
port: config.dev_server.port,
|
|
81
|
-
proxy: config.dev_server.proxy,
|
|
82
|
-
},
|
|
83
|
-
performance: {
|
|
84
|
-
chunkSplit: {
|
|
85
|
-
strategy: "split-by-experience",
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
});
|
|
31
|
+
const workspaceRoot = find_workspace_root(process.cwd());
|
|
89
32
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
33
|
+
const rsbuildConfig = defineConfig({
|
|
34
|
+
source: {
|
|
35
|
+
define: config.define,
|
|
36
|
+
entry: entries,
|
|
37
|
+
},
|
|
38
|
+
plugins: [framework_plugin(config), pluginLess()],
|
|
39
|
+
tools: {
|
|
40
|
+
rspack: {
|
|
41
|
+
experiments: {
|
|
42
|
+
outputModule: config.externalsType === "importmap" ? true : undefined,
|
|
43
|
+
},
|
|
44
|
+
plugins: [
|
|
45
|
+
// @ts-ignore Rspack 插件类型兼容问题
|
|
46
|
+
new AutoExternalPlugin(args, config),
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
output: {
|
|
51
|
+
assetPrefix: config.url.cdn || config.url.base,
|
|
52
|
+
distPath: {
|
|
53
|
+
root: config.output.dist,
|
|
54
|
+
},
|
|
55
|
+
externals,
|
|
56
|
+
filenameHash: config.output.filenameHash,
|
|
57
|
+
legalComments: "none",
|
|
58
|
+
minify: config.minify,
|
|
59
|
+
},
|
|
60
|
+
html: {
|
|
61
|
+
meta: config.html.meta,
|
|
62
|
+
mountId: config.html.root,
|
|
63
|
+
scriptLoading: config.externalsType === "importmap" ? undefined : "module",
|
|
64
|
+
tags: config.html.tags,
|
|
65
|
+
template:
|
|
66
|
+
config.html.template ||
|
|
67
|
+
resolve(get_package_root(), "template/index.html"),
|
|
68
|
+
templateParameters: {
|
|
69
|
+
base_prefix: config.url.base,
|
|
70
|
+
},
|
|
71
|
+
title: config.html.title,
|
|
72
|
+
},
|
|
73
|
+
resolve: {
|
|
74
|
+
alias: config.alias,
|
|
75
|
+
},
|
|
76
|
+
server: {
|
|
77
|
+
publicDir: workspaceRoot
|
|
78
|
+
? {
|
|
79
|
+
name: workspaceRoot,
|
|
80
|
+
copyOnBuild: false,
|
|
81
|
+
watch: false,
|
|
82
|
+
}
|
|
83
|
+
: undefined,
|
|
84
|
+
open: config.dev_server.open
|
|
85
|
+
? config.dev_server.open.map(
|
|
86
|
+
(name: string) =>
|
|
87
|
+
config.url.base +
|
|
88
|
+
(name.endsWith("html") ? `/${name}` : `/${name}.html`),
|
|
89
|
+
)
|
|
90
|
+
: false,
|
|
91
|
+
port: config.dev_server.port,
|
|
92
|
+
proxy: config.dev_server.proxy,
|
|
93
|
+
},
|
|
94
|
+
performance: {
|
|
95
|
+
chunkSplit: {
|
|
96
|
+
strategy: "split-by-experience",
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
});
|
|
94
100
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
101
|
+
console.log(
|
|
102
|
+
"Dev Server Config:",
|
|
103
|
+
JSON.stringify(rsbuildConfig.server, null, 2),
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
const rsbuild = await createRsbuild({ rsbuildConfig });
|
|
107
|
+
|
|
108
|
+
if (args.cmd === "dev") {
|
|
109
|
+
await rsbuild.startDevServer();
|
|
110
|
+
} else if (args.cmd === "preview") {
|
|
111
|
+
await rsbuild.preview();
|
|
112
|
+
} else {
|
|
113
|
+
await rsbuild.build({
|
|
114
|
+
watch: args.pack.watch,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (args.cmd === "build") {
|
|
119
|
+
console.log(picocolors.green("\n**** 构建【page】完成 ****"));
|
|
120
|
+
}
|
|
98
121
|
}
|
package/src/packer/prepare.ts
CHANGED
|
@@ -2,75 +2,81 @@ import picocolors from "picocolors";
|
|
|
2
2
|
import type { ModuloArgs_Pack } from "../args/index.ts";
|
|
3
3
|
import { collect_modules } from "./collect-modules.ts";
|
|
4
4
|
import { omit_root_path_for_entries } from "../tools/omit-root-path.ts";
|
|
5
|
-
import {
|
|
5
|
+
import { getExternalsAndImportMap } from "./get-externals-and-tags.ts";
|
|
6
6
|
import type { GLOBAL_CONFIG } from "../config/type.ts";
|
|
7
7
|
|
|
8
8
|
let printed = false;
|
|
9
9
|
|
|
10
10
|
export function prepare_config(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
args: ModuloArgs_Pack,
|
|
12
|
+
kind: "page" | "module",
|
|
13
|
+
config: GLOBAL_CONFIG,
|
|
14
14
|
) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
config.externals
|
|
18
|
-
);
|
|
15
|
+
console.log(picocolors.blueBright(`\n**** 开始构建 【${kind}】 ****`));
|
|
16
|
+
const entries = collect_modules(args, kind, config);
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
18
|
+
if (!entries) {
|
|
19
|
+
console.log(picocolors.red(`\n没有要构建的${kind},跳过\n`));
|
|
20
|
+
} else {
|
|
21
|
+
console.log(
|
|
22
|
+
`${picocolors.blue(`\n${kind} entries:`)}\n${JSON.stringify(
|
|
23
|
+
omit_root_path_for_entries(entries),
|
|
24
|
+
null,
|
|
25
|
+
2,
|
|
26
|
+
)}\n`,
|
|
27
|
+
);
|
|
28
|
+
}
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
2
|
|
35
|
-
)}\n`
|
|
36
|
-
);
|
|
37
|
-
}
|
|
30
|
+
const { externals, importMap } = getExternalsAndImportMap(
|
|
31
|
+
args,
|
|
32
|
+
config.externals,
|
|
33
|
+
config.externalsType,
|
|
34
|
+
);
|
|
38
35
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
};
|
|
36
|
+
!printed &&
|
|
37
|
+
console.log(
|
|
38
|
+
`${picocolors.blue("\nexternals:")}\n${JSON.stringify(
|
|
39
|
+
externals,
|
|
40
|
+
null,
|
|
41
|
+
2,
|
|
42
|
+
)}\n`,
|
|
43
|
+
);
|
|
48
44
|
|
|
49
|
-
|
|
50
|
-
console.log(
|
|
51
|
-
`${picocolors.blue("\nimportmaps:")}\n${JSON.stringify(
|
|
52
|
-
importmaps,
|
|
53
|
-
null,
|
|
54
|
-
2
|
|
55
|
-
)}\n`
|
|
56
|
-
);
|
|
45
|
+
let importMapsTag: any;
|
|
57
46
|
|
|
58
|
-
|
|
47
|
+
if (config.externalsType === "script") {
|
|
48
|
+
// script 注入模式,生成多个 script 标签
|
|
49
|
+
importMapsTag = Object.values(importMap).map((url) => ({
|
|
50
|
+
tag: "script",
|
|
51
|
+
attrs: { src: url },
|
|
52
|
+
append: false,
|
|
53
|
+
head: true,
|
|
54
|
+
}));
|
|
55
|
+
} else {
|
|
56
|
+
// importmap 模式
|
|
57
|
+
importMapsTag = [
|
|
58
|
+
{
|
|
59
|
+
append: false,
|
|
60
|
+
head: true,
|
|
61
|
+
tag: "script",
|
|
62
|
+
attrs: { type: "importmap" },
|
|
63
|
+
children: `{
|
|
64
|
+
"imports": ${JSON.stringify(importMap, null, 2)}
|
|
65
|
+
}`,
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
}
|
|
59
69
|
|
|
60
|
-
|
|
61
|
-
|
|
70
|
+
!printed &&
|
|
71
|
+
console.log(
|
|
72
|
+
`${picocolors.blue("\nimportmaps/scripts:")}\n${JSON.stringify(
|
|
73
|
+
importMap,
|
|
74
|
+
null,
|
|
75
|
+
2,
|
|
76
|
+
)}\n`,
|
|
77
|
+
);
|
|
62
78
|
|
|
63
|
-
|
|
64
|
-
console.log(picocolors.red(`\n没有要构建的${kind},跳过\n`));
|
|
65
|
-
} else {
|
|
66
|
-
console.log(
|
|
67
|
-
`${picocolors.blue(`\n${kind} entries:`)}\n${JSON.stringify(
|
|
68
|
-
omit_root_path_for_entries(entries),
|
|
69
|
-
null,
|
|
70
|
-
2
|
|
71
|
-
)}\n`
|
|
72
|
-
);
|
|
73
|
-
}
|
|
79
|
+
printed = true;
|
|
74
80
|
|
|
75
|
-
|
|
81
|
+
return { entries, externals, importMapsTag };
|
|
76
82
|
}
|
package/src/tools/cli.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import readline from "node:readline";
|
|
2
|
+
import picocolors from "picocolors";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* CLI 交互式确认
|
|
6
|
+
* @param message 提示信息
|
|
7
|
+
* @returns Promise<boolean> 用户是否确认 (Y/y 为 true)
|
|
8
|
+
*/
|
|
9
|
+
export async function confirm(message: string): Promise<boolean> {
|
|
10
|
+
const rl = readline.createInterface({
|
|
11
|
+
input: process.stdin,
|
|
12
|
+
output: process.stdout,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
rl.question(`${picocolors.yellow(message)} (Y/n) `, (answer) => {
|
|
17
|
+
rl.close();
|
|
18
|
+
resolve(answer.toLowerCase() === "y" || answer === "");
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
}
|
package/src/tools/file.ts
CHANGED
|
@@ -1,19 +1,89 @@
|
|
|
1
|
-
import { readFileSync } from
|
|
2
|
-
import { resolve } from
|
|
3
|
-
import picocolors from
|
|
4
|
-
import { debug_log } from
|
|
1
|
+
import { readFileSync, readdirSync, existsSync, statSync } from "node:fs";
|
|
2
|
+
import { resolve, join } from "node:path";
|
|
3
|
+
import picocolors from "picocolors";
|
|
4
|
+
import { debug_log } from "./log.ts";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
/**
|
|
7
|
+
* 读取文件内容
|
|
8
|
+
* @param path 文件绝对路径
|
|
9
|
+
* @param error_msg 自定义错误消息(可选)
|
|
10
|
+
* @param throwError 是否抛出错误(默认 false)
|
|
11
|
+
* @returns 文件内容字符串,如果失败则返回空字符串(除非 throwError 为 true)
|
|
12
|
+
*/
|
|
13
|
+
export function read_file(
|
|
14
|
+
path: string,
|
|
15
|
+
error_msg?: string,
|
|
16
|
+
throwError = false,
|
|
17
|
+
) {
|
|
18
|
+
try {
|
|
19
|
+
return readFileSync(path, "utf8");
|
|
20
|
+
} catch (error) {
|
|
21
|
+
const msg = error_msg || `文件无法访问或者不存在: ${path}`;
|
|
22
|
+
debug_log("read_file error", msg, error);
|
|
23
|
+
if (throwError) {
|
|
24
|
+
throw new Error(msg);
|
|
25
|
+
}
|
|
26
|
+
console.log(picocolors.red(msg));
|
|
27
|
+
return "";
|
|
28
|
+
}
|
|
13
29
|
}
|
|
14
30
|
|
|
31
|
+
/**
|
|
32
|
+
* 解析路径并读取文件
|
|
33
|
+
*/
|
|
15
34
|
export function resolve_and_read(root: string, name: string) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
35
|
+
const fullpath = resolve(root, name);
|
|
36
|
+
debug_log(`resolve file: ${name}`, "result is:", fullpath);
|
|
37
|
+
return read_file(fullpath);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 获取指定目录下的所有子目录名称
|
|
42
|
+
* @param path 目标目录路径
|
|
43
|
+
* @returns 子目录名称列表
|
|
44
|
+
*/
|
|
45
|
+
export function get_directories(path: string): string[] {
|
|
46
|
+
try {
|
|
47
|
+
if (!existsSync(path)) return [];
|
|
48
|
+
return readdirSync(path).filter((file) => {
|
|
49
|
+
const fullPath = join(path, file);
|
|
50
|
+
return statSync(fullPath).isDirectory();
|
|
51
|
+
});
|
|
52
|
+
} catch (error) {
|
|
53
|
+
debug_log("get_directories error", path, error);
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 在目录中查找入口文件
|
|
60
|
+
* @param dir 目标目录
|
|
61
|
+
* @param candidates 候选文件名(不含扩展名)列表,优先级按顺序
|
|
62
|
+
* @param extensions 支持的扩展名列表,优先级按顺序
|
|
63
|
+
* @returns 找到的入口文件绝对路径,如果未找到返回 undefined
|
|
64
|
+
*/
|
|
65
|
+
export function find_entry_file(
|
|
66
|
+
dir: string,
|
|
67
|
+
candidates: string[],
|
|
68
|
+
extensions: string[] = [".ts", ".tsx", ".js", ".jsx", ".vue"],
|
|
69
|
+
): string | undefined {
|
|
70
|
+
for (const name of candidates) {
|
|
71
|
+
for (const ext of extensions) {
|
|
72
|
+
const filename = `${name}${ext}`;
|
|
73
|
+
const filepath = join(dir, filename);
|
|
74
|
+
if (existsSync(filepath) && statSync(filepath).isFile()) {
|
|
75
|
+
return filepath;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 检查文件是否存在
|
|
84
|
+
*/
|
|
85
|
+
export function exists(path: string): boolean {
|
|
86
|
+
const isExist = existsSync(path);
|
|
87
|
+
debug_log(`check exists: ${path}`, isExist);
|
|
88
|
+
return isExist;
|
|
19
89
|
}
|
|
@@ -1,29 +1,56 @@
|
|
|
1
|
-
import fs from
|
|
2
|
-
import path, { dirname } from
|
|
3
|
-
import { fileURLToPath } from
|
|
4
|
-
import { debug_log } from
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path, { dirname } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { debug_log } from "./log.ts";
|
|
5
5
|
|
|
6
|
-
let packageRoot =
|
|
6
|
+
let packageRoot = "";
|
|
7
7
|
|
|
8
8
|
export function get_package_root() {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
9
|
+
if (!packageRoot) {
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url); // get the resolved path to the file
|
|
11
|
+
const __dirname = dirname(__filename); // get the name of the directory
|
|
12
|
+
|
|
13
|
+
let currentDir = path.resolve(__dirname);
|
|
14
|
+
const root = path.parse(currentDir).root;
|
|
15
|
+
|
|
16
|
+
while (currentDir !== root) {
|
|
17
|
+
const potentialPkgJson = path.join(currentDir, "package.json");
|
|
18
|
+
if (fs.existsSync(potentialPkgJson)) {
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
currentDir = path.dirname(currentDir);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
debug_log("packageRoot", currentDir);
|
|
25
|
+
packageRoot = currentDir;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return packageRoot;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function find_workspace_root(cwd: string) {
|
|
32
|
+
let currentDir = path.resolve(cwd);
|
|
33
|
+
const root = path.parse(currentDir).root;
|
|
34
|
+
|
|
35
|
+
while (currentDir !== root) {
|
|
36
|
+
const pnpmWorkspace = path.join(currentDir, "pnpm-workspace.yaml");
|
|
37
|
+
const packageJsonPath = path.join(currentDir, "package.json");
|
|
38
|
+
|
|
39
|
+
if (fs.existsSync(pnpmWorkspace)) {
|
|
40
|
+
return currentDir;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
44
|
+
try {
|
|
45
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
46
|
+
if (pkg.workspaces) {
|
|
47
|
+
return currentDir;
|
|
48
|
+
}
|
|
49
|
+
} catch {}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
currentDir = path.dirname(currentDir);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return undefined;
|
|
29
56
|
}
|
|
@@ -2,13 +2,13 @@ import { get_packagejson } from "../config/index.ts";
|
|
|
2
2
|
import { PANIC_IF } from "./panic.ts";
|
|
3
3
|
|
|
4
4
|
export function get_framework_name() {
|
|
5
|
-
|
|
5
|
+
const { dependencies } = get_packagejson();
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
PANIC_IF(
|
|
8
|
+
!("vue" in dependencies || "react" in dependencies),
|
|
9
|
+
"package.json中未识别到支持的ui库信息, 当前只支持vue和react",
|
|
10
|
+
);
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
// 该项目是vue还是react项目
|
|
13
|
+
return "vue" in dependencies ? "vue" : "react";
|
|
14
14
|
}
|
|
@@ -1,23 +1,37 @@
|
|
|
1
1
|
import { type PluginReactOptions, pluginReact } from "@rsbuild/plugin-react";
|
|
2
2
|
import { type PluginVueOptions, pluginVue2 } from "@rsbuild/plugin-vue2";
|
|
3
|
-
import {
|
|
3
|
+
import { get_packagejson } from "../config/index.ts";
|
|
4
|
+
import type { GLOBAL_CONFIG } from "../config/type.ts";
|
|
4
5
|
import { get_framework_name } from "./get-framework-name.ts";
|
|
5
6
|
import { PANIC_IF } from "./panic.ts";
|
|
6
7
|
import type { ModuloArgs_Pack } from "../args/index.ts";
|
|
8
|
+
import semver from "semver";
|
|
7
9
|
|
|
8
10
|
export function framework_plugin(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
global_config: GLOBAL_CONFIG,
|
|
12
|
+
options?: PluginVueOptions | PluginReactOptions,
|
|
11
13
|
) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
const { dependencies } = get_packagejson();
|
|
15
|
+
const framework_name = get_framework_name();
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
// 必须使用指定版本号的ui库,以优化代码产出
|
|
18
|
+
const version = dependencies[framework_name];
|
|
19
|
+
|
|
20
|
+
const allowed_versions = [
|
|
21
|
+
global_config.ui_lib.vue2,
|
|
22
|
+
global_config.ui_lib.react19,
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const is_valid = allowed_versions.some((allowed) => {
|
|
26
|
+
const min_version = semver.minVersion(version);
|
|
27
|
+
return min_version && semver.satisfies(min_version, `^${allowed}`);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
PANIC_IF(
|
|
31
|
+
!is_valid,
|
|
32
|
+
`package.json中只允许使用固定版本号, 并且只支持vue-2.7.16, react-19.2.4 (当前版本: ${version})`,
|
|
33
|
+
);
|
|
34
|
+
return framework_name === "vue"
|
|
35
|
+
? pluginVue2(options as any)
|
|
36
|
+
: pluginReact(options as any);
|
|
23
37
|
}
|