@qse/edu-scripts 2.0.4 → 2.1.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/CHANGELOG.md +4 -0
- package/README.md +5 -1
- package/dist/cli.mjs +354 -356
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +4 -4
- package/package.json +16 -16
- package/src/auto-refactor.ts +6 -6
- package/src/build.ts +7 -5
- package/src/cli.ts +5 -6
- package/src/commit-dist.ts +3 -2
- package/src/config/paths.ts +1 -1
- package/src/config/plugins/mock-server/defineMock.ts +1 -0
- package/src/config/plugins/mock-server/index.ts +9 -6
- package/src/config/plugins/postcss-safe-area.ts +1 -0
- package/src/config/webpackConfig.ts +8 -4
- package/src/config/webpackDevServerConfig.ts +6 -1
- package/src/deploy.ts +16 -10
- package/src/generator.ts +3 -2
- package/src/index.ts +1 -1
- package/src/start.ts +2 -1
- package/src/utils/FileSizeReporter.ts +5 -4
- package/src/utils/appConfig.ts +2 -1
- package/src/utils/beforeStart.ts +3 -2
- package/src/utils/changeDeployVersion.ts +1 -1
- package/src/utils/defineConfig.ts +1 -1
- package/src/utils/esm-register.ts +1 -0
- package/src/utils/exec.ts +1 -0
- package/src/utils/getConfig.ts +0 -2
- package/src/utils/getOverride.ts +4 -2
- package/tsdown.config.ts +1 -1
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
svn://192.168.10.168/qsedu/code/00.common/02.front-end-component/06.edu-scripts/trunk
|
|
4
4
|
|
|
5
|
+
v2 版本底层的打包工具从 webpack 迁移至 rspack,速度快了3-10x
|
|
6
|
+
|
|
5
7
|
## 运行条件
|
|
6
8
|
|
|
7
9
|
nodejs 版本至少 18+
|
|
@@ -23,7 +25,9 @@ pnpm create @qse/edu-app@latest
|
|
|
23
25
|
|
|
24
26
|
## 安装
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
如果你的项目还在使用 require.ensure,请使用 v1.15.0 版本
|
|
29
|
+
|
|
30
|
+
第一次使用这个框架,请看[老项目接入流程](/refactor)
|
|
27
31
|
|
|
28
32
|
```shell
|
|
29
33
|
npm i @qse/edu-scripts -D
|
package/dist/cli.mjs
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
|
+
import chalk from "chalk";
|
|
3
4
|
import fs from "fs-extra";
|
|
4
|
-
import
|
|
5
|
+
import semver from "semver";
|
|
5
6
|
import { globby, globbySync } from "globby";
|
|
6
7
|
import { fileURLToPath } from "node:url";
|
|
7
|
-
import
|
|
8
|
-
import semver from "semver";
|
|
8
|
+
import path from "path";
|
|
9
9
|
import yargs from "yargs";
|
|
10
|
+
import { checkbox, input, select } from "@inquirer/prompts";
|
|
11
|
+
import ora from "ora";
|
|
10
12
|
import { rspack } from "@rspack/core";
|
|
11
|
-
import
|
|
13
|
+
import filesize from "filesize";
|
|
14
|
+
import { gzipSizeSync } from "gzip-size";
|
|
15
|
+
import recursive from "recursive-readdir";
|
|
16
|
+
import stripAnsi from "strip-ansi";
|
|
12
17
|
import { RsdoctorRspackPlugin } from "@rsdoctor/rspack-plugin";
|
|
13
18
|
import ReactRefreshPlugin from "@rspack/plugin-react-refresh";
|
|
14
19
|
import HtmlWebpackPlugin from "html-webpack-plugin";
|
|
15
20
|
import path$1 from "node:path";
|
|
16
21
|
import chokidar from "chokidar";
|
|
22
|
+
import cookieParser from "cookie-parser";
|
|
17
23
|
import { debounce, memoize } from "es-toolkit";
|
|
18
24
|
import express from "express";
|
|
19
|
-
import cookieParser from "cookie-parser";
|
|
20
25
|
import multer from "multer";
|
|
21
26
|
import { pathToRegexp } from "path-to-regexp";
|
|
22
|
-
import filesize from "filesize";
|
|
23
|
-
import recursive from "recursive-readdir";
|
|
24
|
-
import stripAnsi from "strip-ansi";
|
|
25
|
-
import { gzipSizeSync } from "gzip-size";
|
|
26
|
-
import { sshSftp } from "@qse/ssh-sftp";
|
|
27
|
-
import { parse, transformFromAstSync, traverse, types } from "@babel/core";
|
|
28
|
-
import ora from "ora";
|
|
29
|
-
import { format } from "prettier";
|
|
30
|
-
import { checkbox, input, select } from "@inquirer/prompts";
|
|
31
27
|
import cp from "child_process";
|
|
32
28
|
import tmp from "tmp";
|
|
29
|
+
import { sshSftp } from "@qse/ssh-sftp";
|
|
30
|
+
import { format } from "prettier";
|
|
31
|
+
import { parse, transformFromAstSync, traverse, types } from "@babel/core";
|
|
32
|
+
import { RspackDevServer } from "@rspack/dev-server";
|
|
33
33
|
|
|
34
34
|
//#region src/utils/esm-register.ts
|
|
35
35
|
const { register } = createRequire(import.meta.url)("@swc-node/register/register");
|
|
@@ -155,6 +155,228 @@ if (appPkg$2.eslintConfig) {
|
|
|
155
155
|
console.log(chalk.yellow("export default config"));
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
//#endregion
|
|
159
|
+
//#region src/auto-refactor.ts
|
|
160
|
+
const pkg$1 = fs.readJsonSync(paths.resolveOwn("package.json"));
|
|
161
|
+
async function step(msg, callback) {
|
|
162
|
+
const spinner = ora(msg).start();
|
|
163
|
+
try {
|
|
164
|
+
await callback(spinner);
|
|
165
|
+
spinner.succeed();
|
|
166
|
+
} catch (error) {
|
|
167
|
+
spinner.fail();
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
async function autoRefactor() {
|
|
172
|
+
if (await fs.pathExists(paths.public)) {
|
|
173
|
+
console.log(chalk.green("已完成改造,不需要重复执行,如果运行报错请查看文档"));
|
|
174
|
+
console.log(`文档: ${chalk.underline(pkg$1.homepage)}`);
|
|
175
|
+
process.exit(0);
|
|
176
|
+
}
|
|
177
|
+
const appPkg = fs.readJsonSync(paths.package);
|
|
178
|
+
const name = await input({
|
|
179
|
+
message: "请输入模块名称,要求唯一,不能与其他工程相同",
|
|
180
|
+
default: appPkg.name,
|
|
181
|
+
validate: (v) => /^[a-z][a-z0-9_-]+$/.test(v) || "请按格式输入 /^[a-z][a-z0-9_-]+$/ 只能使用小写字母、连字符、下划线"
|
|
182
|
+
});
|
|
183
|
+
const version = await input({
|
|
184
|
+
message: "版本号",
|
|
185
|
+
default: "1.0.0",
|
|
186
|
+
validate: (v) => /^\d+\.\d+\.\d+$/.test(v) || "请按格式输入 /^\\d+\\.\\d+\\.\\d+$/ 例如: 1.0.0"
|
|
187
|
+
});
|
|
188
|
+
const mode = await select({
|
|
189
|
+
message: "项目使用的哪种模式",
|
|
190
|
+
choices: [
|
|
191
|
+
{
|
|
192
|
+
name: "教育子工程模式",
|
|
193
|
+
value: ""
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
name: "教育主工程模式",
|
|
197
|
+
value: "main"
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
name: "独立模式",
|
|
201
|
+
value: "single"
|
|
202
|
+
}
|
|
203
|
+
]
|
|
204
|
+
});
|
|
205
|
+
let deploy = [];
|
|
206
|
+
if (mode !== "single") deploy = await checkbox({
|
|
207
|
+
message: "项目需要部署到哪里",
|
|
208
|
+
choices: [
|
|
209
|
+
{
|
|
210
|
+
name: "校端",
|
|
211
|
+
value: "-s"
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
name: "局端",
|
|
215
|
+
value: "-b"
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
name: "公文端",
|
|
219
|
+
value: "-d"
|
|
220
|
+
}
|
|
221
|
+
],
|
|
222
|
+
validate: (v) => !!v && v.length > 0 || "必须选一个"
|
|
223
|
+
});
|
|
224
|
+
const answers = {
|
|
225
|
+
name,
|
|
226
|
+
version,
|
|
227
|
+
mode,
|
|
228
|
+
deploy
|
|
229
|
+
};
|
|
230
|
+
appPkg.name = answers.name;
|
|
231
|
+
appPkg.version = answers.version;
|
|
232
|
+
await step("创建 public 文件夹", async () => {
|
|
233
|
+
await fs.mkdir(paths.public);
|
|
234
|
+
});
|
|
235
|
+
await step("移动 js 文件夹", async () => {
|
|
236
|
+
if (await fs.pathExists(path.resolve(paths.src, "js"))) await fs.move(path.resolve(paths.src, "js"), path.resolve(paths.public, "js"));
|
|
237
|
+
});
|
|
238
|
+
await step("移动 html 文件", async () => {
|
|
239
|
+
const HTMLFiles = await globby("*.html", { cwd: paths.src });
|
|
240
|
+
for (const file of HTMLFiles) await fs.move(path.resolve(paths.src, file), path.resolve(paths.public, file));
|
|
241
|
+
});
|
|
242
|
+
await step("删除 dll 文件夹", async () => {
|
|
243
|
+
if (await fs.pathExists(path.resolve(paths.src, "dll"))) await fs.remove(path.resolve(paths.src, "dll"));
|
|
244
|
+
});
|
|
245
|
+
await step("删除没用的 babel 和 webpack 配置", async () => {
|
|
246
|
+
const deleteFiles = [
|
|
247
|
+
...await globby("{.,*}babel*"),
|
|
248
|
+
...await globby("*webpack*"),
|
|
249
|
+
...await globby("package-lock.json"),
|
|
250
|
+
paths.nodeModules,
|
|
251
|
+
paths.sshSftp
|
|
252
|
+
];
|
|
253
|
+
for (const filePath of deleteFiles) await fs.remove(filePath);
|
|
254
|
+
});
|
|
255
|
+
await step("设置项目模式", () => {
|
|
256
|
+
if (answers.mode) appPkg.edu = { mode: answers.mode };
|
|
257
|
+
});
|
|
258
|
+
await step("修改 package.json 的 scripts", () => {
|
|
259
|
+
const scripts = appPkg.scripts;
|
|
260
|
+
scripts.start = "edu-scripts start";
|
|
261
|
+
scripts.build = "edu-scripts build";
|
|
262
|
+
scripts.analyze = "edu-scripts build --analyze";
|
|
263
|
+
if (answers.mode !== "single") scripts.deploy = `edu-scripts deploy ${answers.deploy.join(" ")}`;
|
|
264
|
+
else {
|
|
265
|
+
scripts.deploy = `edu-scripts deploy`;
|
|
266
|
+
scripts["commit-dist"] = "edu-scripts commit-dist --rm-local";
|
|
267
|
+
}
|
|
268
|
+
scripts["one-key-deploy"] = "npm version patch";
|
|
269
|
+
scripts.postversion = "npm run build && npm run deploy";
|
|
270
|
+
});
|
|
271
|
+
await step("删除 babel/webpack 相关依赖", (spinner) => {
|
|
272
|
+
const deleteRe = /(babel|autoprefixer|webpack|loader|less|css|sass|hmr|ssh-sftp|regenerator-runtime|nowa|prettier)/i;
|
|
273
|
+
const deletePkgs = {
|
|
274
|
+
dependencies: [],
|
|
275
|
+
devDependencies: []
|
|
276
|
+
};
|
|
277
|
+
Object.entries(deletePkgs).forEach(([scope, pkgs]) => {
|
|
278
|
+
for (const key in appPkg[scope]) if (Object.hasOwnProperty.call(appPkg[scope], key)) {
|
|
279
|
+
if (deleteRe.test(key)) {
|
|
280
|
+
pkgs.push(key);
|
|
281
|
+
delete appPkg[scope][key];
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
spinner.clear();
|
|
286
|
+
console.log(`删除的pkgs\n${chalk.green(JSON.stringify(deletePkgs, null, 2))}\n`);
|
|
287
|
+
appPkg.devDependencies["@qse/edu-scripts"] = "^" + pkg$1.version;
|
|
288
|
+
});
|
|
289
|
+
await fs.writeFile(paths.package, JSON.stringify(appPkg, null, 2), "utf-8");
|
|
290
|
+
console.log(chalk.green(`
|
|
291
|
+
改造还未完成,剩余步骤请查看文档
|
|
292
|
+
${pkg$1.homepage}#/refactor
|
|
293
|
+
|
|
294
|
+
运行 npm i 安装依赖
|
|
295
|
+
运行 edu-scripts start 启动服务
|
|
296
|
+
`));
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
//#endregion
|
|
300
|
+
//#region src/utils/FileSizeReporter.ts
|
|
301
|
+
function canReadAsset(asset) {
|
|
302
|
+
return /\.(js|css)$/.test(asset) && !/service-worker\.js/.test(asset) && !/precache-manifest\.[0-9a-f]+\.js/.test(asset);
|
|
303
|
+
}
|
|
304
|
+
function printFileSizesAfterBuild(webpackStats, previousSizeMap, buildFolder, maxBundleGzipSize, maxChunkGzipSize) {
|
|
305
|
+
const root = previousSizeMap.root;
|
|
306
|
+
const sizes = previousSizeMap.sizes;
|
|
307
|
+
const assets = (webpackStats.stats || [webpackStats]).map((stats) => stats.toJson({
|
|
308
|
+
all: false,
|
|
309
|
+
assets: true
|
|
310
|
+
}).assets.filter((asset) => canReadAsset(asset.name)).map((asset) => {
|
|
311
|
+
const size = gzipSizeSync(fs.readFileSync(path.join(root, asset.name)));
|
|
312
|
+
const previousSize = sizes[removeFileNameHash(root, asset.name)];
|
|
313
|
+
const difference = getDifferenceLabel(size, previousSize);
|
|
314
|
+
return {
|
|
315
|
+
folder: path.join(path.basename(buildFolder), path.dirname(asset.name)),
|
|
316
|
+
name: path.basename(asset.name),
|
|
317
|
+
size,
|
|
318
|
+
sizeLabel: filesize(size) + (difference ? " (" + difference + ")" : "")
|
|
319
|
+
};
|
|
320
|
+
})).reduce((single, all) => all.concat(single), []);
|
|
321
|
+
if (assets.length === 0) return;
|
|
322
|
+
console.log("\ngzip 后文件大小:\n");
|
|
323
|
+
assets.sort((a, b) => b.size - a.size);
|
|
324
|
+
const mainAssetIdx = assets.findIndex((asset) => /_\d+\.\d+\.\d+/.test(asset.name));
|
|
325
|
+
assets.unshift(assets.splice(mainAssetIdx, 1)[0]);
|
|
326
|
+
const longestSizeLabelLength = Math.max.apply(null, assets.map((a) => stripAnsi(a.sizeLabel).length));
|
|
327
|
+
let suggestBundleSplitting = false;
|
|
328
|
+
assets.forEach((asset) => {
|
|
329
|
+
let sizeLabel = asset.sizeLabel;
|
|
330
|
+
const sizeLength = stripAnsi(sizeLabel).length;
|
|
331
|
+
if (sizeLength < longestSizeLabelLength) {
|
|
332
|
+
const rightPadding = " ".repeat(longestSizeLabelLength - sizeLength);
|
|
333
|
+
sizeLabel += rightPadding;
|
|
334
|
+
}
|
|
335
|
+
const isMainBundle = /_\d+\.\d+\.\d+/.test(asset.name);
|
|
336
|
+
const maxRecommendedSize = isMainBundle ? maxBundleGzipSize : maxChunkGzipSize;
|
|
337
|
+
const isLarge = maxRecommendedSize && asset.size > maxRecommendedSize;
|
|
338
|
+
if (isLarge && path.extname(asset.name) === ".js") suggestBundleSplitting = true;
|
|
339
|
+
console.log(" " + (isLarge ? chalk.yellow(sizeLabel) : sizeLabel) + " " + chalk.dim(asset.folder + path.sep) + chalk.cyan(asset.name));
|
|
340
|
+
if (isMainBundle) console.log("");
|
|
341
|
+
});
|
|
342
|
+
if (suggestBundleSplitting) {
|
|
343
|
+
console.log();
|
|
344
|
+
console.log(chalk.yellow(`产物大小明显大于推荐的大小 (主文件 ${filesize(maxBundleGzipSize)}, chunk ${filesize(maxChunkGzipSize)}, 黄色标注为偏大)`));
|
|
345
|
+
console.log(chalk.yellow("考虑下使用代码分割解决"));
|
|
346
|
+
console.log(chalk.yellow("也可以使用 npm run analyze 命令分析产物"));
|
|
347
|
+
}
|
|
348
|
+
console.log();
|
|
349
|
+
}
|
|
350
|
+
function removeFileNameHash(buildFolder, fileName) {
|
|
351
|
+
return fileName.replace(buildFolder, "").replace(/\\/g, "/").replace(/\/\d+\.\d+\.\d+\//, "/").replace(/\/?(.*)(\.[0-9a-f]+)(\.chunk)?(\.js|\.css)/, (match, p1, p2, p3, p4) => p1 + p4);
|
|
352
|
+
}
|
|
353
|
+
function getDifferenceLabel(currentSize, previousSize) {
|
|
354
|
+
const FIFTY_KILOBYTES = 1024 * 50;
|
|
355
|
+
const difference = currentSize - previousSize;
|
|
356
|
+
const fileSize = !Number.isNaN(difference) ? filesize(difference) : 0;
|
|
357
|
+
if (difference >= FIFTY_KILOBYTES) return chalk.red("+" + fileSize);
|
|
358
|
+
else if (difference < FIFTY_KILOBYTES && difference > 0) return chalk.yellow("+" + fileSize);
|
|
359
|
+
else if (difference < 0) return chalk.green(fileSize);
|
|
360
|
+
else return "";
|
|
361
|
+
}
|
|
362
|
+
function measureFileSizesBeforeBuild(buildFolder) {
|
|
363
|
+
return new Promise((resolve) => {
|
|
364
|
+
recursive(buildFolder, (err, fileNames) => {
|
|
365
|
+
let sizes;
|
|
366
|
+
if (!err && fileNames) sizes = fileNames.filter(canReadAsset).reduce((memo, fileName) => {
|
|
367
|
+
const contents = fs.readFileSync(fileName);
|
|
368
|
+
const key = removeFileNameHash(buildFolder, fileName);
|
|
369
|
+
memo[key] = gzipSizeSync(contents);
|
|
370
|
+
return memo;
|
|
371
|
+
}, {});
|
|
372
|
+
resolve({
|
|
373
|
+
root: buildFolder,
|
|
374
|
+
sizes: sizes || {}
|
|
375
|
+
});
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
|
|
158
380
|
//#endregion
|
|
159
381
|
//#region src/utils/resolveModule.ts
|
|
160
382
|
function resolveModule(mod) {
|
|
@@ -790,129 +1012,6 @@ function getConfig(args) {
|
|
|
790
1012
|
return webpackConfig;
|
|
791
1013
|
}
|
|
792
1014
|
|
|
793
|
-
//#endregion
|
|
794
|
-
//#region src/start.ts
|
|
795
|
-
async function start(args) {
|
|
796
|
-
process.env.NODE_ENV = "development";
|
|
797
|
-
process.env.BABEL_ENV = "development";
|
|
798
|
-
process.env.BROWSERSLIST = "chrome >= 70";
|
|
799
|
-
process.env.WEBPACK_DEV_SERVER_BASE_PORT = "3000";
|
|
800
|
-
process.env.BROWSERSLIST_IGNORE_OLD_DATA = "true";
|
|
801
|
-
const basePort = process.env.WEBPACK_DEV_SERVER_BASE_PORT;
|
|
802
|
-
const port = await RspackDevServer.getFreePort(args.port || process.env.PORT);
|
|
803
|
-
if (!(args.port || process.env.PORT) && +port !== +basePort) console.log(chalk.bgYellow(`${basePort} 端口已被占用,现切换到 ${port} 端口运行`));
|
|
804
|
-
args.port = port;
|
|
805
|
-
process.env.PORT = port;
|
|
806
|
-
const config = getConfig(args);
|
|
807
|
-
const compiler = rspack(config);
|
|
808
|
-
const middleware = rspack.lazyCompilationMiddleware(compiler);
|
|
809
|
-
const oldSetupMiddlewares = config.devServer.setupMiddlewares;
|
|
810
|
-
config.devServer.setupMiddlewares = (middlewares, devServer) => {
|
|
811
|
-
if (oldSetupMiddlewares) middlewares = oldSetupMiddlewares(middlewares, devServer);
|
|
812
|
-
middlewares.unshift(middleware);
|
|
813
|
-
return middlewares;
|
|
814
|
-
};
|
|
815
|
-
const devServer = new RspackDevServer(config.devServer, compiler);
|
|
816
|
-
devServer.start();
|
|
817
|
-
["SIGINT", "SIGTERM"].forEach(function(sig) {
|
|
818
|
-
process.on(sig, function() {
|
|
819
|
-
devServer.stop();
|
|
820
|
-
process.exit();
|
|
821
|
-
});
|
|
822
|
-
});
|
|
823
|
-
if (process.env.CI !== "true") process.stdin.on("end", function() {
|
|
824
|
-
devServer.stop();
|
|
825
|
-
process.exit();
|
|
826
|
-
});
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
//#endregion
|
|
830
|
-
//#region src/utils/FileSizeReporter.ts
|
|
831
|
-
/**
|
|
832
|
-
* Copyright (c) 2015-present, Facebook, Inc.
|
|
833
|
-
*
|
|
834
|
-
* This source code is licensed under the MIT license found in the
|
|
835
|
-
* LICENSE file in the root directory of this source tree.
|
|
836
|
-
*/
|
|
837
|
-
function canReadAsset(asset) {
|
|
838
|
-
return /\.(js|css)$/.test(asset) && !/service-worker\.js/.test(asset) && !/precache-manifest\.[0-9a-f]+\.js/.test(asset);
|
|
839
|
-
}
|
|
840
|
-
function printFileSizesAfterBuild(webpackStats, previousSizeMap, buildFolder, maxBundleGzipSize, maxChunkGzipSize) {
|
|
841
|
-
const root = previousSizeMap.root;
|
|
842
|
-
const sizes = previousSizeMap.sizes;
|
|
843
|
-
const assets = (webpackStats.stats || [webpackStats]).map((stats) => stats.toJson({
|
|
844
|
-
all: false,
|
|
845
|
-
assets: true
|
|
846
|
-
}).assets.filter((asset) => canReadAsset(asset.name)).map((asset) => {
|
|
847
|
-
const size = gzipSizeSync(fs.readFileSync(path.join(root, asset.name)));
|
|
848
|
-
const previousSize = sizes[removeFileNameHash(root, asset.name)];
|
|
849
|
-
const difference = getDifferenceLabel(size, previousSize);
|
|
850
|
-
return {
|
|
851
|
-
folder: path.join(path.basename(buildFolder), path.dirname(asset.name)),
|
|
852
|
-
name: path.basename(asset.name),
|
|
853
|
-
size,
|
|
854
|
-
sizeLabel: filesize(size) + (difference ? " (" + difference + ")" : "")
|
|
855
|
-
};
|
|
856
|
-
})).reduce((single, all) => all.concat(single), []);
|
|
857
|
-
if (assets.length === 0) return;
|
|
858
|
-
console.log("\ngzip 后文件大小:\n");
|
|
859
|
-
assets.sort((a, b) => b.size - a.size);
|
|
860
|
-
const mainAssetIdx = assets.findIndex((asset) => /_\d+\.\d+\.\d+/.test(asset.name));
|
|
861
|
-
assets.unshift(assets.splice(mainAssetIdx, 1)[0]);
|
|
862
|
-
const longestSizeLabelLength = Math.max.apply(null, assets.map((a) => stripAnsi(a.sizeLabel).length));
|
|
863
|
-
let suggestBundleSplitting = false;
|
|
864
|
-
assets.forEach((asset) => {
|
|
865
|
-
let sizeLabel = asset.sizeLabel;
|
|
866
|
-
const sizeLength = stripAnsi(sizeLabel).length;
|
|
867
|
-
if (sizeLength < longestSizeLabelLength) {
|
|
868
|
-
const rightPadding = " ".repeat(longestSizeLabelLength - sizeLength);
|
|
869
|
-
sizeLabel += rightPadding;
|
|
870
|
-
}
|
|
871
|
-
const isMainBundle = /_\d+\.\d+\.\d+/.test(asset.name);
|
|
872
|
-
const maxRecommendedSize = isMainBundle ? maxBundleGzipSize : maxChunkGzipSize;
|
|
873
|
-
const isLarge = maxRecommendedSize && asset.size > maxRecommendedSize;
|
|
874
|
-
if (isLarge && path.extname(asset.name) === ".js") suggestBundleSplitting = true;
|
|
875
|
-
console.log(" " + (isLarge ? chalk.yellow(sizeLabel) : sizeLabel) + " " + chalk.dim(asset.folder + path.sep) + chalk.cyan(asset.name));
|
|
876
|
-
if (isMainBundle) console.log("");
|
|
877
|
-
});
|
|
878
|
-
if (suggestBundleSplitting) {
|
|
879
|
-
console.log();
|
|
880
|
-
console.log(chalk.yellow(`产物大小明显大于推荐的大小 (主文件 ${filesize(maxBundleGzipSize)}, chunk ${filesize(maxChunkGzipSize)}, 黄色标注为偏大)`));
|
|
881
|
-
console.log(chalk.yellow("考虑下使用代码分割解决"));
|
|
882
|
-
console.log(chalk.yellow("也可以使用 npm run analyze 命令分析产物"));
|
|
883
|
-
}
|
|
884
|
-
console.log();
|
|
885
|
-
}
|
|
886
|
-
function removeFileNameHash(buildFolder, fileName) {
|
|
887
|
-
return fileName.replace(buildFolder, "").replace(/\\/g, "/").replace(/\/\d+\.\d+\.\d+\//, "/").replace(/\/?(.*)(\.[0-9a-f]+)(\.chunk)?(\.js|\.css)/, (match, p1, p2, p3, p4) => p1 + p4);
|
|
888
|
-
}
|
|
889
|
-
function getDifferenceLabel(currentSize, previousSize) {
|
|
890
|
-
const FIFTY_KILOBYTES = 1024 * 50;
|
|
891
|
-
const difference = currentSize - previousSize;
|
|
892
|
-
const fileSize = !Number.isNaN(difference) ? filesize(difference) : 0;
|
|
893
|
-
if (difference >= FIFTY_KILOBYTES) return chalk.red("+" + fileSize);
|
|
894
|
-
else if (difference < FIFTY_KILOBYTES && difference > 0) return chalk.yellow("+" + fileSize);
|
|
895
|
-
else if (difference < 0) return chalk.green(fileSize);
|
|
896
|
-
else return "";
|
|
897
|
-
}
|
|
898
|
-
function measureFileSizesBeforeBuild(buildFolder) {
|
|
899
|
-
return new Promise((resolve) => {
|
|
900
|
-
recursive(buildFolder, (err, fileNames) => {
|
|
901
|
-
let sizes;
|
|
902
|
-
if (!err && fileNames) sizes = fileNames.filter(canReadAsset).reduce((memo, fileName) => {
|
|
903
|
-
const contents = fs.readFileSync(fileName);
|
|
904
|
-
const key = removeFileNameHash(buildFolder, fileName);
|
|
905
|
-
memo[key] = gzipSizeSync(contents);
|
|
906
|
-
return memo;
|
|
907
|
-
}, {});
|
|
908
|
-
resolve({
|
|
909
|
-
root: buildFolder,
|
|
910
|
-
sizes: sizes || {}
|
|
911
|
-
});
|
|
912
|
-
});
|
|
913
|
-
});
|
|
914
|
-
}
|
|
915
|
-
|
|
916
1015
|
//#endregion
|
|
917
1016
|
//#region src/build.ts
|
|
918
1017
|
const WARN_AFTER_BUNDLE_GZIP_SIZE = appConfig.single ? 1024 * 1024 : 30 * 1024;
|
|
@@ -957,6 +1056,82 @@ async function build(args) {
|
|
|
957
1056
|
});
|
|
958
1057
|
}
|
|
959
1058
|
|
|
1059
|
+
//#endregion
|
|
1060
|
+
//#region src/commit-dist.ts
|
|
1061
|
+
const exec = (cmd, opts) => cp.execSync(cmd, {
|
|
1062
|
+
encoding: "utf-8",
|
|
1063
|
+
stdio: "pipe",
|
|
1064
|
+
...opts
|
|
1065
|
+
});
|
|
1066
|
+
function validateSVNRoot(root) {
|
|
1067
|
+
const ls = exec(`svn ls ${root}`);
|
|
1068
|
+
return ["trunk", "branches"].every((s) => ls.includes(s));
|
|
1069
|
+
}
|
|
1070
|
+
function getWorkingCopyInfo() {
|
|
1071
|
+
exec(`svn up`);
|
|
1072
|
+
const url = exec(`svn info --show-item url`).trim();
|
|
1073
|
+
const revision = exec(`svn info --show-item last-changed-revision`).trim();
|
|
1074
|
+
const author = exec(`svn info --show-item last-changed-author`).trim();
|
|
1075
|
+
let branch = "trunk";
|
|
1076
|
+
let root = url.replace(/\/trunk$/, "");
|
|
1077
|
+
if (url.includes("/branches/")) {
|
|
1078
|
+
branch = url.split("/").pop();
|
|
1079
|
+
root = url.replace(/\/branches\/[^/]+$/, "");
|
|
1080
|
+
}
|
|
1081
|
+
let distBranchURL = root + "/branches/dist";
|
|
1082
|
+
let distBranchDirURL = distBranchURL + "/" + branch;
|
|
1083
|
+
if (!validateSVNRoot(root)) {
|
|
1084
|
+
console.log(chalk.red("SVN目录不符合规则,必须包含 trunk branches"));
|
|
1085
|
+
process.exit(1);
|
|
1086
|
+
}
|
|
1087
|
+
return {
|
|
1088
|
+
url,
|
|
1089
|
+
branch,
|
|
1090
|
+
revision,
|
|
1091
|
+
author,
|
|
1092
|
+
distBranchURL,
|
|
1093
|
+
distBranchDirURL,
|
|
1094
|
+
root
|
|
1095
|
+
};
|
|
1096
|
+
}
|
|
1097
|
+
function copyDistToRepo(info) {
|
|
1098
|
+
const tmpdir = tmp.dirSync().name;
|
|
1099
|
+
try {
|
|
1100
|
+
exec(`svn ls ${info.distBranchDirURL} --depth empty`);
|
|
1101
|
+
} catch (error) {
|
|
1102
|
+
if (error.message.includes("non-existent")) exec(`svn mkdir ${info.distBranchDirURL} --parents -m "[edu-scripts] create ${info.branch} dist"`);
|
|
1103
|
+
else throw error;
|
|
1104
|
+
}
|
|
1105
|
+
exec(`svn co ${info.distBranchDirURL} ${tmpdir}`);
|
|
1106
|
+
try {
|
|
1107
|
+
exec(`svn rm * --force -q`, { cwd: tmpdir });
|
|
1108
|
+
} catch {}
|
|
1109
|
+
fs.copySync(paths.dist, tmpdir);
|
|
1110
|
+
exec(`svn add * --force --auto-props --parents --depth infinity -q`, { cwd: tmpdir });
|
|
1111
|
+
exec(`svn ci -m "${`[edu-scripts] commit ${info.branch} dist #${info.revision} @${info.author}`}"`, { cwd: tmpdir });
|
|
1112
|
+
fs.removeSync(tmpdir);
|
|
1113
|
+
}
|
|
1114
|
+
async function commitDist(args) {
|
|
1115
|
+
if (!fs.existsSync(paths.dist)) {
|
|
1116
|
+
console.log(chalk.red("未找到 dist 文件夹,请先 edu-scpirts build"));
|
|
1117
|
+
process.exit(1);
|
|
1118
|
+
}
|
|
1119
|
+
if (exec("svn st").trim().length) {
|
|
1120
|
+
console.log(chalk.red("似乎存在未提交的代码,请提交后重试。运行 svn st 查看具体信息"));
|
|
1121
|
+
process.exit(1);
|
|
1122
|
+
}
|
|
1123
|
+
const info = getWorkingCopyInfo();
|
|
1124
|
+
console.log(chalk.green([
|
|
1125
|
+
`分支: ${info.branch}`,
|
|
1126
|
+
`版本: ${info.revision}`,
|
|
1127
|
+
`作者: ${info.author}`,
|
|
1128
|
+
`地址: ${info.distBranchDirURL}`
|
|
1129
|
+
].join("\n")));
|
|
1130
|
+
copyDistToRepo(info);
|
|
1131
|
+
if (args.rmLocal) fs.removeSync(paths.dist);
|
|
1132
|
+
console.log(chalk.green("提交完成"));
|
|
1133
|
+
}
|
|
1134
|
+
|
|
960
1135
|
//#endregion
|
|
961
1136
|
//#region src/utils/changeDeployVersion.ts
|
|
962
1137
|
const TARGET_IDENTIFIER_NAME = "project_apiArr";
|
|
@@ -1134,12 +1309,16 @@ async function normalDeploy(args) {
|
|
|
1134
1309
|
if (args.documentshelves) uploadSftpConfigs.push(presetConfig.d);
|
|
1135
1310
|
if (args.compositionshelves) uploadSftpConfigs.push(presetConfig.c);
|
|
1136
1311
|
if (args.compositionshelvesDingtalk) uploadSftpConfigs.push(presetConfig.cd);
|
|
1312
|
+
if (uploadSftpConfigs.length === 0 && fs.existsSync(paths.sshSftp)) {
|
|
1313
|
+
const config = fs.readJsonSync(paths.sshSftp);
|
|
1314
|
+
uploadSftpConfigs.push(config);
|
|
1315
|
+
}
|
|
1137
1316
|
if (uploadSftpConfigs.length === 0) {
|
|
1138
1317
|
console.log(`
|
|
1139
1318
|
${chalk.red("指定 deploy 部署范围")}
|
|
1140
1319
|
执行 ${chalk.green("npx edu-scripts deploy -h")} 查看具体用法
|
|
1141
1320
|
`);
|
|
1142
|
-
process.exit();
|
|
1321
|
+
process.exit(1);
|
|
1143
1322
|
}
|
|
1144
1323
|
const uploadConfig = {
|
|
1145
1324
|
...baseConfig,
|
|
@@ -1166,223 +1345,6 @@ function deploy(args) {
|
|
|
1166
1345
|
else normalDeploy(args);
|
|
1167
1346
|
}
|
|
1168
1347
|
|
|
1169
|
-
//#endregion
|
|
1170
|
-
//#region src/auto-refactor.ts
|
|
1171
|
-
const pkg$1 = fs.readJsonSync(paths.resolveOwn("package.json"));
|
|
1172
|
-
async function step(msg, callback) {
|
|
1173
|
-
const spinner = ora(msg).start();
|
|
1174
|
-
try {
|
|
1175
|
-
await callback(spinner);
|
|
1176
|
-
spinner.succeed();
|
|
1177
|
-
} catch (error) {
|
|
1178
|
-
spinner.fail();
|
|
1179
|
-
throw error;
|
|
1180
|
-
}
|
|
1181
|
-
}
|
|
1182
|
-
async function autoRefactor() {
|
|
1183
|
-
if (await fs.pathExists(paths.public)) {
|
|
1184
|
-
console.log(chalk.green("已完成改造,不需要重复执行,如果运行报错请查看文档"));
|
|
1185
|
-
console.log(`文档: ${chalk.underline(pkg$1.homepage)}`);
|
|
1186
|
-
process.exit(0);
|
|
1187
|
-
}
|
|
1188
|
-
const appPkg = fs.readJsonSync(paths.package);
|
|
1189
|
-
const name = await input({
|
|
1190
|
-
message: "请输入模块名称,要求唯一,不能与其他工程相同",
|
|
1191
|
-
default: appPkg.name,
|
|
1192
|
-
validate: (v) => /^[a-z][a-z0-9_-]+$/.test(v) || "请按格式输入 /^[a-z][a-z0-9_-]+$/ 只能使用小写字母、连字符、下划线"
|
|
1193
|
-
});
|
|
1194
|
-
const version = await input({
|
|
1195
|
-
message: "版本号",
|
|
1196
|
-
default: "1.0.0",
|
|
1197
|
-
validate: (v) => /^\d+\.\d+\.\d+$/.test(v) || "请按格式输入 /^\\d+\\.\\d+\\.\\d+$/ 例如: 1.0.0"
|
|
1198
|
-
});
|
|
1199
|
-
const mode = await select({
|
|
1200
|
-
message: "项目使用的哪种模式",
|
|
1201
|
-
choices: [
|
|
1202
|
-
{
|
|
1203
|
-
name: "教育子工程模式",
|
|
1204
|
-
value: ""
|
|
1205
|
-
},
|
|
1206
|
-
{
|
|
1207
|
-
name: "教育主工程模式",
|
|
1208
|
-
value: "main"
|
|
1209
|
-
},
|
|
1210
|
-
{
|
|
1211
|
-
name: "独立模式",
|
|
1212
|
-
value: "single"
|
|
1213
|
-
}
|
|
1214
|
-
]
|
|
1215
|
-
});
|
|
1216
|
-
let deploy = [];
|
|
1217
|
-
if (mode !== "single") deploy = await checkbox({
|
|
1218
|
-
message: "项目需要部署到哪里",
|
|
1219
|
-
choices: [
|
|
1220
|
-
{
|
|
1221
|
-
name: "校端",
|
|
1222
|
-
value: "-s"
|
|
1223
|
-
},
|
|
1224
|
-
{
|
|
1225
|
-
name: "局端",
|
|
1226
|
-
value: "-b"
|
|
1227
|
-
},
|
|
1228
|
-
{
|
|
1229
|
-
name: "公文端",
|
|
1230
|
-
value: "-d"
|
|
1231
|
-
}
|
|
1232
|
-
],
|
|
1233
|
-
validate: (v) => !!v && v.length > 0 || "必须选一个"
|
|
1234
|
-
});
|
|
1235
|
-
const answers = {
|
|
1236
|
-
name,
|
|
1237
|
-
version,
|
|
1238
|
-
mode,
|
|
1239
|
-
deploy
|
|
1240
|
-
};
|
|
1241
|
-
appPkg.name = answers.name;
|
|
1242
|
-
appPkg.version = answers.version;
|
|
1243
|
-
await step("创建 public 文件夹", async () => {
|
|
1244
|
-
await fs.mkdir(paths.public);
|
|
1245
|
-
});
|
|
1246
|
-
await step("移动 js 文件夹", async () => {
|
|
1247
|
-
if (await fs.pathExists(path.resolve(paths.src, "js"))) await fs.move(path.resolve(paths.src, "js"), path.resolve(paths.public, "js"));
|
|
1248
|
-
});
|
|
1249
|
-
await step("移动 html 文件", async () => {
|
|
1250
|
-
const HTMLFiles = await globby("*.html", { cwd: paths.src });
|
|
1251
|
-
for (const file of HTMLFiles) await fs.move(path.resolve(paths.src, file), path.resolve(paths.public, file));
|
|
1252
|
-
});
|
|
1253
|
-
await step("删除 dll 文件夹", async () => {
|
|
1254
|
-
if (await fs.pathExists(path.resolve(paths.src, "dll"))) await fs.remove(path.resolve(paths.src, "dll"));
|
|
1255
|
-
});
|
|
1256
|
-
await step("删除没用的 babel 和 webpack 配置", async () => {
|
|
1257
|
-
const deleteFiles = [
|
|
1258
|
-
...await globby("{.,*}babel*"),
|
|
1259
|
-
...await globby("*webpack*"),
|
|
1260
|
-
...await globby("package-lock.json"),
|
|
1261
|
-
paths.nodeModules,
|
|
1262
|
-
paths.sshSftp
|
|
1263
|
-
];
|
|
1264
|
-
for (const filePath of deleteFiles) await fs.remove(filePath);
|
|
1265
|
-
});
|
|
1266
|
-
await step("设置项目模式", () => {
|
|
1267
|
-
if (answers.mode) appPkg.edu = { mode: answers.mode };
|
|
1268
|
-
});
|
|
1269
|
-
await step("修改 package.json 的 scripts", () => {
|
|
1270
|
-
const scripts = appPkg.scripts;
|
|
1271
|
-
scripts.start = "edu-scripts start";
|
|
1272
|
-
scripts.build = "edu-scripts build";
|
|
1273
|
-
scripts.analyze = "edu-scripts build --analyze";
|
|
1274
|
-
if (answers.mode !== "single") scripts.deploy = `edu-scripts deploy ${answers.deploy.join(" ")}`;
|
|
1275
|
-
else {
|
|
1276
|
-
scripts.deploy = `edu-scripts deploy`;
|
|
1277
|
-
scripts["commit-dist"] = "edu-scripts commit-dist --rm-local";
|
|
1278
|
-
}
|
|
1279
|
-
scripts["one-key-deploy"] = "npm version patch";
|
|
1280
|
-
scripts.postversion = "npm run build && npm run deploy";
|
|
1281
|
-
});
|
|
1282
|
-
await step("删除 babel/webpack 相关依赖", (spinner) => {
|
|
1283
|
-
const deleteRe = /(babel|autoprefixer|webpack|loader|less|css|sass|hmr|ssh-sftp|regenerator-runtime|nowa|prettier)/i;
|
|
1284
|
-
const deletePkgs = {
|
|
1285
|
-
dependencies: [],
|
|
1286
|
-
devDependencies: []
|
|
1287
|
-
};
|
|
1288
|
-
Object.entries(deletePkgs).forEach(([scope, pkgs]) => {
|
|
1289
|
-
for (const key in appPkg[scope]) if (Object.hasOwnProperty.call(appPkg[scope], key)) {
|
|
1290
|
-
if (deleteRe.test(key)) {
|
|
1291
|
-
pkgs.push(key);
|
|
1292
|
-
delete appPkg[scope][key];
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
});
|
|
1296
|
-
spinner.clear();
|
|
1297
|
-
console.log(`删除的pkgs\n${chalk.green(JSON.stringify(deletePkgs, null, 2))}\n`);
|
|
1298
|
-
appPkg.devDependencies["@qse/edu-scripts"] = "^" + pkg$1.version;
|
|
1299
|
-
});
|
|
1300
|
-
await fs.writeFile(paths.package, JSON.stringify(appPkg, null, 2), "utf-8");
|
|
1301
|
-
console.log(chalk.green(`
|
|
1302
|
-
改造还未完成,剩余步骤请查看文档
|
|
1303
|
-
${pkg$1.homepage}#/refactor
|
|
1304
|
-
|
|
1305
|
-
运行 npm i 安装依赖
|
|
1306
|
-
运行 edu-scripts start 启动服务
|
|
1307
|
-
`));
|
|
1308
|
-
}
|
|
1309
|
-
|
|
1310
|
-
//#endregion
|
|
1311
|
-
//#region src/commit-dist.ts
|
|
1312
|
-
const exec = (cmd, opts) => cp.execSync(cmd, {
|
|
1313
|
-
encoding: "utf-8",
|
|
1314
|
-
stdio: "pipe",
|
|
1315
|
-
...opts
|
|
1316
|
-
});
|
|
1317
|
-
function validateSVNRoot(root) {
|
|
1318
|
-
const ls = exec(`svn ls ${root}`);
|
|
1319
|
-
return ["trunk", "branches"].every((s) => ls.includes(s));
|
|
1320
|
-
}
|
|
1321
|
-
function getWorkingCopyInfo() {
|
|
1322
|
-
exec(`svn up`);
|
|
1323
|
-
const url = exec(`svn info --show-item url`).trim();
|
|
1324
|
-
const revision = exec(`svn info --show-item last-changed-revision`).trim();
|
|
1325
|
-
const author = exec(`svn info --show-item last-changed-author`).trim();
|
|
1326
|
-
let branch = "trunk";
|
|
1327
|
-
let root = url.replace(/\/trunk$/, "");
|
|
1328
|
-
if (url.includes("/branches/")) {
|
|
1329
|
-
branch = url.split("/").pop();
|
|
1330
|
-
root = url.replace(/\/branches\/[^/]+$/, "");
|
|
1331
|
-
}
|
|
1332
|
-
let distBranchURL = root + "/branches/dist";
|
|
1333
|
-
let distBranchDirURL = distBranchURL + "/" + branch;
|
|
1334
|
-
if (!validateSVNRoot(root)) {
|
|
1335
|
-
console.log(chalk.red("SVN目录不符合规则,必须包含 trunk branches"));
|
|
1336
|
-
process.exit(1);
|
|
1337
|
-
}
|
|
1338
|
-
return {
|
|
1339
|
-
url,
|
|
1340
|
-
branch,
|
|
1341
|
-
revision,
|
|
1342
|
-
author,
|
|
1343
|
-
distBranchURL,
|
|
1344
|
-
distBranchDirURL,
|
|
1345
|
-
root
|
|
1346
|
-
};
|
|
1347
|
-
}
|
|
1348
|
-
function copyDistToRepo(info) {
|
|
1349
|
-
const tmpdir = tmp.dirSync().name;
|
|
1350
|
-
try {
|
|
1351
|
-
exec(`svn ls ${info.distBranchDirURL} --depth empty`);
|
|
1352
|
-
} catch (error) {
|
|
1353
|
-
if (error.message.includes("non-existent")) exec(`svn mkdir ${info.distBranchDirURL} --parents -m "[edu-scripts] create ${info.branch} dist"`);
|
|
1354
|
-
else throw error;
|
|
1355
|
-
}
|
|
1356
|
-
exec(`svn co ${info.distBranchDirURL} ${tmpdir}`);
|
|
1357
|
-
try {
|
|
1358
|
-
exec(`svn rm * --force -q`, { cwd: tmpdir });
|
|
1359
|
-
} catch {}
|
|
1360
|
-
fs.copySync(paths.dist, tmpdir);
|
|
1361
|
-
exec(`svn add * --force --auto-props --parents --depth infinity -q`, { cwd: tmpdir });
|
|
1362
|
-
exec(`svn ci -m "${`[edu-scripts] commit ${info.branch} dist #${info.revision} @${info.author}`}"`, { cwd: tmpdir });
|
|
1363
|
-
fs.removeSync(tmpdir);
|
|
1364
|
-
}
|
|
1365
|
-
async function commitDist(args) {
|
|
1366
|
-
if (!fs.existsSync(paths.dist)) {
|
|
1367
|
-
console.log(chalk.red("未找到 dist 文件夹,请先 edu-scpirts build"));
|
|
1368
|
-
process.exit(1);
|
|
1369
|
-
}
|
|
1370
|
-
if (exec("svn st").trim().length) {
|
|
1371
|
-
console.log(chalk.red("似乎存在未提交的代码,请提交后重试。运行 svn st 查看具体信息"));
|
|
1372
|
-
process.exit(1);
|
|
1373
|
-
}
|
|
1374
|
-
const info = getWorkingCopyInfo();
|
|
1375
|
-
console.log(chalk.green([
|
|
1376
|
-
`分支: ${info.branch}`,
|
|
1377
|
-
`版本: ${info.revision}`,
|
|
1378
|
-
`作者: ${info.author}`,
|
|
1379
|
-
`地址: ${info.distBranchDirURL}`
|
|
1380
|
-
].join("\n")));
|
|
1381
|
-
copyDistToRepo(info);
|
|
1382
|
-
if (args.rmLocal) fs.removeSync(paths.dist);
|
|
1383
|
-
console.log(chalk.green("提交完成"));
|
|
1384
|
-
}
|
|
1385
|
-
|
|
1386
1348
|
//#endregion
|
|
1387
1349
|
//#region src/generator.ts
|
|
1388
1350
|
const getTmpPath = (...args) => paths.resolveOwn("asset", "template", ...args);
|
|
@@ -1429,6 +1391,42 @@ async function generatorTailwind() {
|
|
|
1429
1391
|
].join("\n")));
|
|
1430
1392
|
}
|
|
1431
1393
|
|
|
1394
|
+
//#endregion
|
|
1395
|
+
//#region src/start.ts
|
|
1396
|
+
async function start(args) {
|
|
1397
|
+
process.env.NODE_ENV = "development";
|
|
1398
|
+
process.env.BABEL_ENV = "development";
|
|
1399
|
+
process.env.BROWSERSLIST = "chrome >= 70";
|
|
1400
|
+
process.env.WEBPACK_DEV_SERVER_BASE_PORT = "3000";
|
|
1401
|
+
process.env.BROWSERSLIST_IGNORE_OLD_DATA = "true";
|
|
1402
|
+
const basePort = process.env.WEBPACK_DEV_SERVER_BASE_PORT;
|
|
1403
|
+
const port = await RspackDevServer.getFreePort(args.port || process.env.PORT);
|
|
1404
|
+
if (!(args.port || process.env.PORT) && +port !== +basePort) console.log(chalk.bgYellow(`${basePort} 端口已被占用,现切换到 ${port} 端口运行`));
|
|
1405
|
+
args.port = port;
|
|
1406
|
+
process.env.PORT = port;
|
|
1407
|
+
const config = getConfig(args);
|
|
1408
|
+
const compiler = rspack(config);
|
|
1409
|
+
const middleware = rspack.lazyCompilationMiddleware(compiler);
|
|
1410
|
+
const oldSetupMiddlewares = config.devServer.setupMiddlewares;
|
|
1411
|
+
config.devServer.setupMiddlewares = (middlewares, devServer) => {
|
|
1412
|
+
if (oldSetupMiddlewares) middlewares = oldSetupMiddlewares(middlewares, devServer);
|
|
1413
|
+
middlewares.unshift(middleware);
|
|
1414
|
+
return middlewares;
|
|
1415
|
+
};
|
|
1416
|
+
const devServer = new RspackDevServer(config.devServer, compiler);
|
|
1417
|
+
devServer.start();
|
|
1418
|
+
["SIGINT", "SIGTERM"].forEach(function(sig) {
|
|
1419
|
+
process.on(sig, function() {
|
|
1420
|
+
devServer.stop();
|
|
1421
|
+
process.exit();
|
|
1422
|
+
});
|
|
1423
|
+
});
|
|
1424
|
+
if (process.env.CI !== "true") process.stdin.on("end", function() {
|
|
1425
|
+
devServer.stop();
|
|
1426
|
+
process.exit();
|
|
1427
|
+
});
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1432
1430
|
//#endregion
|
|
1433
1431
|
//#region src/cli.ts
|
|
1434
1432
|
const pkg = fs.readJsonSync(paths.resolveOwn("package.json"));
|
|
@@ -1446,7 +1444,7 @@ yargs(process.argv.slice(2)).usage(`教育工程化 webpack5 基础框架\n文
|
|
|
1446
1444
|
desc: "输出 html 文件",
|
|
1447
1445
|
default: false,
|
|
1448
1446
|
boolean: true
|
|
1449
|
-
}), (args) => build(args)).command("deploy", "自动部署 dist 到 v1
|
|
1447
|
+
}), (args) => build(args)).command("deploy", "自动部署 dist 到 v1 服务器,可以使用 @qse/ssh-sftp 工具生成.sftprc.json文件,或者直接使用命令行参数指定上传目标", (yargs) => yargs.option("school", {
|
|
1450
1448
|
alias: "s",
|
|
1451
1449
|
desc: "上传到校端",
|
|
1452
1450
|
default: false,
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { Chalk } from "chalk";
|
|
2
2
|
import { Compiler, Configuration, SwcLoaderOptions } from "@rspack/core";
|
|
3
|
-
import { Configuration as Configuration$1 } from "@rspack/dev-server";
|
|
4
3
|
import { RequestHandler } from "express";
|
|
4
|
+
import { Configuration as Configuration$1 } from "@rspack/dev-server";
|
|
5
5
|
|
|
6
|
+
//#region src/config/plugins/mock-server/defineMock.d.ts
|
|
7
|
+
type Method = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS' | 'CONNECT' | 'TRACE';
|
|
8
|
+
type API = string;
|
|
9
|
+
type MockConfig = Record<`${Method} ${API}`, string | number | null | undefined | boolean | Record<string, any> | RequestHandler>;
|
|
10
|
+
declare function defineMock(config: MockConfig): MockConfig;
|
|
11
|
+
//#endregion
|
|
6
12
|
//#region src/utils/defineConfig.d.ts
|
|
7
13
|
type ProxyConfigArray = NonNullable<Configuration$1['proxy']>;
|
|
8
14
|
type Configuration$2 = {
|
|
@@ -81,10 +87,4 @@ type Configuration$2 = {
|
|
|
81
87
|
};
|
|
82
88
|
declare function defineConfig(config: Configuration$2): Configuration$2;
|
|
83
89
|
//#endregion
|
|
84
|
-
//#region src/config/plugins/mock-server/defineMock.d.ts
|
|
85
|
-
type Method = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS' | 'CONNECT' | 'TRACE';
|
|
86
|
-
type API = string;
|
|
87
|
-
type MockConfig = Record<`${Method} ${API}`, string | number | null | undefined | boolean | Record<string, any> | RequestHandler>;
|
|
88
|
-
declare function defineMock(config: MockConfig): MockConfig;
|
|
89
|
-
//#endregion
|
|
90
90
|
export { defineConfig, defineMock };
|
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
//#region src/
|
|
2
|
-
function
|
|
1
|
+
//#region src/config/plugins/mock-server/defineMock.ts
|
|
2
|
+
function defineMock(config) {
|
|
3
3
|
return config;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
//#endregion
|
|
7
|
-
//#region src/
|
|
8
|
-
function
|
|
7
|
+
//#region src/utils/defineConfig.ts
|
|
8
|
+
function defineConfig(config) {
|
|
9
9
|
return config;
|
|
10
10
|
}
|
|
11
11
|
|
package/package.json
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qse/edu-scripts",
|
|
3
|
-
"version": "2.0.4",
|
|
4
|
-
"author": "Kinoko",
|
|
5
|
-
"license": "MIT",
|
|
6
3
|
"type": "module",
|
|
4
|
+
"version": "2.1.0",
|
|
7
5
|
"description": "教育工程化基础框架",
|
|
6
|
+
"author": "Kinoko",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "http://192.168.10.19:3339/qsxxwapdev/edu-scripts/",
|
|
9
|
+
"publishConfig": {
|
|
10
|
+
"registry": "https://registry.npmjs.org/",
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"main": "dist/index.mjs",
|
|
14
|
+
"types": "dist/index.d.mts",
|
|
15
|
+
"bin": {
|
|
16
|
+
"edu-scripts": "dist/cli.mjs",
|
|
17
|
+
"edu": "dist/cli.mjs"
|
|
18
|
+
},
|
|
8
19
|
"engines": {
|
|
9
20
|
"node": ">=18"
|
|
10
21
|
},
|
|
@@ -21,21 +32,10 @@
|
|
|
21
32
|
"postversion": "npm run release",
|
|
22
33
|
"test": "jest"
|
|
23
34
|
},
|
|
24
|
-
"homepage": "http://192.168.10.19:3339/qsxxwapdev/edu-scripts/",
|
|
25
|
-
"publishConfig": {
|
|
26
|
-
"registry": "https://registry.npmjs.org/",
|
|
27
|
-
"access": "public"
|
|
28
|
-
},
|
|
29
|
-
"bin": {
|
|
30
|
-
"edu-scripts": "dist/cli.mjs",
|
|
31
|
-
"edu": "dist/cli.mjs"
|
|
32
|
-
},
|
|
33
|
-
"main": "dist/index.mjs",
|
|
34
|
-
"typings": "dist/index.d.mts",
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@babel/core": "~7.29.0",
|
|
37
37
|
"@inquirer/prompts": "^8.3.0",
|
|
38
|
-
"@qse/ssh-sftp": "^1.
|
|
38
|
+
"@qse/ssh-sftp": "^1.4.0",
|
|
39
39
|
"@rsdoctor/rspack-plugin": "^1.5.2",
|
|
40
40
|
"@rspack/core": "^1.7.6",
|
|
41
41
|
"@rspack/dev-server": "^1.2.1",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"devDependencies": {
|
|
85
85
|
"@babel/preset-env": "~7.29.0",
|
|
86
86
|
"@babel/preset-typescript": "^7.28.5",
|
|
87
|
-
"@qse/eslint-config": "^1.
|
|
87
|
+
"@qse/eslint-config": "^1.1.2",
|
|
88
88
|
"@types/cookie-parser": "^1.4.10",
|
|
89
89
|
"@types/fs-extra": "^11.0.4",
|
|
90
90
|
"@types/jest": "^30.0.0",
|
package/src/auto-refactor.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import paths from './config/paths'
|
|
3
|
-
import path from 'path'
|
|
1
|
+
import { checkbox, input, select } from '@inquirer/prompts'
|
|
4
2
|
import chalk from 'chalk'
|
|
3
|
+
import fs from 'fs-extra'
|
|
5
4
|
import { globby } from 'globby'
|
|
6
5
|
import ora from 'ora'
|
|
7
|
-
import
|
|
6
|
+
import path from 'path'
|
|
7
|
+
|
|
8
|
+
import paths from './config/paths'
|
|
8
9
|
|
|
9
10
|
const pkg = fs.readJsonSync(paths.resolveOwn('package.json'))
|
|
10
11
|
|
|
@@ -39,8 +40,7 @@ export default async function autoRefactor() {
|
|
|
39
40
|
const version = await input({
|
|
40
41
|
message: '版本号',
|
|
41
42
|
default: '1.0.0',
|
|
42
|
-
validate: (v) =>
|
|
43
|
-
/^\d+\.\d+\.\d+$/.test(v) || '请按格式输入 /^\\d+\\.\\d+\\.\\d+$/ 例如: 1.0.0',
|
|
43
|
+
validate: (v) => /^\d+\.\d+\.\d+$/.test(v) || '请按格式输入 /^\\d+\\.\\d+\\.\\d+$/ 例如: 1.0.0',
|
|
44
44
|
})
|
|
45
45
|
|
|
46
46
|
const mode = await select({
|
package/src/build.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Stats } from '@rspack/core'
|
|
2
|
+
|
|
3
|
+
import { rspack } from '@rspack/core'
|
|
2
4
|
import chalk from 'chalk'
|
|
3
|
-
import getConfig from './utils/getConfig'
|
|
4
|
-
// @ts-ignore
|
|
5
|
-
import { measureFileSizesBeforeBuild, printFileSizesAfterBuild } from './utils/FileSizeReporter'
|
|
6
|
-
import paths from './config/paths'
|
|
7
5
|
import fs from 'fs-extra'
|
|
6
|
+
|
|
7
|
+
import paths from './config/paths'
|
|
8
8
|
import appConfig from './utils/appConfig'
|
|
9
|
+
import { measureFileSizesBeforeBuild, printFileSizesAfterBuild } from './utils/FileSizeReporter'
|
|
10
|
+
import getConfig from './utils/getConfig'
|
|
9
11
|
|
|
10
12
|
const WARN_AFTER_BUNDLE_GZIP_SIZE = appConfig.single ? 1024 * 1024 : 30 * 1024
|
|
11
13
|
const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024
|
package/src/cli.ts
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import './utils/esm-register'
|
|
3
|
-
|
|
4
3
|
import './utils/beforeStart'
|
|
5
4
|
|
|
6
5
|
import fs from 'fs-extra'
|
|
7
6
|
import yargs from 'yargs'
|
|
8
|
-
import paths from './config/paths'
|
|
9
7
|
|
|
10
|
-
import start from './start'
|
|
11
|
-
import build from './build'
|
|
12
|
-
import deploy from './deploy'
|
|
13
8
|
import autoRefactor from './auto-refactor'
|
|
9
|
+
import build from './build'
|
|
14
10
|
import commitDist from './commit-dist'
|
|
11
|
+
import paths from './config/paths'
|
|
12
|
+
import deploy from './deploy'
|
|
15
13
|
import * as generator from './generator'
|
|
14
|
+
import start from './start'
|
|
16
15
|
|
|
17
16
|
const pkg = fs.readJsonSync(paths.resolveOwn('package.json'))
|
|
18
17
|
|
|
@@ -46,7 +45,7 @@ yargs(process.argv.slice(2))
|
|
|
46
45
|
)
|
|
47
46
|
.command(
|
|
48
47
|
'deploy',
|
|
49
|
-
'自动部署 dist 到 v1
|
|
48
|
+
'自动部署 dist 到 v1 服务器,可以使用 @qse/ssh-sftp 工具生成.sftprc.json文件,或者直接使用命令行参数指定上传目标',
|
|
50
49
|
(yargs) =>
|
|
51
50
|
yargs
|
|
52
51
|
.option('school', { alias: 's', desc: '上传到校端', default: false, boolean: true })
|
package/src/commit-dist.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import chalk from 'chalk'
|
|
2
|
-
import paths from './config/paths'
|
|
3
|
-
import fs from 'fs-extra'
|
|
4
2
|
import cp from 'child_process'
|
|
3
|
+
import fs from 'fs-extra'
|
|
5
4
|
import tmp from 'tmp'
|
|
6
5
|
|
|
6
|
+
import paths from './config/paths'
|
|
7
|
+
|
|
7
8
|
const exec = (cmd: string, opts?: cp.ExecSyncOptions) =>
|
|
8
9
|
cp.execSync(cmd, { encoding: 'utf-8', stdio: 'pipe', ...opts }) as string
|
|
9
10
|
|
package/src/config/paths.ts
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { globbySync } from 'globby'
|
|
1
|
+
import chalk from 'chalk'
|
|
3
2
|
import chokidar from 'chokidar'
|
|
3
|
+
import cookieParser from 'cookie-parser'
|
|
4
4
|
import { debounce, memoize } from 'es-toolkit'
|
|
5
|
-
import chalk from 'chalk'
|
|
6
|
-
import fs from 'fs-extra'
|
|
7
5
|
import express from 'express'
|
|
8
|
-
import
|
|
6
|
+
import fs from 'fs-extra'
|
|
7
|
+
import { globbySync } from 'globby'
|
|
9
8
|
import multer from 'multer'
|
|
10
|
-
import { pathToRegexp } from 'path-to-regexp'
|
|
11
9
|
import { createRequire } from 'node:module'
|
|
10
|
+
import { pathToRegexp } from 'path-to-regexp'
|
|
11
|
+
|
|
12
12
|
import { resolveModule } from '@/utils/resolveModule'
|
|
13
|
+
|
|
14
|
+
import paths from '../../paths'
|
|
15
|
+
|
|
13
16
|
const require = createRequire(import.meta.url)
|
|
14
17
|
|
|
15
18
|
let mockCache: Record<string, { handler: any; method: string; path: string }> = {}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { resolveModule } from '@/utils/resolveModule'
|
|
2
|
-
import { RsdoctorRspackPlugin } from '@rsdoctor/rspack-plugin'
|
|
3
1
|
import type { Compiler, Configuration, RuleSetRule, SwcLoaderOptions } from '@rspack/core'
|
|
2
|
+
|
|
3
|
+
import { RsdoctorRspackPlugin } from '@rsdoctor/rspack-plugin'
|
|
4
4
|
import { rspack } from '@rspack/core'
|
|
5
5
|
import ReactRefreshPlugin from '@rspack/plugin-react-refresh'
|
|
6
6
|
import chalk from 'chalk'
|
|
@@ -8,11 +8,15 @@ import fs from 'fs-extra'
|
|
|
8
8
|
import HtmlWebpackPlugin from 'html-webpack-plugin'
|
|
9
9
|
import { createRequire } from 'node:module'
|
|
10
10
|
import path from 'node:path'
|
|
11
|
-
import
|
|
11
|
+
import { fileURLToPath } from 'node:url'
|
|
12
|
+
|
|
13
|
+
import { resolveModule } from '@/utils/resolveModule'
|
|
14
|
+
|
|
12
15
|
import type { Configuration as CustomConfiguration } from '../utils/defineConfig'
|
|
16
|
+
|
|
17
|
+
import appConfig from '../utils/appConfig'
|
|
13
18
|
import paths from './paths'
|
|
14
19
|
import PostcssSafeAreaPlugin from './plugins/postcss-safe-area'
|
|
15
|
-
import { fileURLToPath } from 'node:url'
|
|
16
20
|
|
|
17
21
|
const require = createRequire(import.meta.url)
|
|
18
22
|
const appPkg = fs.readJsonSync(paths.package) as { name: string; version: string }
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Configuration } from '@rspack/dev-server'
|
|
2
|
+
|
|
2
3
|
import type { Configuration as CustomConfiguration } from '../utils/defineConfig'
|
|
4
|
+
|
|
3
5
|
import setupMockServer from './plugins/mock-server'
|
|
4
6
|
|
|
5
7
|
interface ProxyConfig {
|
|
@@ -24,7 +26,10 @@ function createProxy(context: string, target: string, origin?: string): ProxyCon
|
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
export default function getWebpackDevServerConfig(
|
|
29
|
+
export default function getWebpackDevServerConfig(
|
|
30
|
+
args: any,
|
|
31
|
+
override: CustomConfiguration
|
|
32
|
+
): Configuration {
|
|
28
33
|
const host = process.env.HOST || '0.0.0.0'
|
|
29
34
|
|
|
30
35
|
const devServer: Configuration = {
|
package/src/deploy.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
import type { Options as SshSftpOptions } from '@qse/ssh-sftp'
|
|
2
|
+
|
|
2
3
|
import { sshSftp } from '@qse/ssh-sftp'
|
|
3
|
-
import paths from './config/paths.js'
|
|
4
4
|
import chalk from 'chalk'
|
|
5
5
|
import fs from 'fs-extra'
|
|
6
|
-
// @ts-ignore
|
|
7
|
-
import changeDeployVersion from './utils/changeDeployVersion'
|
|
8
6
|
import ora from 'ora'
|
|
9
|
-
import appConfig from './utils/appConfig.js'
|
|
10
7
|
import { format } from 'prettier'
|
|
11
8
|
|
|
9
|
+
import paths from './config/paths.js'
|
|
10
|
+
import appConfig from './utils/appConfig.js'
|
|
11
|
+
import changeDeployVersion from './utils/changeDeployVersion'
|
|
12
|
+
|
|
12
13
|
const appPkg = fs.readJsonSync(paths.package)
|
|
13
14
|
|
|
14
15
|
const baseConfig = {
|
|
@@ -54,9 +55,9 @@ async function normalDeploy(args: DeployArgs) {
|
|
|
54
55
|
return lines.slice(-50).join('\n')
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
async function upload(opts:
|
|
58
|
+
async function upload(opts: SshSftpOptions) {
|
|
58
59
|
// 上传dist文件
|
|
59
|
-
const { sftp, opts: fullOpts } = await sshSftp(opts)
|
|
60
|
+
const { sftp, opts: fullOpts } = (await sshSftp(opts))!
|
|
60
61
|
|
|
61
62
|
const spinner = ora('自动更新 ver.js 版本配置').start()
|
|
62
63
|
// 指定远程需要修改的文件
|
|
@@ -113,7 +114,7 @@ async function normalDeploy(args: DeployArgs) {
|
|
|
113
114
|
}
|
|
114
115
|
}
|
|
115
116
|
|
|
116
|
-
const presetConfig = {
|
|
117
|
+
const presetConfig: Record<string, SshSftpOptions> = {
|
|
117
118
|
s: { preset: { context: 'eduwebngv1', folder: 'userportal' } },
|
|
118
119
|
b: { preset: { context: 'eduwebngv1', folder: 'bureaupc' } },
|
|
119
120
|
d: { preset: { context: 'eduwebngv1', folder: 'documentshelves' } },
|
|
@@ -123,7 +124,7 @@ async function normalDeploy(args: DeployArgs) {
|
|
|
123
124
|
remotePath: '/erp/edumaven/dingcorrection-page-dev/compositionshelves',
|
|
124
125
|
},
|
|
125
126
|
}
|
|
126
|
-
const uploadSftpConfigs = []
|
|
127
|
+
const uploadSftpConfigs: SshSftpOptions[] = []
|
|
127
128
|
if (args.bureau) {
|
|
128
129
|
uploadSftpConfigs.push(presetConfig.b)
|
|
129
130
|
}
|
|
@@ -139,6 +140,11 @@ async function normalDeploy(args: DeployArgs) {
|
|
|
139
140
|
if (args.compositionshelvesDingtalk) {
|
|
140
141
|
uploadSftpConfigs.push(presetConfig.cd)
|
|
141
142
|
}
|
|
143
|
+
if (uploadSftpConfigs.length === 0 && fs.existsSync(paths.sshSftp)) {
|
|
144
|
+
const config = fs.readJsonSync(paths.sshSftp)
|
|
145
|
+
uploadSftpConfigs.push(config)
|
|
146
|
+
}
|
|
147
|
+
|
|
142
148
|
if (uploadSftpConfigs.length === 0) {
|
|
143
149
|
console.log(
|
|
144
150
|
`
|
|
@@ -146,7 +152,7 @@ async function normalDeploy(args: DeployArgs) {
|
|
|
146
152
|
执行 ${chalk.green('npx edu-scripts deploy -h')} 查看具体用法
|
|
147
153
|
`
|
|
148
154
|
)
|
|
149
|
-
process.exit()
|
|
155
|
+
process.exit(1)
|
|
150
156
|
}
|
|
151
157
|
|
|
152
158
|
const uploadConfig = { ...baseConfig, ignore: [...baseConfig.ignore, 'js/ver.js'] }
|
package/src/generator.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import chalk from 'chalk'
|
|
1
2
|
import fs from 'fs-extra'
|
|
3
|
+
|
|
2
4
|
import paths from './config/paths'
|
|
3
|
-
import chalk from 'chalk'
|
|
4
5
|
|
|
5
6
|
const getTmpPath = (...args: string[]) => paths.resolveOwn('asset', 'template', ...args)
|
|
6
7
|
|
|
@@ -56,4 +57,4 @@ async function generatorTailwind() {
|
|
|
56
57
|
)
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
export { generatorOverride as override,
|
|
60
|
+
export { generatorOverride as override, generatorTailwind as tailwind, generatorTsconfig as ts }
|
package/src/index.ts
CHANGED
package/src/start.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { rspack } from '@rspack/core'
|
|
2
2
|
import { RspackDevServer } from '@rspack/dev-server'
|
|
3
|
-
import getConfig from './utils/getConfig.js'
|
|
4
3
|
import chalk from 'chalk'
|
|
5
4
|
|
|
5
|
+
import getConfig from './utils/getConfig.js'
|
|
6
|
+
|
|
6
7
|
interface StartArgs {
|
|
7
8
|
port?: string
|
|
8
9
|
}
|
|
@@ -5,15 +5,16 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import
|
|
9
|
-
|
|
8
|
+
import type { Stats } from '@rspack/core'
|
|
9
|
+
|
|
10
10
|
import chalk from 'chalk'
|
|
11
11
|
import filesize from 'filesize'
|
|
12
|
+
import fs from 'fs-extra'
|
|
13
|
+
import { gzipSizeSync } from 'gzip-size'
|
|
14
|
+
import path from 'path'
|
|
12
15
|
// @ts-ignore
|
|
13
16
|
import recursive from 'recursive-readdir'
|
|
14
17
|
import stripAnsi from 'strip-ansi'
|
|
15
|
-
import { gzipSizeSync } from 'gzip-size'
|
|
16
|
-
import type { Stats } from '@rspack/core'
|
|
17
18
|
|
|
18
19
|
interface SizeMap {
|
|
19
20
|
root: string
|
package/src/utils/appConfig.ts
CHANGED
package/src/utils/beforeStart.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import fs from 'fs-extra'
|
|
2
|
-
import paths from '../config/paths'
|
|
3
1
|
import chalk from 'chalk'
|
|
2
|
+
import fs from 'fs-extra'
|
|
4
3
|
import semver from 'semver'
|
|
4
|
+
|
|
5
|
+
import paths from '../config/paths'
|
|
5
6
|
import appConfig from './appConfig'
|
|
6
7
|
|
|
7
8
|
const pkg = fs.readJsonSync(paths.resolveOwn('package.json'))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Chalk } from 'chalk'
|
|
2
1
|
import type { Compiler, Configuration as RspackConfiguration, SwcLoaderOptions } from '@rspack/core'
|
|
3
2
|
import type { Configuration as DevServerConfiguration } from '@rspack/dev-server'
|
|
3
|
+
import type { Chalk } from 'chalk'
|
|
4
4
|
|
|
5
5
|
type ProxyConfigArray = NonNullable<DevServerConfiguration['proxy']>
|
|
6
6
|
|
package/src/utils/exec.ts
CHANGED
package/src/utils/getConfig.ts
CHANGED
package/src/utils/getOverride.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import fs from 'fs-extra'
|
|
2
|
-
import paths from '../config/paths'
|
|
3
2
|
import { createRequire } from 'node:module'
|
|
4
|
-
|
|
3
|
+
|
|
4
|
+
import type { Configuration } from './defineConfig'
|
|
5
|
+
|
|
6
|
+
import paths from '../config/paths'
|
|
5
7
|
import { resolveModule } from './resolveModule'
|
|
6
8
|
|
|
7
9
|
const require = createRequire(import.meta.url)
|
package/tsdown.config.ts
CHANGED