@snack-kit/scripts 0.5.0 → 0.7.0
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/README.md +89 -108
- package/bin/main.js +118 -45
- package/config/webpack.loader.config.js +2 -1
- package/config/webpack.shared.js +1 -1
- package/config/webpack.snack.config.js +2 -2
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -10,25 +10,29 @@ npm install @snack-kit/scripts --save-dev
|
|
|
10
10
|
|
|
11
11
|
## 命令
|
|
12
12
|
|
|
13
|
-
| 命令
|
|
14
|
-
|
|
15
|
-
| `snack-
|
|
16
|
-
| `snack-
|
|
17
|
-
| `snack-
|
|
18
|
-
| `snack-
|
|
19
|
-
| `snack-
|
|
13
|
+
| 命令 | 说明 |
|
|
14
|
+
|------------------------|---------------|
|
|
15
|
+
| `snack-cli init [dir]` | 初始化新 snack 工程 |
|
|
16
|
+
| `snack-cli create` | 在当前工程创建新模块模版 |
|
|
17
|
+
| `snack-cli start` | 启动开发调试服务 |
|
|
18
|
+
| `snack-cli build` | 生产模式打包 |
|
|
19
|
+
| `snack-cli entry` | 打包独立入口页面 |
|
|
20
|
+
|
|
21
|
+
> `snack-scripts` 作为历史兼容别名保留,与 `snack-cli` 完全等价。
|
|
20
22
|
|
|
21
23
|
### init — 初始化工程
|
|
22
24
|
|
|
23
25
|
```bash
|
|
24
26
|
# 在当前目录初始化
|
|
25
|
-
snack-
|
|
27
|
+
snack-cli init
|
|
26
28
|
|
|
27
29
|
# 在指定目录初始化
|
|
28
|
-
snack-
|
|
30
|
+
snack-cli init my-project
|
|
29
31
|
```
|
|
30
32
|
|
|
31
|
-
交互式提问:项目名、描述、作者、调试服务地址、入口页面 id/type
|
|
33
|
+
交互式提问:项目名、描述、作者、调试服务地址、入口页面 id/type、React 版本(17 / 18 / 19)。
|
|
34
|
+
|
|
35
|
+
提示语言跟随系统语言自动切换(中文 / English)。
|
|
32
36
|
|
|
33
37
|
生成文件:
|
|
34
38
|
|
|
@@ -47,10 +51,10 @@ my-project/
|
|
|
47
51
|
在 snack 工程根目录执行:
|
|
48
52
|
|
|
49
53
|
```bash
|
|
50
|
-
snack-
|
|
54
|
+
snack-cli create
|
|
51
55
|
```
|
|
52
56
|
|
|
53
|
-
|
|
57
|
+
交互式提问:模块名称、目录名(PascalCase)、描述、作者、是否生成 setting 模块。
|
|
54
58
|
|
|
55
59
|
生成文件(以 `UserManager` 为例):
|
|
56
60
|
|
|
@@ -66,113 +70,77 @@ src/package/UserManager/
|
|
|
66
70
|
└── setting.scss
|
|
67
71
|
```
|
|
68
72
|
|
|
73
|
+
初始化生成的 `package.json` scripts:
|
|
74
|
+
|
|
69
75
|
```json
|
|
70
76
|
{
|
|
71
77
|
"scripts": {
|
|
72
|
-
"start": "snack-
|
|
73
|
-
"build": "snack-
|
|
74
|
-
"entry": "snack-
|
|
78
|
+
"start": "snack-cli start",
|
|
79
|
+
"build": "snack-cli build",
|
|
80
|
+
"entry": "snack-cli entry"
|
|
75
81
|
}
|
|
76
82
|
}
|
|
77
83
|
```
|
|
78
84
|
|
|
79
85
|
## package.json 配置项
|
|
80
86
|
|
|
81
|
-
```
|
|
87
|
+
```json
|
|
82
88
|
{
|
|
83
|
-
|
|
84
|
-
:
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
:
|
|
88
|
-
"
|
|
89
|
-
|
|
90
|
-
:
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
:
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
:
|
|
114
|
-
"portal", // 所加载的页面分类(可选)
|
|
115
|
-
"title"
|
|
116
|
-
:
|
|
117
|
-
"My App", // HTML 页面 title(可选)
|
|
118
|
-
"favicon"
|
|
119
|
-
:
|
|
120
|
-
"./favicon.ico", // 浏览器角标路径,相对项目根路径(可选)
|
|
121
|
-
"service"
|
|
122
|
-
:
|
|
123
|
-
"", // snackbar 服务端地址,默认使用当前地址栏(可选)
|
|
124
|
-
"devServer"
|
|
125
|
-
:
|
|
126
|
-
"", // 调试服务网关(可选)
|
|
127
|
-
"mobile"
|
|
128
|
-
:
|
|
129
|
-
{ // 移动端页面配置,竖屏或宽度 < 1024px 时加载(可选)
|
|
130
|
-
"id"
|
|
131
|
-
:
|
|
132
|
-
"my_page_mobile",
|
|
133
|
-
"type"
|
|
134
|
-
:
|
|
135
|
-
"portal"
|
|
136
|
-
}
|
|
137
|
-
,
|
|
138
|
-
"files"
|
|
139
|
-
:
|
|
140
|
-
[], // 需复制到发布目录的文件或目录路径(可选)
|
|
141
|
-
"js"
|
|
142
|
-
:
|
|
143
|
-
"./plugin.ts", // 外挂打包的 JS/TS 文件路径(可选)
|
|
144
|
-
"css"
|
|
145
|
-
:
|
|
146
|
-
"./plugin.scss", // 外挂打包的 CSS/SCSS 文件路径(可选)
|
|
147
|
-
"template"
|
|
148
|
-
:
|
|
149
|
-
{ // 自定义 HTML 模板路径,相对项目根路径(可选)
|
|
150
|
-
"index"
|
|
151
|
-
:
|
|
152
|
-
"./public/index.html",
|
|
153
|
-
"dev"
|
|
154
|
-
:
|
|
155
|
-
"./public/dev.html",
|
|
156
|
-
"entry"
|
|
157
|
-
:
|
|
158
|
-
"./public/entry.html"
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
,
|
|
162
|
-
"plugin"
|
|
163
|
-
:
|
|
164
|
-
{ // snack 模块独立 index.html 外挂文件(可选)
|
|
165
|
-
"js"
|
|
166
|
-
:
|
|
167
|
-
"./plugin.ts",
|
|
168
|
-
"css"
|
|
169
|
-
:
|
|
170
|
-
"./plugin.scss"
|
|
171
|
-
}
|
|
89
|
+
"input": "./src/package",
|
|
90
|
+
"output": "./dist",
|
|
91
|
+
"snack": {
|
|
92
|
+
"externals": {},
|
|
93
|
+
"buildIgnore": [],
|
|
94
|
+
"devPackage": [],
|
|
95
|
+
"entry": {
|
|
96
|
+
"name": "entry",
|
|
97
|
+
"id": "my_page",
|
|
98
|
+
"type": "portal",
|
|
99
|
+
"title": "My App",
|
|
100
|
+
"favicon": "./favicon.ico",
|
|
101
|
+
"service": "",
|
|
102
|
+
"devServer": "",
|
|
103
|
+
"mobile": {
|
|
104
|
+
"id": "my_page_mobile",
|
|
105
|
+
"type": "portal"
|
|
106
|
+
},
|
|
107
|
+
"files": [],
|
|
108
|
+
"js": "./plugin.ts",
|
|
109
|
+
"css": "./plugin.scss",
|
|
110
|
+
"template": {
|
|
111
|
+
"index": "./public/index.html",
|
|
112
|
+
"dev": "./public/dev.html",
|
|
113
|
+
"entry": "./public/entry.html"
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
"plugin": {
|
|
117
|
+
"js": "./plugin.ts",
|
|
118
|
+
"css": "./plugin.scss"
|
|
172
119
|
}
|
|
120
|
+
}
|
|
173
121
|
}
|
|
174
122
|
```
|
|
175
123
|
|
|
124
|
+
| 字段 | 说明 | 默认值 |
|
|
125
|
+
|-------------------------|------------------------------|-----------------|
|
|
126
|
+
| `input` | snack 模块目录 | `"src/package"` |
|
|
127
|
+
| `output` | 生产输出目录 | `"dist"` |
|
|
128
|
+
| `snack.externals` | 同 webpack externals,过滤不打包的依赖 | `{}` |
|
|
129
|
+
| `snack.buildIgnore` | 生产打包忽略的模块(模块目录名) | `[]` |
|
|
130
|
+
| `snack.devPackage` | 开发模式仅启动指定模块,空数组表示全部启动 | `[]` |
|
|
131
|
+
| `snack.entry.name` | 入口页输出目录名 | `"entry"` |
|
|
132
|
+
| `snack.entry.id` | 所加载的页面 id | — |
|
|
133
|
+
| `snack.entry.type` | 所加载的页面分类 | — |
|
|
134
|
+
| `snack.entry.title` | HTML 页面 title | — |
|
|
135
|
+
| `snack.entry.favicon` | 浏览器角标路径,相对项目根路径 | — |
|
|
136
|
+
| `snack.entry.service` | snackbar 服务端地址,默认使用当前地址栏 | — |
|
|
137
|
+
| `snack.entry.devServer` | 调试服务网关 | — |
|
|
138
|
+
| `snack.entry.mobile` | 移动端页面配置,竖屏或宽度 < 1024px 时加载 | — |
|
|
139
|
+
| `snack.entry.files` | 需复制到发布目录的文件或目录路径 | `[]` |
|
|
140
|
+
| `snack.entry.js` | 外挂打包的 JS/TS 文件路径 | — |
|
|
141
|
+
| `snack.entry.css` | 外挂打包的 CSS/SCSS 文件路径 | — |
|
|
142
|
+
| `snack.entry.template` | 自定义 HTML 模板路径,相对项目根路径 | — |
|
|
143
|
+
|
|
176
144
|
## config-overrides.js
|
|
177
145
|
|
|
178
146
|
在项目根目录创建 `config-overrides.js` 可自定义 webpack 配置:
|
|
@@ -191,9 +159,9 @@ module.exports = (config) => {
|
|
|
191
159
|
```json
|
|
192
160
|
{
|
|
193
161
|
"scripts": {
|
|
194
|
-
"start": "snack-
|
|
195
|
-
"build": "snack-
|
|
196
|
-
"entry": "snack-
|
|
162
|
+
"start": "snack-cli start --templatePath=template",
|
|
163
|
+
"build": "snack-cli build --templatePath=template",
|
|
164
|
+
"entry": "snack-cli entry --templatePath=template"
|
|
197
165
|
}
|
|
198
166
|
}
|
|
199
167
|
```
|
|
@@ -202,6 +170,19 @@ module.exports = (config) => {
|
|
|
202
170
|
|
|
203
171
|
## Changelog
|
|
204
172
|
|
|
173
|
+
### 0.7.0
|
|
174
|
+
|
|
175
|
+
- 修复: 修复 loader.js 打包丢失的问题
|
|
176
|
+
|
|
177
|
+
### 0.6.0
|
|
178
|
+
|
|
179
|
+
- 新增:`snack-cli` 命令别名,与 `snack-scripts` 完全等价,`snack-scripts` 保留作为历史兼容
|
|
180
|
+
- 新增:`init` 命令支持交互式选择 React 版本(17 / 18 / 19),生成对应依赖版本
|
|
181
|
+
- 新增:CLI 提示语言跟随系统语言自动切换(`LANG` 环境变量,中文 / English)
|
|
182
|
+
- 修复:`init` 生成的 `@snack-kit/core` 版本从 `^0.1.0` 修正为 `^0.3.0`
|
|
183
|
+
- 修复:`init` 生成的 `scripts` 命令从 `snack-scripts` 更新为 `snack-cli`
|
|
184
|
+
- 优化:升级 `sass-loader` 至 v13,启用 Modern API(`api: 'modern'`),消除 Dart Sass Legacy JS API deprecation 警告
|
|
185
|
+
|
|
205
186
|
### 0.5.0
|
|
206
187
|
|
|
207
188
|
- 修复:默认渲染高度的问题
|
package/bin/main.js
CHANGED
|
@@ -29,6 +29,58 @@ const platform = process.platform;
|
|
|
29
29
|
const webpackFile = platform === 'win32' ? 'webpack.cmd' : 'webpack';
|
|
30
30
|
const isNpm = fs.existsSync(path.resolve(process.cwd(), './node_modules/.bin/', webpackFile));
|
|
31
31
|
|
|
32
|
+
// ─── 语言检测 ─────────────────────────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
function detectLang() {
|
|
35
|
+
const env = process.env.LANG || process.env.LANGUAGE || process.env.LC_ALL || process.env.LC_MESSAGES || '';
|
|
36
|
+
return env.toLowerCase().startsWith('zh') ? 'zh' : 'en';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const lang = detectLang();
|
|
40
|
+
const t = {
|
|
41
|
+
// init
|
|
42
|
+
initTitle: { zh: ' Snack 项目初始化', en: ' Snack Project Init' },
|
|
43
|
+
projectName: { zh: '项目名称', en: 'Project name' },
|
|
44
|
+
description: { zh: '项目描述', en: 'Description' },
|
|
45
|
+
author: { zh: '作者', en: 'Author' },
|
|
46
|
+
debugServers: { zh: '调试服务器(多个用逗号分隔)', en: 'Debug servers (comma separated)' },
|
|
47
|
+
entryPageId: { zh: '入口页面 ID', en: 'Entry page id' },
|
|
48
|
+
entryPageType: { zh: '入口页面类型', en: 'Entry page type' },
|
|
49
|
+
reactVersion: { zh: 'React 版本', en: 'React version' },
|
|
50
|
+
projectCreated: { zh: ' 项目已创建:', en: ' Project created at:' },
|
|
51
|
+
nextSteps: { zh: ' 后续步骤:', en: ' Next steps:' },
|
|
52
|
+
// create
|
|
53
|
+
createTitle: { zh: ' Snack 模块创建', en: ' Snack Module Create' },
|
|
54
|
+
moduleName: { zh: '模块名称', en: 'Module name' },
|
|
55
|
+
moduleDirName: { zh: '模块目录名(PascalCase)', en: 'Module directory name (PascalCase)' },
|
|
56
|
+
withSetting: { zh: '生成配置模块?(y/n)', en: 'Generate setting module? (y/n)' },
|
|
57
|
+
moduleCreated: { zh: ' 模块已创建:', en: ' Module created:' },
|
|
58
|
+
filesGenerated: { zh: ' 已生成文件:', en: ' Files generated:' },
|
|
59
|
+
// errors
|
|
60
|
+
errNoPkg: { zh: '错误:当前目录没有 package.json,请在 snack 工程根目录下执行该命令', en: 'Error: No package.json found. Run this command in a snack project root.' },
|
|
61
|
+
errDirRequired: { zh: '错误:模块目录名不能为空', en: 'Error: Module directory name is required' },
|
|
62
|
+
errDirExists: { zh: '错误:模块目录已存在:', en: 'Error: Module directory already exists:' },
|
|
63
|
+
errNameConflict: { zh: '请修改 snack-cli package.json "name" 的默认名称,该名称将在部署时作为分类目录', en: 'Please change the default "name" in package.json. It will be used as a category directory during deployment.' },
|
|
64
|
+
errNoEntry: { zh: 'package.json 未找到 snack.entry 配置项', en: 'snack.entry config not found in package.json' },
|
|
65
|
+
errTempDir: { zh: '临时目录创建失败', en: 'Failed to create temp directory' },
|
|
66
|
+
errIntegrity: { zh: '完整性校验失败', en: 'Integrity check failed' },
|
|
67
|
+
// build logs
|
|
68
|
+
clearOutputDir: { zh: '清理输出目录', en: 'clear output dir' },
|
|
69
|
+
clearOutputDirEnd: { zh: '清理完成', en: 'clear output dir end' },
|
|
70
|
+
devServerRunning: { zh: 'Snack 开发服务器运行中...', en: 'Snack DevServer Runing...' },
|
|
71
|
+
createLoaderAndHTML: { zh: '生成 loader.js 和入口 HTML(并行)...', en: 'create loader.js & entry HTML (parallel) ...' },
|
|
72
|
+
createLoaderAndHTMLEnd: { zh: '生成完成', en: 'create loader.js & entry HTML end' },
|
|
73
|
+
createSnack: { zh: '生成 snack 模块...', en: 'create snack ...' },
|
|
74
|
+
createSnackEnd: { zh: '生成完成', en: 'create snack end' },
|
|
75
|
+
createEntry: { zh: '生成入口页...', en: 'create entry ...' },
|
|
76
|
+
integrityPass: { zh: '完整性校验通过', en: 'Integrity check passed' },
|
|
77
|
+
integrityFileMissing: { zh: '完整性校验:文件缺失', en: 'snack check: file is missing' },
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
function i(key) {
|
|
81
|
+
return t[key][lang];
|
|
82
|
+
}
|
|
83
|
+
|
|
32
84
|
// ─── 交互式提问工具 ───────────────────────────────────────────────────────────
|
|
33
85
|
|
|
34
86
|
function prompt(rl, question, defaultValue) {
|
|
@@ -41,36 +93,59 @@ function prompt(rl, question, defaultValue) {
|
|
|
41
93
|
});
|
|
42
94
|
}
|
|
43
95
|
|
|
96
|
+
function select(rl, question, options, defaultValue) {
|
|
97
|
+
return new Promise(resolve => {
|
|
98
|
+
const hint = options.map((o, i) => `${i + 1}) ${o}`).join(' ');
|
|
99
|
+
const defaultHint = options.includes(defaultValue) ? defaultValue : options[0];
|
|
100
|
+
rl.question(`${question} [${hint}] (${defaultHint}): `, answer => {
|
|
101
|
+
const val = answer.trim();
|
|
102
|
+
if (val === '') return resolve(defaultHint);
|
|
103
|
+
const num = parseInt(val, 10);
|
|
104
|
+
if (!isNaN(num) && num >= 1 && num <= options.length) return resolve(options[num - 1]);
|
|
105
|
+
if (options.includes(val)) return resolve(val);
|
|
106
|
+
resolve(defaultHint);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
44
111
|
// ─── init 命令:初始化新 snack 工程 ──────────────────────────────────────────
|
|
45
112
|
|
|
46
113
|
async function runInit() {
|
|
47
114
|
const targetDir = argv._[1] ? path.resolve(process.cwd(), argv._[1]) : process.cwd();
|
|
48
115
|
const dirName = path.basename(targetDir);
|
|
49
116
|
|
|
50
|
-
console.log('\n
|
|
117
|
+
console.log(`\n${i('initTitle')}\n`);
|
|
51
118
|
|
|
52
119
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
53
120
|
|
|
54
|
-
const name
|
|
55
|
-
const description
|
|
56
|
-
const author
|
|
57
|
-
const debugInput
|
|
58
|
-
const entryId
|
|
59
|
-
const entryType
|
|
121
|
+
const name = await prompt(rl, i('projectName'), dirName);
|
|
122
|
+
const description = await prompt(rl, i('description'), '');
|
|
123
|
+
const author = await prompt(rl, i('author'), '');
|
|
124
|
+
const debugInput = await prompt(rl, i('debugServers'), 'http://127.0.0.1:3000');
|
|
125
|
+
const entryId = await prompt(rl, i('entryPageId'), name);
|
|
126
|
+
const entryType = await prompt(rl, i('entryPageType'), 'portal');
|
|
127
|
+
const reactVersion = await select(rl, i('reactVersion'), ['17', '18', '19'], '19');
|
|
60
128
|
|
|
61
129
|
rl.close();
|
|
62
130
|
|
|
63
131
|
const debugServers = debugInput.split(',').map(s => s.trim()).filter(Boolean);
|
|
64
132
|
|
|
133
|
+
const reactVersionMap = {
|
|
134
|
+
'17': { react: '^17.0.0', reactDom: '^17.0.0', typesReact: '^17.0.0', typesReactDom: '^17.0.0' },
|
|
135
|
+
'18': { react: '^18.0.0', reactDom: '^18.0.0', typesReact: '^18.0.0', typesReactDom: '^18.0.0' },
|
|
136
|
+
'19': { react: '^19.0.0', reactDom: '^19.0.0', typesReact: '^19.0.0', typesReactDom: '^19.0.0' },
|
|
137
|
+
};
|
|
138
|
+
const reactDeps = reactVersionMap[reactVersion];
|
|
139
|
+
|
|
65
140
|
// ── package.json ─────────────────────────────────────────────────────────
|
|
66
141
|
const pkg = {
|
|
67
142
|
name,
|
|
68
143
|
version: '1.0.0',
|
|
69
144
|
description,
|
|
70
145
|
scripts: {
|
|
71
|
-
start: 'snack-
|
|
72
|
-
build: 'snack-
|
|
73
|
-
entry: 'snack-
|
|
146
|
+
start: 'snack-cli start',
|
|
147
|
+
build: 'snack-cli build',
|
|
148
|
+
entry: 'snack-cli entry'
|
|
74
149
|
},
|
|
75
150
|
input: './src/package',
|
|
76
151
|
output: './dist',
|
|
@@ -90,13 +165,13 @@ async function runInit() {
|
|
|
90
165
|
author,
|
|
91
166
|
license: 'ISC',
|
|
92
167
|
dependencies: {
|
|
93
|
-
'@snack-kit/core': '^0.
|
|
94
|
-
'react':
|
|
95
|
-
'react-dom':
|
|
168
|
+
'@snack-kit/core': '^0.3.0',
|
|
169
|
+
'react': reactDeps.react,
|
|
170
|
+
'react-dom': reactDeps.reactDom
|
|
96
171
|
},
|
|
97
172
|
devDependencies: {
|
|
98
|
-
'@types/react':
|
|
99
|
-
'@types/react-dom':
|
|
173
|
+
'@types/react': reactDeps.typesReact,
|
|
174
|
+
'@types/react-dom': reactDeps.typesReactDom
|
|
100
175
|
},
|
|
101
176
|
dev: { debug: debugServers }
|
|
102
177
|
};
|
|
@@ -150,9 +225,9 @@ declare module '*.bmp'
|
|
|
150
225
|
await fs.outputFile(path.join(targetDir, 'src/env.d.ts'), envDts);
|
|
151
226
|
|
|
152
227
|
console.log(`
|
|
153
|
-
|
|
228
|
+
${i('projectCreated')} ${targetDir}
|
|
154
229
|
|
|
155
|
-
|
|
230
|
+
${i('nextSteps')}
|
|
156
231
|
${targetDir !== process.cwd() ? `cd ${argv._[1]}\n ` : ''}npm install
|
|
157
232
|
npm run start
|
|
158
233
|
`);
|
|
@@ -161,45 +236,43 @@ declare module '*.bmp'
|
|
|
161
236
|
// ─── create 命令:在当前工程创建新模块模版 ────────────────────────────────────
|
|
162
237
|
|
|
163
238
|
async function runCreate() {
|
|
164
|
-
// 确认在一个 snack 工程目录下
|
|
165
239
|
const pkgPath = path.resolve(projectPath, 'package.json');
|
|
166
240
|
if (!fs.existsSync(pkgPath)) {
|
|
167
|
-
console.error('
|
|
241
|
+
console.error(i('errNoPkg'));
|
|
168
242
|
process.exit(1);
|
|
169
243
|
}
|
|
170
244
|
const projectPkg = fs.readJSONSync(pkgPath);
|
|
171
245
|
const packageDir = path.resolve(projectPath, projectPkg.input || 'src/package');
|
|
172
246
|
|
|
173
|
-
console.log('\n
|
|
247
|
+
console.log(`\n${i('createTitle')}\n`);
|
|
174
248
|
|
|
175
249
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
176
250
|
|
|
177
|
-
const
|
|
178
|
-
let dirName = await prompt(rl, '
|
|
179
|
-
const description = await prompt(rl, '
|
|
180
|
-
const author = await prompt(rl, '
|
|
181
|
-
const withSetting = (await prompt(rl, '
|
|
251
|
+
const moduleName = await prompt(rl, i('moduleName'), lang === 'zh' ? '新模块' : 'New Module');
|
|
252
|
+
let dirName = await prompt(rl, i('moduleDirName'), '');
|
|
253
|
+
const description = await prompt(rl, i('description'), '');
|
|
254
|
+
const author = await prompt(rl, i('author'), projectPkg.author || '');
|
|
255
|
+
const withSetting = (await prompt(rl, i('withSetting'), 'y')).toLowerCase() === 'y';
|
|
182
256
|
|
|
183
257
|
rl.close();
|
|
184
258
|
|
|
185
259
|
if (!dirName) {
|
|
186
|
-
console.error('
|
|
260
|
+
console.error(i('errDirRequired'));
|
|
187
261
|
process.exit(1);
|
|
188
262
|
}
|
|
189
263
|
|
|
190
|
-
// 首字母大写
|
|
191
264
|
dirName = dirName.charAt(0).toUpperCase() + dirName.slice(1);
|
|
192
265
|
const moduleDir = path.join(packageDir, dirName);
|
|
193
266
|
const className = dirName;
|
|
194
267
|
|
|
195
268
|
if (fs.existsSync(moduleDir)) {
|
|
196
|
-
console.error(
|
|
269
|
+
console.error(`${i('errDirExists')} ${moduleDir}`);
|
|
197
270
|
process.exit(1);
|
|
198
271
|
}
|
|
199
272
|
|
|
200
273
|
// ── snack.json ────────────────────────────────────────────────────────────
|
|
201
274
|
const snackJson = {
|
|
202
|
-
name:
|
|
275
|
+
name: moduleName,
|
|
203
276
|
version: '0.0.0.1',
|
|
204
277
|
author,
|
|
205
278
|
description
|
|
@@ -268,9 +341,9 @@ export class ${className}Setting extends SnackSetting {
|
|
|
268
341
|
}
|
|
269
342
|
|
|
270
343
|
console.log(`
|
|
271
|
-
|
|
344
|
+
${i('moduleCreated')} ${moduleDir}
|
|
272
345
|
|
|
273
|
-
|
|
346
|
+
${i('filesGenerated')}
|
|
274
347
|
${dirName}/snack.json
|
|
275
348
|
${dirName}/index.ts
|
|
276
349
|
${dirName}/src/index.tsx
|
|
@@ -305,7 +378,7 @@ async function check(output) {
|
|
|
305
378
|
if (!await fs.exists(snackjson)) continue;
|
|
306
379
|
const index = path.join(output, dirname, 'index.js');
|
|
307
380
|
if (!await fs.exists(index)) {
|
|
308
|
-
console.error('
|
|
381
|
+
console.error(`${i('integrityFileMissing')}: ${index}`);
|
|
309
382
|
return false;
|
|
310
383
|
}
|
|
311
384
|
}
|
|
@@ -313,14 +386,14 @@ async function check(output) {
|
|
|
313
386
|
console.error('snack check: ', err);
|
|
314
387
|
return false;
|
|
315
388
|
}
|
|
316
|
-
console.log('
|
|
389
|
+
console.log(i('integrityPass'));
|
|
317
390
|
return true;
|
|
318
391
|
}
|
|
319
392
|
|
|
320
393
|
async function run(script) {
|
|
321
394
|
const projectPackageJSON = fs.readJSONSync(path.resolve(projectPath, 'package.json'));
|
|
322
395
|
if (projectPackageJSON.name === 'snack-cli') {
|
|
323
|
-
throw '
|
|
396
|
+
throw i('errNameConflict');
|
|
324
397
|
}
|
|
325
398
|
|
|
326
399
|
process.env.SNACK_CLI_VERSION = version;
|
|
@@ -337,17 +410,17 @@ async function run(script) {
|
|
|
337
410
|
await fs.remove(process.env.PROJECT_TEMPLATE_PATH);
|
|
338
411
|
const err = await fs.copy(templatePath, process.env.PROJECT_TEMPLATE_PATH);
|
|
339
412
|
if (err) {
|
|
340
|
-
console.error('
|
|
413
|
+
console.error(i('errTempDir'));
|
|
341
414
|
throw err;
|
|
342
415
|
}
|
|
343
416
|
|
|
344
417
|
process.env.PROJECT_SNACK_CONFIG = JSON.stringify(projectPackageJSON.snack || {});
|
|
345
418
|
|
|
346
419
|
if (script === 'entry') {
|
|
347
|
-
if (!projectPackageJSON.snack?.entry) throw '
|
|
420
|
+
if (!projectPackageJSON.snack?.entry) throw i('errNoEntry');
|
|
348
421
|
process.env.RUN_MODE = 'production';
|
|
349
422
|
process.env.PROJECT_OUT_PATH = path.resolve(projectPath, projectPackageJSON.snack.entry.name || 'entry');
|
|
350
|
-
console.log('
|
|
423
|
+
console.log(i('createEntry'));
|
|
351
424
|
await execWebpack(['--mode=production', `--config=${entryConfigPath}`]);
|
|
352
425
|
} else {
|
|
353
426
|
if (script === 'start') {
|
|
@@ -360,28 +433,28 @@ async function run(script) {
|
|
|
360
433
|
|
|
361
434
|
process.env.PROJECT_PACKAGE_LIST = JSON.stringify(GetPackageList(process.env.PROJECT_PACKAGE_PATH));
|
|
362
435
|
|
|
363
|
-
console.log(
|
|
436
|
+
console.log(`${i('clearOutputDir')} "${process.env.PROJECT_OUT_PATH}" ...`);
|
|
364
437
|
clearOutput(process.env.PROJECT_OUT_PATH);
|
|
365
|
-
console.log('
|
|
438
|
+
console.log(i('clearOutputDirEnd'));
|
|
366
439
|
|
|
367
440
|
if (script === 'start') {
|
|
368
|
-
console.log('
|
|
441
|
+
console.log(i('devServerRunning'));
|
|
369
442
|
await execWebpack(['serve', '--mode=development', `--config=${devConfigPath}`]);
|
|
370
443
|
} else {
|
|
371
|
-
console.log(
|
|
444
|
+
console.log(i('createLoaderAndHTML'));
|
|
372
445
|
await Promise.all([
|
|
373
446
|
execWebpack(['--mode=production', `--config=${loaderConfigPath}`]),
|
|
374
447
|
execWebpack(['--mode=production', `--config=${indexHTMLPath}`])
|
|
375
448
|
]);
|
|
376
|
-
console.log('
|
|
377
|
-
console.log('
|
|
449
|
+
console.log(i('createLoaderAndHTMLEnd'));
|
|
450
|
+
console.log(i('createSnack'));
|
|
378
451
|
await execWebpack(['--mode=production', `--config=${snackPath}`]);
|
|
379
|
-
console.log('
|
|
452
|
+
console.log(i('createSnackEnd'));
|
|
380
453
|
}
|
|
381
454
|
|
|
382
455
|
if (process.env.RUN_MODE !== 'development' && !await check(process.env.PROJECT_OUT_PATH)) {
|
|
383
456
|
fs.removeSync(process.env.PROJECT_OUT_PATH);
|
|
384
|
-
throw '
|
|
457
|
+
throw i('errIntegrity');
|
|
385
458
|
}
|
|
386
459
|
}
|
|
387
460
|
|
|
@@ -2,7 +2,7 @@ const path = require('path');
|
|
|
2
2
|
const fs = require('fs-extra');
|
|
3
3
|
const minimist = require('minimist');
|
|
4
4
|
const { injectIndexFile } = require('../utils/package');
|
|
5
|
-
const { createResolve, createModuleRules, createOptimization, filesystemCache } = require('./webpack.shared');
|
|
5
|
+
const { createResolve, createModuleRules, createOptimization, filesystemCache, resolveLoader } = require('./webpack.shared');
|
|
6
6
|
|
|
7
7
|
const argv = minimist(process.argv.slice(2), { default: { mode: 'development' } });
|
|
8
8
|
const isDevelopment = argv.mode === 'development';
|
|
@@ -36,6 +36,7 @@ module.exports = {
|
|
|
36
36
|
rules: createModuleRules()
|
|
37
37
|
},
|
|
38
38
|
externals: {},
|
|
39
|
+
resolveLoader,
|
|
39
40
|
resolve: createResolve(),
|
|
40
41
|
optimization: createOptimization(isProduction)
|
|
41
42
|
};
|
package/config/webpack.shared.js
CHANGED
|
@@ -151,7 +151,7 @@ function createSwcRule(withRefresh = false) {
|
|
|
151
151
|
*/
|
|
152
152
|
const styleRule = {
|
|
153
153
|
test: /\.(css|sass|scss)$/,
|
|
154
|
-
use: ['style-loader', 'css-loader', 'sass-loader']
|
|
154
|
+
use: ['style-loader', 'css-loader', { loader: 'sass-loader', options: { api: 'modern' } }]
|
|
155
155
|
};
|
|
156
156
|
|
|
157
157
|
/**
|
|
@@ -56,8 +56,8 @@ let conf = {
|
|
|
56
56
|
externals: {
|
|
57
57
|
react: 'react',
|
|
58
58
|
'react-dom': 'react-dom',
|
|
59
|
-
'@snack-kit/lib': '
|
|
60
|
-
'@snack-kit/core': 'snack-core',
|
|
59
|
+
'@snack-kit/lib': 'snack-kit-lib',
|
|
60
|
+
'@snack-kit/core': 'snack-kit-core',
|
|
61
61
|
...externals
|
|
62
62
|
},
|
|
63
63
|
module: {
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@snack-kit/scripts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "snack-cli package scripts Powered by Para FED",
|
|
5
5
|
"bin": {
|
|
6
|
-
"snack-scripts": "./bin/main.js"
|
|
6
|
+
"snack-scripts": "./bin/main.js",
|
|
7
|
+
"snack-cli": "./bin/main.js"
|
|
7
8
|
},
|
|
8
9
|
"files": [
|
|
9
10
|
"bin",
|
|
@@ -33,8 +34,6 @@
|
|
|
33
34
|
"@babel/preset-react": "^7.24.7",
|
|
34
35
|
"@babel/preset-typescript": "^7.24.7",
|
|
35
36
|
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
|
|
36
|
-
"react": "^19.0.0",
|
|
37
|
-
"react-dom": "^19.0.0",
|
|
38
37
|
"@snack-kit/core": "^0.3.0",
|
|
39
38
|
"@snack-kit/lib": "^0.6.0",
|
|
40
39
|
"@swc/core": "^1.2.100",
|
|
@@ -45,10 +44,12 @@
|
|
|
45
44
|
"fs-extra": "^8.1.0",
|
|
46
45
|
"html-webpack-plugin": "^5.3.2",
|
|
47
46
|
"minimist": "^1.2.8",
|
|
47
|
+
"react": "^19.0.0",
|
|
48
|
+
"react-dom": "^19.0.0",
|
|
48
49
|
"react-refresh": "^0.11.0",
|
|
49
50
|
"regenerator-runtime": "^0.13.9",
|
|
50
51
|
"sass": "^1.77.2",
|
|
51
|
-
"sass-loader": "^
|
|
52
|
+
"sass-loader": "^13.3.3",
|
|
52
53
|
"style-loader": "^3.2.1",
|
|
53
54
|
"swc-loader": "^0.1.15",
|
|
54
55
|
"typescript": "^4.4.2",
|