@qse/edu-scripts 1.12.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.
Files changed (85) hide show
  1. package/CHANGELOG.md +333 -0
  2. package/README.md +105 -0
  3. package/app.d.ts +68 -0
  4. package/docs/changelog.md +5 -0
  5. package/docs/deploy.md +53 -0
  6. package/docs/feat.md +74 -0
  7. package/docs/grayscale.md +31 -0
  8. package/docs/index.md +5 -0
  9. package/docs/mode.md +42 -0
  10. package/docs/override.md +165 -0
  11. package/docs/refactor-react-16.md +40 -0
  12. package/docs/refactor.md +139 -0
  13. package/jest.config.js +195 -0
  14. package/lib/asset/dll/libcommon3-manifest.json +181 -0
  15. package/lib/asset/template/edu-app-env.d.ts.tpl +15 -0
  16. package/lib/asset/template/edu-scripts.override.js.tpl +14 -0
  17. package/lib/asset/template/page/index.class.js.tpl +24 -0
  18. package/lib/asset/template/page/index.class.tsx.tpl +10 -0
  19. package/lib/asset/template/page/index.fc.js.tpl +16 -0
  20. package/lib/asset/template/page/index.fc.tsx.tpl +9 -0
  21. package/lib/asset/template/page/index.less.tpl +3 -0
  22. package/lib/asset/template/page/logic.js.tpl +4 -0
  23. package/lib/asset/template/page/route.js.tpl +12 -0
  24. package/lib/asset/template/tailwind.config.js.tpl +11 -0
  25. package/lib/asset/template/tsconfig.json.tpl +24 -0
  26. package/lib/auto-refactor.js +175 -0
  27. package/lib/build.js +87 -0
  28. package/lib/cli.js +63 -0
  29. package/lib/commit-dist.js +117 -0
  30. package/lib/config/babel.dependencies.js +56 -0
  31. package/lib/config/babel.js +82 -0
  32. package/lib/config/paths.js +44 -0
  33. package/lib/config/plugins/postcss-safe-area.js +22 -0
  34. package/lib/config/webpackConfig.js +384 -0
  35. package/lib/config/webpackDevServerConfig.js +47 -0
  36. package/lib/deploy.js +186 -0
  37. package/lib/generator.js +155 -0
  38. package/lib/index.d.ts +1 -0
  39. package/lib/index.js +13 -0
  40. package/lib/start.js +51 -0
  41. package/lib/utils/FileSizeReporter.js +131 -0
  42. package/lib/utils/appConfig.js +44 -0
  43. package/lib/utils/beforeStart.js +73 -0
  44. package/lib/utils/changeDeployVersion.js +125 -0
  45. package/lib/utils/defineConfig.d.ts +59 -0
  46. package/lib/utils/defineConfig.js +10 -0
  47. package/lib/utils/exec.js +13 -0
  48. package/lib/utils/getConfig.js +30 -0
  49. package/lib/utils/getOverride.js +33 -0
  50. package/package.json +102 -0
  51. package/src/asset/dll/libcommon3-manifest.json +181 -0
  52. package/src/asset/template/edu-app-env.d.ts.tpl +15 -0
  53. package/src/asset/template/edu-scripts.override.js.tpl +14 -0
  54. package/src/asset/template/page/index.class.js.tpl +24 -0
  55. package/src/asset/template/page/index.class.tsx.tpl +10 -0
  56. package/src/asset/template/page/index.fc.js.tpl +16 -0
  57. package/src/asset/template/page/index.fc.tsx.tpl +9 -0
  58. package/src/asset/template/page/index.less.tpl +3 -0
  59. package/src/asset/template/page/logic.js.tpl +4 -0
  60. package/src/asset/template/page/route.js.tpl +12 -0
  61. package/src/asset/template/tailwind.config.js.tpl +11 -0
  62. package/src/asset/template/tsconfig.json.tpl +24 -0
  63. package/src/auto-refactor.js +172 -0
  64. package/src/build.js +74 -0
  65. package/src/cli.js +91 -0
  66. package/src/commit-dist.js +103 -0
  67. package/src/config/babel.dependencies.js +65 -0
  68. package/src/config/babel.js +88 -0
  69. package/src/config/paths.js +37 -0
  70. package/src/config/plugins/postcss-safe-area.js +21 -0
  71. package/src/config/webpackConfig.js +410 -0
  72. package/src/config/webpackDevServerConfig.js +44 -0
  73. package/src/deploy.js +158 -0
  74. package/src/generator.js +138 -0
  75. package/src/index.ts +1 -0
  76. package/src/start.js +46 -0
  77. package/src/utils/FileSizeReporter.js +144 -0
  78. package/src/utils/appConfig.js +35 -0
  79. package/src/utils/beforeStart.js +66 -0
  80. package/src/utils/changeDeployVersion.js +115 -0
  81. package/src/utils/defineConfig.ts +63 -0
  82. package/src/utils/exec.js +7 -0
  83. package/src/utils/getConfig.js +26 -0
  84. package/src/utils/getOverride.js +32 -0
  85. package/tsconfig.json +31 -0
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+
3
+ const path = require('path');
4
+
5
+ const fs = require('fs-extra');
6
+
7
+ const {
8
+ upperFirst,
9
+ camelCase,
10
+ has
11
+ } = require('lodash');
12
+
13
+ const paths = require('./config/paths');
14
+
15
+ const chalk = require('chalk');
16
+ /**
17
+ * @param {string[]} args
18
+ * @returns {string}
19
+ */
20
+
21
+
22
+ const getTmpPath = (...args) => path.resolve(__dirname, 'asset', 'template', ...args);
23
+
24
+ function genFile({
25
+ source,
26
+ target,
27
+ modulePath,
28
+ replace
29
+ }) {
30
+ let content = fs.readFileSync(source, 'utf-8');
31
+
32
+ if (typeof replace === 'object') {
33
+ Object.entries(replace).forEach(([searchValue, replaceValue]) => {
34
+ content = content.replaceAll(searchValue, replaceValue);
35
+ });
36
+ }
37
+
38
+ fs.writeFileSync(path.resolve(modulePath, target), content);
39
+ }
40
+ /**
41
+ * @typedef {Object} PageArgs
42
+ * @property {string} name
43
+ * @property {boolean} [fc=false]
44
+ * @property {boolean} [ts=true]
45
+ * @property {boolean} [route=true]
46
+ *
47
+ * @param {PageArgs} args
48
+ */
49
+
50
+
51
+ async function generatorPage(args) {
52
+ const tmpPath = getTmpPath('page', 'index.[type].[ext].tpl');
53
+ const lessPath = tmpPath.replace('[type].[ext]', 'less');
54
+ const moduleName = camelCase(args.name);
55
+ const ModuleName = upperFirst(moduleName);
56
+ const type = args.fc ? 'fc' : 'class';
57
+ const ext = fs.existsSync(paths.tsconfig) ? args.ts ? 'tsx' : 'js' : 'js';
58
+ const jsPath = tmpPath.replace('[type]', type).replace('[ext]', ext);
59
+ const routePath = tmpPath.replace('index.[type].[ext]', 'route.js');
60
+ const logicPath = tmpPath.replace('index.[type].[ext]', 'logic.js');
61
+ const modulePath = path.resolve(paths.pages, moduleName);
62
+ const ModuleFileName = args.route ? ModuleName : 'index';
63
+ const ModuleLogicName = args.route ? ModuleName + 'Logic' : 'logic';
64
+ const replace = {
65
+ ModuleName,
66
+ moduleName,
67
+ ModuleFileName,
68
+ ModuleLogicName
69
+ };
70
+ fs.ensureDirSync(modulePath);
71
+ genFile({
72
+ source: jsPath,
73
+ target: `${ModuleFileName}.${ext}`,
74
+ modulePath,
75
+ replace
76
+ });
77
+ genFile({
78
+ source: lessPath,
79
+ target: `${ModuleFileName}.less`,
80
+ modulePath,
81
+ replace
82
+ });
83
+
84
+ if (type === 'class' && ext === 'js') {
85
+ genFile({
86
+ source: logicPath,
87
+ target: `${ModuleLogicName}.${ext.slice(0, 2)}`,
88
+ modulePath,
89
+ replace
90
+ });
91
+ }
92
+
93
+ if (args.route) {
94
+ genFile({
95
+ source: routePath,
96
+ target: `index.${ext.slice(0, 2)}`,
97
+ modulePath,
98
+ replace
99
+ });
100
+ }
101
+
102
+ console.log(chalk.green([`生成完毕:`, `import ${ModuleName} from '@/pages/${moduleName}'`, `const ${ModuleName} = lazy(() => import(/* webpackChunkName: '${moduleName}' */ '@/pages/${moduleName}'))`, `{ path: '/${moduleName}', element: <${ModuleName} /> },`].join('\n')));
103
+ }
104
+
105
+ async function generatorOverride() {
106
+ if (fs.existsSync(paths.override)) {
107
+ console.log(chalk.red(`文件已存在 ${paths.override}`));
108
+ process.exit(0);
109
+ }
110
+
111
+ fs.copySync(getTmpPath('edu-scripts.override.js.tpl'), paths.override);
112
+ console.log(chalk.green(`成功生成 ${paths.override}`));
113
+ }
114
+
115
+ async function generatorTsconfig() {
116
+ if (fs.existsSync(paths.tsconfig)) {
117
+ console.log(chalk.red(`文件已存在 ${paths.tsconfig}`));
118
+ process.exit(0);
119
+ }
120
+
121
+ fs.copySync(getTmpPath('tsconfig.json.tpl'), paths.tsconfig);
122
+ fs.copySync(getTmpPath('edu-app-env.d.ts.tpl'), paths.eduAppEnv);
123
+ console.log(chalk.green(`成功生成 ${paths.tsconfig}`));
124
+ }
125
+
126
+ async function generatorTailwind() {
127
+ if (fs.existsSync(paths.tailwind)) {
128
+ console.log(chalk.red(`文件已存在 ${paths.tailwind}`));
129
+ process.exit(0);
130
+ }
131
+
132
+ fs.copySync(getTmpPath('tailwind.config.js.tpl'), paths.tailwind);
133
+ const code = ['@tailwind base;', '@tailwind components;', '@tailwind utilities;'].join('\n');
134
+ const globalLessFile = paths.resolveApp('src', 'index.less');
135
+
136
+ if (fs.existsSync(globalLessFile)) {
137
+ const content = fs.readFileSync(globalLessFile, 'utf-8');
138
+
139
+ if (!content.includes('@tailwind base')) {
140
+ fs.writeFileSync(globalLessFile, [code, content].join('\n'));
141
+ }
142
+
143
+ console.log(chalk.green(`成功生成 ${paths.tailwind}`));
144
+ return;
145
+ }
146
+
147
+ console.log(chalk.green([`成功生成 ${paths.tailwind}`, '', '添加以下代码到入口处的 index.less 中', code].join('\n')));
148
+ }
149
+
150
+ module.exports = {
151
+ page: generatorPage,
152
+ override: generatorOverride,
153
+ ts: generatorTsconfig,
154
+ tailwind: generatorTailwind
155
+ };
package/lib/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { defineConfig } from './utils/defineConfig';
package/lib/index.js ADDED
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "defineConfig", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _defineConfig.defineConfig;
10
+ }
11
+ });
12
+
13
+ var _defineConfig = require("./utils/defineConfig");
package/lib/start.js ADDED
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+
3
+ process.env.NODE_ENV = 'development';
4
+ process.env.BABEL_ENV = 'development';
5
+ process.env.BROWSERSLIST = 'chrome >= 70';
6
+ process.env.WEBPACK_DEV_SERVER_BASE_PORT = '3000'; // Makes the script crash on unhandled rejections instead of silently
7
+ // ignoring them. In the future, promise rejections that are not handled will
8
+ // terminate the Node.js process with a non-zero exit code.
9
+
10
+ process.on('unhandledRejection', err => {
11
+ throw err;
12
+ });
13
+
14
+ const WebpackDevServer = require('webpack-dev-server');
15
+
16
+ const webpack = require('webpack');
17
+
18
+ const getConfig = require('./utils/getConfig');
19
+
20
+ const chalk = require('chalk');
21
+
22
+ process.env.WDS_SOCKET_HOST = WebpackDevServer.internalIPSync('v4') || '127.0.0.1';
23
+
24
+ module.exports = async function start(args) {
25
+ const basePort = process.env.WEBPACK_DEV_SERVER_BASE_PORT;
26
+ const port = await WebpackDevServer.getFreePort(args.port || process.env.PORT);
27
+
28
+ if (!(args.port || process.env.PORT) && +port !== +basePort) {
29
+ console.log(chalk.bgYellow(`${basePort} 端口已被占用,现切换到 ${port} 端口运行`));
30
+ }
31
+
32
+ process.env.WDS_SOCKET_PORT = port;
33
+ args.port = port;
34
+ const compiler = webpack(getConfig(args));
35
+ const devServer = new WebpackDevServer(compiler.options.devServer, compiler);
36
+ devServer.start();
37
+ [('SIGINT', 'SIGTERM')].forEach(function (sig) {
38
+ process.on(sig, function () {
39
+ devServer.stop();
40
+ process.exit();
41
+ });
42
+ });
43
+
44
+ if (process.env.CI !== 'true') {
45
+ // Gracefully exit when stdin ends
46
+ process.stdin.on('end', function () {
47
+ devServer.stop();
48
+ process.exit();
49
+ });
50
+ }
51
+ };
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Copyright (c) 2015-present, Facebook, Inc.
5
+ *
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ var fs = require('fs');
10
+
11
+ var path = require('path');
12
+
13
+ var chalk = require('chalk');
14
+
15
+ var filesize = require('filesize');
16
+
17
+ var recursive = require('recursive-readdir');
18
+
19
+ var stripAnsi = require('strip-ansi');
20
+
21
+ var gzipSize = require('gzip-size').sync;
22
+
23
+ function canReadAsset(asset) {
24
+ return /\.(js|css)$/.test(asset) && !/service-worker\.js/.test(asset) && !/precache-manifest\.[0-9a-f]+\.js/.test(asset);
25
+ } // Prints a detailed summary of build files.
26
+
27
+
28
+ function printFileSizesAfterBuild(webpackStats, previousSizeMap, buildFolder, maxBundleGzipSize, maxChunkGzipSize) {
29
+ var root = previousSizeMap.root;
30
+ var sizes = previousSizeMap.sizes;
31
+ var assets = (webpackStats.stats || [webpackStats]).map(stats => stats.toJson({
32
+ all: false,
33
+ assets: true
34
+ }).assets.filter(asset => canReadAsset(asset.name)).map(asset => {
35
+ var fileContents = fs.readFileSync(path.join(root, asset.name));
36
+ var size = gzipSize(fileContents);
37
+ var previousSize = sizes[removeFileNameHash(root, asset.name)];
38
+ var difference = getDifferenceLabel(size, previousSize);
39
+ return {
40
+ folder: path.join(path.basename(buildFolder), path.dirname(asset.name)),
41
+ name: path.basename(asset.name),
42
+ size: size,
43
+ sizeLabel: filesize(size) + (difference ? ' (' + difference + ')' : '')
44
+ };
45
+ })).reduce((single, all) => all.concat(single), []);
46
+ assets.sort((a, b) => b.size - a.size); // move main file to first
47
+
48
+ var mainAssetIdx = assets.findIndex(asset => /_\d+\.\d+\.\d+\./.test(asset.name));
49
+ assets.unshift(assets.splice(mainAssetIdx, 1)[0]);
50
+ var longestSizeLabelLength = Math.max.apply(null, assets.map(a => stripAnsi(a.sizeLabel).length));
51
+ var suggestBundleSplitting = false;
52
+ assets.forEach(asset => {
53
+ var sizeLabel = asset.sizeLabel;
54
+ var sizeLength = stripAnsi(sizeLabel).length;
55
+
56
+ if (sizeLength < longestSizeLabelLength) {
57
+ var rightPadding = ' '.repeat(longestSizeLabelLength - sizeLength);
58
+ sizeLabel += rightPadding;
59
+ }
60
+
61
+ var isMainBundle = /_\d+\.\d+\.\d+\./.test(asset.name);
62
+ var maxRecommendedSize = isMainBundle ? maxBundleGzipSize : maxChunkGzipSize;
63
+ var isLarge = maxRecommendedSize && asset.size > maxRecommendedSize;
64
+
65
+ if (isLarge && path.extname(asset.name) === '.js') {
66
+ suggestBundleSplitting = true;
67
+ }
68
+
69
+ console.log(' ' + (isLarge ? chalk.yellow(sizeLabel) : sizeLabel) + ' ' + chalk.dim(asset.folder + path.sep) + chalk.cyan(asset.name));
70
+
71
+ if (isMainBundle) {
72
+ console.log('');
73
+ }
74
+ });
75
+
76
+ if (suggestBundleSplitting) {
77
+ console.log();
78
+ console.log(chalk.yellow('产物大小明显大于推荐的大小 (主文件 30k, chunk 1M, 黄色标注为偏大)'));
79
+ console.log(chalk.yellow('考虑下使用代码分割解决'));
80
+ console.log(chalk.yellow('也可以使用 npm run analyze 命令分析产物'));
81
+ }
82
+ }
83
+
84
+ function removeFileNameHash(buildFolder, fileName) {
85
+ return fileName.replace(buildFolder, '').replace(/\\/g, '/').replace(/\/\d+\.\d+\.\d+\//, '/').replace(/\/?(.*)(\.[0-9a-f]+)(\.chunk)?(\.js|\.css)/, (match, p1, p2, p3, p4) => p1 + p4);
86
+ } // Input: 1024, 2048
87
+ // Output: "(+1 KB)"
88
+
89
+
90
+ function getDifferenceLabel(currentSize, previousSize) {
91
+ var FIFTY_KILOBYTES = 1024 * 50;
92
+ var difference = currentSize - previousSize;
93
+ var fileSize = !Number.isNaN(difference) ? filesize(difference) : 0;
94
+
95
+ if (difference >= FIFTY_KILOBYTES) {
96
+ return chalk.red('+' + fileSize);
97
+ } else if (difference < FIFTY_KILOBYTES && difference > 0) {
98
+ return chalk.yellow('+' + fileSize);
99
+ } else if (difference < 0) {
100
+ return chalk.green(fileSize);
101
+ } else {
102
+ return '';
103
+ }
104
+ }
105
+
106
+ function measureFileSizesBeforeBuild(buildFolder) {
107
+ return new Promise(resolve => {
108
+ recursive(buildFolder, (err, fileNames) => {
109
+ var sizes;
110
+
111
+ if (!err && fileNames) {
112
+ sizes = fileNames.filter(canReadAsset).reduce((memo, fileName) => {
113
+ var contents = fs.readFileSync(fileName);
114
+ var key = removeFileNameHash(buildFolder, fileName);
115
+ memo[key] = gzipSize(contents);
116
+ return memo;
117
+ }, {});
118
+ }
119
+
120
+ resolve({
121
+ root: buildFolder,
122
+ sizes: sizes || {}
123
+ });
124
+ });
125
+ });
126
+ }
127
+
128
+ module.exports = {
129
+ measureFileSizesBeforeBuild: measureFileSizesBeforeBuild,
130
+ printFileSizesAfterBuild: printFileSizesAfterBuild
131
+ };
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+
3
+ const paths = require('../config/paths');
4
+
5
+ const appPkg = require(paths.package);
6
+
7
+ const fs = require('fs');
8
+
9
+ const edu = appPkg.edu || {};
10
+
11
+ if (edu.single || edu.mainProject) {
12
+ if (edu.single) {
13
+ edu.mode = 'single';
14
+ delete edu.single;
15
+ }
16
+
17
+ if (edu.mainProject) {
18
+ edu.mode = 'main';
19
+ delete edu.mainProject;
20
+ }
21
+
22
+ fs.writeFileSync(paths.package, JSON.stringify(appPkg, null, 2), 'utf-8');
23
+ }
24
+
25
+ const appConfig = {
26
+ /** @type {'main'|'single'} */
27
+ get mode() {
28
+ return edu.mode;
29
+ },
30
+
31
+ get mainProject() {
32
+ return this.mode === 'main';
33
+ },
34
+
35
+ get single() {
36
+ return this.mode === 'single';
37
+ },
38
+
39
+ get grayscale() {
40
+ return !!edu.grayscale;
41
+ }
42
+
43
+ };
44
+ module.exports = appConfig;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+
3
+ const fs = require('fs');
4
+
5
+ const paths = require('../config/paths');
6
+
7
+ const chalk = require('chalk');
8
+
9
+ const pkg = require('../../package.json');
10
+
11
+ const updateNotifier = require('update-notifier');
12
+
13
+ const notifier = updateNotifier({
14
+ pkg,
15
+ shouldNotifyInNpmScript: true,
16
+ updateCheckInterval: 1000 * 60 // 时刻保持更新
17
+
18
+ });
19
+
20
+ if (notifier.update && ['minor', 'major'].includes(notifier.update.type)) {
21
+ const message = '发现新版本 ' + chalk.dim('{currentVersion}') + chalk.reset(' → ') + chalk.green('{latestVersion}') + ' \n运行 ' + chalk.cyan('{updateCommand}') + ' 进行更新\n\n' + chalk.bold.red('请始终保持最新版本\n') + '更新日志: ' + chalk.green(`${pkg.homepage}#/changelog`);
22
+ notifier.notify({
23
+ message
24
+ });
25
+ process.exit(1);
26
+ }
27
+
28
+ const appPkg = require(paths.package);
29
+
30
+ const appConfig = require('./appConfig');
31
+
32
+ switch (appConfig.mode) {
33
+ case 'main':
34
+ console.log(chalk.bgMagenta('正在使用教育主工程模式'));
35
+ break;
36
+
37
+ case 'single':
38
+ console.log(chalk.bgMagenta('正在使用独立项目模式'));
39
+ break;
40
+
41
+ default:
42
+ console.log(chalk.bgMagenta('正在使用教育集成模式'));
43
+ break;
44
+ }
45
+
46
+ if (appConfig.grayscale) {
47
+ console.log(chalk.bgYellow('正在使用灰度测试模式'));
48
+ }
49
+
50
+ if (!(appConfig.single || appConfig.mainProject)) {
51
+ if (fs.existsSync(paths.static)) {
52
+ console.log(chalk.bgYellow('教育集成工程不能含有 public/static, 现已自动删除'));
53
+
54
+ try {
55
+ fs.rmSync(paths.static, {
56
+ recursive: true
57
+ });
58
+ } catch (e) {}
59
+ }
60
+ }
61
+
62
+ if (!fs.existsSync(paths.public) && !process.argv.includes('auto-refactor')) {
63
+ console.log(chalk.red(`public 文件夹不存在,请先按文档改造项目`));
64
+ console.log(`文档: ${chalk.underline(pkg.homepage)}`);
65
+ console.log(`\n使用 ${chalk.green('npx edu-scripts auto-refactor')} 自动改造\n`);
66
+ process.exit(0);
67
+ }
68
+
69
+ if (appPkg.browserslist) {
70
+ console.log(chalk.yellow('已删除 package.json 中 browserslist,该值由内部自动控制\n'));
71
+ delete appPkg.browserslist;
72
+ fs.writeFileSync(paths.package, JSON.stringify(appPkg, null, 2), 'utf-8');
73
+ }
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+
3
+ const t = require('@babel/types');
4
+
5
+ const {
6
+ parse
7
+ } = require('@babel/parser');
8
+
9
+ const generate = require('@babel/generator').default;
10
+
11
+ const traverse = require('@babel/traverse').default;
12
+
13
+ const {
14
+ format
15
+ } = require('prettier'); // ver.js 中定义模块的数组
16
+
17
+
18
+ const TARGET_IDENTIFIER_NAME = 'project_apiArr';
19
+ const MODULE_IDENTIFIER_NAME = 'module';
20
+
21
+ function changeDeployVersion(code, pkg) {
22
+ const {
23
+ name,
24
+ version,
25
+ grayscale
26
+ } = pkg;
27
+ let ast;
28
+
29
+ try {
30
+ ast = parse(code);
31
+ } catch (error) {
32
+ throw new Error(`代码解析错误: ${error.message}`);
33
+ }
34
+
35
+ const keyName = grayscale ? 'grayscale' : 'main';
36
+ /**
37
+ * @return {babel.NodePath<t.VariableDeclarator> | undefined}
38
+ */
39
+
40
+ function findTargetDeclarator(ast) {
41
+ let res;
42
+ traverse(ast, {
43
+ VariableDeclarator(path) {
44
+ if (t.isIdentifier(path.node.id, {
45
+ name: TARGET_IDENTIFIER_NAME
46
+ }) && t.isArrayExpression(path.node.init)) {
47
+ res = path;
48
+ }
49
+ }
50
+
51
+ });
52
+ return res;
53
+ }
54
+ /**
55
+ * @param {babel.NodePath<t.VariableDeclarator>} path
56
+ * @return {babel.NodePath<t.ObjectExpression> | undefined}
57
+ */
58
+
59
+
60
+ function findModuleObject(path) {
61
+ let res;
62
+ path.traverse({
63
+ ObjectExpression(path) {
64
+ if (path.node.properties.some(node => t.isIdentifier(node.key, {
65
+ name: MODULE_IDENTIFIER_NAME
66
+ }) && t.isLiteral(node.value, {
67
+ value: name
68
+ }))) {
69
+ res = path;
70
+ }
71
+ }
72
+
73
+ });
74
+ return res;
75
+ }
76
+ /**
77
+ * @param {babel.NodePath<t.ObjectExpression>} path
78
+ */
79
+
80
+
81
+ function modifyModuleVersion(path) {
82
+ let hasModify = false;
83
+ path.traverse({
84
+ Property(path) {
85
+ if (path.node.key.name === keyName) {
86
+ path.node.value.value = version;
87
+ hasModify = true;
88
+ }
89
+ }
90
+
91
+ });
92
+
93
+ if (!hasModify) {
94
+ path.node.properties.push(t.objectProperty(t.identifier(keyName), t.stringLiteral(version)));
95
+ }
96
+ }
97
+ /**
98
+ * @param {babel.NodePath<t.VariableDeclarator>} path
99
+ */
100
+
101
+
102
+ function addModuleToTarget(path) {
103
+ const elements = path.node.init.elements;
104
+ elements.splice(elements.length - 2, 0, t.objectExpression([t.objectProperty(t.identifier(MODULE_IDENTIFIER_NAME), t.stringLiteral(name)), t.objectProperty(t.identifier(keyName), t.stringLiteral(version))]));
105
+ }
106
+
107
+ const targetPath = findTargetDeclarator(ast);
108
+ if (!targetPath) throw new Error(`ver.js 不合规范,未找到参数 ${TARGET_IDENTIFIER_NAME}`);
109
+ const moduleObjPath = findModuleObject(targetPath);
110
+
111
+ if (moduleObjPath) {
112
+ modifyModuleVersion(moduleObjPath);
113
+ } else {
114
+ addModuleToTarget(targetPath);
115
+ }
116
+
117
+ return format(generate(ast, {
118
+ minified: true
119
+ }).code, {
120
+ parser: 'babel',
121
+ printWidth: 120
122
+ });
123
+ }
124
+
125
+ module.exports = changeDeployVersion;
@@ -0,0 +1,59 @@
1
+ import type { Configuration } from 'webpack';
2
+ import type { Configuration as DevServerConfiguration, ProxyConfigArray } from 'webpack-dev-server';
3
+ export declare type BabelImportPlugin = [
4
+ 'import',
5
+ {
6
+ libraryName: string;
7
+ libraryDirectory: string;
8
+ camel2DashComponentName?: boolean;
9
+ style?: boolean | 'css' | ((name: string) => string);
10
+ },
11
+ string
12
+ ];
13
+ export declare type BabelConfig = {
14
+ presets: any[];
15
+ plugins: (string | BabelImportPlugin | any[])[];
16
+ };
17
+ export declare type Config = {
18
+ webpack?: (config: Configuration) => Configuration | undefined;
19
+ devServer?: (config: DevServerConfiguration) => DevServerConfiguration | undefined;
20
+ babel?: (config: BabelConfig, type: 'src' | 'node_modules') => any | undefined;
21
+ /**
22
+ * webpack alias 配置,会与内置 alias 合并
23
+ *
24
+ * @default
25
+ * { '@': './src' }
26
+ */
27
+ alias?: Record<string, string>;
28
+ /**
29
+ * webpack externals 配置,会与内置 externals 合并
30
+ */
31
+ externals?: Record<string, string>;
32
+ /**
33
+ * terser pure_funcs,esbuild pure 配置,传 [] 可以不清空 console.log
34
+ * @default ['console.log']
35
+ */
36
+ pure_funcs?: string[];
37
+ /**
38
+ * 编译 node_modules 下文件
39
+ *
40
+ * 仅在 development 环境下生效。production 一定会编译 node_modules
41
+ * @default true
42
+ */
43
+ transformNodeModules?: boolean;
44
+ /**
45
+ * 指定压缩工具,esbuild 比 terser 快 20-40 倍,实际压缩率差 10%左右
46
+ *
47
+ * @default 'esbuild'
48
+ */
49
+ minify?: boolean | 'terser' | 'esbuild';
50
+ /** 自定义全局参数 */
51
+ define?: Record<string, any>;
52
+ /**
53
+ * webpack-dev-server proxy
54
+ * @default /api -> /qsxxwapdev/api
55
+ */
56
+ proxy?: ProxyConfigArray;
57
+ extraPostCSSPlugins?: any[];
58
+ };
59
+ export declare function defineConfig(config: Config): Config;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.defineConfig = defineConfig;
7
+
8
+ function defineConfig(config) {
9
+ return config;
10
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ const cp = require('child_process');
4
+
5
+ const exec = cmd => {
6
+ console.log(`> ${cmd}`);
7
+ return cp.execSync(cmd, {
8
+ stdio: 'inherit',
9
+ encoding: 'utf-8'
10
+ });
11
+ };
12
+
13
+ module.exports = exec;