@tmsfe/tmskit 0.0.6 → 0.0.7
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 +27 -27
- package/dist/index.cjs.js +332 -407
- package/main.js +3 -3
- package/package.json +75 -75
- package/src/config/constant.js +71 -71
- package/src/config/defaultTmsConfig.js +16 -16
- package/src/entry.js +60 -60
- package/src/gulp/build.js +5 -5
- package/src/gulp/compile.js +81 -87
- package/src/gulp/dev.js +102 -102
- package/src/gulp/plugins/less.js +116 -116
- package/src/gulp/plugins/mpCommonDep.js +131 -131
- package/src/gulp/plugins/mpJsonDep.js +108 -108
- package/src/gulp/plugins/mpWxmlDep.js +194 -194
- package/src/gulp/plugins/postcss-font-base64.js +72 -72
- package/src/gulp/plugins/replaceEnv.js +29 -29
- package/src/gulp/plugins/utils/pluginError.js +25 -25
- package/src/index.js +62 -62
- package/src/init.js +33 -33
- package/src/scripts/create/ask.js +63 -63
- package/src/scripts/create/generator.js +25 -25
- package/src/scripts/create/ignoreFiles.js +7 -7
- package/src/scripts/create/index.js +72 -72
- package/src/scripts/create/render.js +19 -19
- package/src/scripts/run/build/index.js +17 -17
- package/src/scripts/run/dev/index.js +84 -84
- package/src/scripts/run/index.js +68 -68
- package/src/scripts/run/init/index.js +87 -87
- package/src/scripts/run/install/index.js +29 -29
- package/src/utils/buildAppJson.js +221 -221
- package/src/utils/checkDependencies.js +77 -77
- package/src/utils/cliUtils.js +35 -35
- package/src/utils/cloneModules.js +116 -116
- package/src/utils/findCssImport.js +30 -30
- package/src/utils/global.js +36 -36
- package/src/utils/handleError.js +16 -16
- package/src/utils/io.js +106 -106
- package/src/utils/log.js +44 -44
- package/src/utils/mpCiUtils.js +73 -73
- package/src/utils/npmUtils.js +166 -166
- package/src/utils/tkitUtils.js +158 -158
- package/src/utils/widgets.js +167 -167
package/src/utils/log.js
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
const chalk = require('chalk');
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* 本文件提供无依赖的在终端打印彩色文字的方法。
|
|
5
|
-
*/
|
|
6
|
-
const resetCfg = decodeURIComponent('%1B%5B0m'); // \033[0m转义后的字符按,用来还原属性
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* 打印红底黑字格式的文字
|
|
10
|
-
* @param {String} message 需要打印的文字信息
|
|
11
|
-
* @returns {undefined} 无
|
|
12
|
-
*/
|
|
13
|
-
const fail = (message = '') => {
|
|
14
|
-
const redStyleConfig = decodeURIComponent('%1B%5B41%3B30m'); // \033[41;30m转义后的字符按,console时输出红色文字
|
|
15
|
-
const greenFontStyleConfig = decodeURIComponent('%1B%5B41%3B37m'); // \033[41;30m转义后的字符按,console时输出红底白色文字
|
|
16
|
-
console.log(`${redStyleConfig} ERROR ${greenFontStyleConfig} ${message}${resetCfg}`); // eslint-disable-line no-console
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* 打印绿底黑字格式的文字
|
|
21
|
-
* @param {String} message 需要打印的文字信息
|
|
22
|
-
* @returns {undefined} 无
|
|
23
|
-
*/
|
|
24
|
-
const succeed = (message = '') => {
|
|
25
|
-
const greenStyleConfig = decodeURIComponent('%1B%5B42%3B30m'); // \033[42;30m转义后的字符按,console时输出绿色文字
|
|
26
|
-
const greenFontStyleConfig = decodeURIComponent('%1B%5B40%3B32m'); // \033[40;32m转义后的字符按,console时输出绿色文字
|
|
27
|
-
console.log(`${greenStyleConfig} Success ${greenFontStyleConfig} ${message}${resetCfg}`); // eslint-disable-line no-console
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* 打印warn提示
|
|
33
|
-
* @param {String} message 需要打印的文字信息
|
|
34
|
-
* @returns {undefined} 无
|
|
35
|
-
*/
|
|
36
|
-
const warn = (message) => {
|
|
37
|
-
console.log(chalk.yellow(message));
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
module.exports = {
|
|
41
|
-
fail,
|
|
42
|
-
succeed,
|
|
43
|
-
warn,
|
|
44
|
-
};
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 本文件提供无依赖的在终端打印彩色文字的方法。
|
|
5
|
+
*/
|
|
6
|
+
const resetCfg = decodeURIComponent('%1B%5B0m'); // \033[0m转义后的字符按,用来还原属性
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 打印红底黑字格式的文字
|
|
10
|
+
* @param {String} message 需要打印的文字信息
|
|
11
|
+
* @returns {undefined} 无
|
|
12
|
+
*/
|
|
13
|
+
const fail = (message = '') => {
|
|
14
|
+
const redStyleConfig = decodeURIComponent('%1B%5B41%3B30m'); // \033[41;30m转义后的字符按,console时输出红色文字
|
|
15
|
+
const greenFontStyleConfig = decodeURIComponent('%1B%5B41%3B37m'); // \033[41;30m转义后的字符按,console时输出红底白色文字
|
|
16
|
+
console.log(`${redStyleConfig} ERROR ${greenFontStyleConfig} ${message}${resetCfg}`); // eslint-disable-line no-console
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 打印绿底黑字格式的文字
|
|
21
|
+
* @param {String} message 需要打印的文字信息
|
|
22
|
+
* @returns {undefined} 无
|
|
23
|
+
*/
|
|
24
|
+
const succeed = (message = '') => {
|
|
25
|
+
const greenStyleConfig = decodeURIComponent('%1B%5B42%3B30m'); // \033[42;30m转义后的字符按,console时输出绿色文字
|
|
26
|
+
const greenFontStyleConfig = decodeURIComponent('%1B%5B40%3B32m'); // \033[40;32m转义后的字符按,console时输出绿色文字
|
|
27
|
+
console.log(`${greenStyleConfig} Success ${greenFontStyleConfig} ${message}${resetCfg}`); // eslint-disable-line no-console
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 打印warn提示
|
|
33
|
+
* @param {String} message 需要打印的文字信息
|
|
34
|
+
* @returns {undefined} 无
|
|
35
|
+
*/
|
|
36
|
+
const warn = (message) => {
|
|
37
|
+
console.log(chalk.yellow(message));
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
module.exports = {
|
|
41
|
+
fail,
|
|
42
|
+
succeed,
|
|
43
|
+
warn,
|
|
44
|
+
};
|
package/src/utils/mpCiUtils.js
CHANGED
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
const ci = require('miniprogram-ci');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* 获取小程序ci的Project对象
|
|
6
|
-
* @returns {Object} 小程序ci对象
|
|
7
|
-
*/
|
|
8
|
-
const getMpCi = ({ appId, projectPath, type = 'miniProgram', privateKey = 'TODO' }) => {
|
|
9
|
-
const cfgJsonContent = require(path.join(projectPath, 'project.config.json'));
|
|
10
|
-
const ignores = cfgJsonContent?.packOptions?.ignore.map(({ value }) => value) || [];
|
|
11
|
-
|
|
12
|
-
return new ci.Project({
|
|
13
|
-
appid: appId,
|
|
14
|
-
privateKey,
|
|
15
|
-
type,
|
|
16
|
-
projectPath,
|
|
17
|
-
ignores: ['node_modules/**/*', ...ignores],
|
|
18
|
-
});
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
// 用小程序ci工具构建小程序
|
|
23
|
-
const packMpProject = async (project) => {
|
|
24
|
-
await ci.packNpm(project, {
|
|
25
|
-
ignores: ['cloud/**/*'],
|
|
26
|
-
});
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* 格式化构建npm结果信息
|
|
31
|
-
* @param {Array<String>} warning 构建时的告警信息
|
|
32
|
-
* @returns {String} npm构建错误信息
|
|
33
|
-
*/
|
|
34
|
-
const formatPackNpmWarning = (warning) => {
|
|
35
|
-
if (!warning) {
|
|
36
|
-
return '';
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const result = warning.map((it, index) => `${index + 1}. ${it.msg}
|
|
40
|
-
\t@ ${it.jsPath}:${it.tips}`).join('---------------\n');
|
|
41
|
-
|
|
42
|
-
return result;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* 构建miniprogram_npm
|
|
47
|
-
* @returns {Object} 小程序ci对象
|
|
48
|
-
*/
|
|
49
|
-
const buildMpNpm = async ({
|
|
50
|
-
appId,
|
|
51
|
-
projectPath,
|
|
52
|
-
privateKey,
|
|
53
|
-
}) => {
|
|
54
|
-
const mpCi = await getMpCi({
|
|
55
|
-
appId,
|
|
56
|
-
projectPath,
|
|
57
|
-
privateKey,
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
const packNpmWarning = await packMpProject(mpCi);
|
|
61
|
-
|
|
62
|
-
const packNpmMsg = formatPackNpmWarning(packNpmWarning);
|
|
63
|
-
if (packNpmMsg) {
|
|
64
|
-
return Promise.reject(packNpmMsg);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return Promise.resolve();
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
module.exports = {
|
|
72
|
-
buildMpNpm,
|
|
73
|
-
};
|
|
1
|
+
const ci = require('miniprogram-ci');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 获取小程序ci的Project对象
|
|
6
|
+
* @returns {Object} 小程序ci对象
|
|
7
|
+
*/
|
|
8
|
+
const getMpCi = ({ appId, projectPath, type = 'miniProgram', privateKey = 'TODO' }) => {
|
|
9
|
+
const cfgJsonContent = require(path.join(projectPath, 'project.config.json'));
|
|
10
|
+
const ignores = cfgJsonContent?.packOptions?.ignore.map(({ value }) => value) || [];
|
|
11
|
+
|
|
12
|
+
return new ci.Project({
|
|
13
|
+
appid: appId,
|
|
14
|
+
privateKey,
|
|
15
|
+
type,
|
|
16
|
+
projectPath,
|
|
17
|
+
ignores: ['node_modules/**/*', ...ignores],
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
// 用小程序ci工具构建小程序
|
|
23
|
+
const packMpProject = async (project) => {
|
|
24
|
+
await ci.packNpm(project, {
|
|
25
|
+
ignores: ['cloud/**/*'],
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 格式化构建npm结果信息
|
|
31
|
+
* @param {Array<String>} warning 构建时的告警信息
|
|
32
|
+
* @returns {String} npm构建错误信息
|
|
33
|
+
*/
|
|
34
|
+
const formatPackNpmWarning = (warning) => {
|
|
35
|
+
if (!warning) {
|
|
36
|
+
return '';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const result = warning.map((it, index) => `${index + 1}. ${it.msg}
|
|
40
|
+
\t@ ${it.jsPath}:${it.tips}`).join('---------------\n');
|
|
41
|
+
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 构建miniprogram_npm
|
|
47
|
+
* @returns {Object} 小程序ci对象
|
|
48
|
+
*/
|
|
49
|
+
const buildMpNpm = async ({
|
|
50
|
+
appId,
|
|
51
|
+
projectPath,
|
|
52
|
+
privateKey,
|
|
53
|
+
}) => {
|
|
54
|
+
const mpCi = await getMpCi({
|
|
55
|
+
appId,
|
|
56
|
+
projectPath,
|
|
57
|
+
privateKey,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const packNpmWarning = await packMpProject(mpCi);
|
|
61
|
+
|
|
62
|
+
const packNpmMsg = formatPackNpmWarning(packNpmWarning);
|
|
63
|
+
if (packNpmMsg) {
|
|
64
|
+
return Promise.reject(packNpmMsg);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return Promise.resolve();
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
module.exports = {
|
|
72
|
+
buildMpNpm,
|
|
73
|
+
};
|
package/src/utils/npmUtils.js
CHANGED
|
@@ -1,166 +1,166 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 本文件主要负责项目或者分包依赖的npm的安装
|
|
3
|
-
*/
|
|
4
|
-
const fs = require('fs');
|
|
5
|
-
const fsExtra = require('fs-extra');
|
|
6
|
-
const crypto = require('crypto');
|
|
7
|
-
const path = require('path');
|
|
8
|
-
const shell = require('shelljs');
|
|
9
|
-
const glob = require('glob-ignore');
|
|
10
|
-
const LOG = require('./log');
|
|
11
|
-
|
|
12
|
-
const shellJsOption = { async: false, silent: true };
|
|
13
|
-
const dirPath = process.cwd(); // 项目根目录
|
|
14
|
-
|
|
15
|
-
const install = async (packageJsonPath = '', retry = true, cacheDir) => {
|
|
16
|
-
const obj = {};
|
|
17
|
-
const packageContent = fs.readFileSync(packageJsonPath);
|
|
18
|
-
const packageJson = JSON.parse(packageContent);
|
|
19
|
-
obj.dependencies = packageJson.dependencies || {};
|
|
20
|
-
// obj.devDependencies = packageJson.devDependencies || {};
|
|
21
|
-
|
|
22
|
-
// dependencies和devDependencies字段为空,没有需要安装的npm包,直接return
|
|
23
|
-
// if (Object.keys(obj.dependencies).length === 0 && Object.keys(obj.devDependencies).length === 0) {
|
|
24
|
-
if (Object.keys(obj.dependencies).length === 0) {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// 以package.json中dependencies字段stringify后的md5值作为缓存key
|
|
29
|
-
// 任意包名或者版本号的差异,将导致md5后的差异,从而导致缓存失效,重新下载
|
|
30
|
-
// 如此来保证npm缓存的准确性
|
|
31
|
-
const str = JSON.stringify(obj);
|
|
32
|
-
const key = crypto.createHash('md5').update(str)
|
|
33
|
-
.digest('hex');
|
|
34
|
-
const keyPath = path.join(cacheDir, key);
|
|
35
|
-
const tarFile = path.join(keyPath, 'node_modules.tar.gz');
|
|
36
|
-
|
|
37
|
-
// npm缓存路径不存在
|
|
38
|
-
// 或者缓存的包大小小于512byte,认为缓存不合法
|
|
39
|
-
// 清空缓存目录,重新下载npm包缓存
|
|
40
|
-
const missCache = !fsExtra.pathExistsSync(keyPath)
|
|
41
|
-
|| !fsExtra.existsSync(tarFile)
|
|
42
|
-
|| fsExtra.statSync(tarFile).size < 512;
|
|
43
|
-
if (missCache) {
|
|
44
|
-
console.log(`未命中缓存,下载${packageJsonPath}依赖`);
|
|
45
|
-
fsExtra.emptydirSync(keyPath);
|
|
46
|
-
shell.cp('-f', packageJsonPath, keyPath);
|
|
47
|
-
shell.cd(keyPath);
|
|
48
|
-
try {
|
|
49
|
-
shell.exec('npx yarn --production --registry http://mirrors.tencent.com/npm/', shellJsOption);
|
|
50
|
-
} catch (err) {
|
|
51
|
-
console.log('err', err);
|
|
52
|
-
if (retry) {
|
|
53
|
-
return await install(packageJsonPath, false);
|
|
54
|
-
}
|
|
55
|
-
throw err;
|
|
56
|
-
}
|
|
57
|
-
shell.exec('tar -zcvf ./node_modules.tar.gz ./node_modules', shellJsOption);
|
|
58
|
-
shell.exec('rm -rf ./node_modules', shellJsOption);
|
|
59
|
-
}
|
|
60
|
-
shell.cp('-Rf', tarFile, `${path.dirname(packageJsonPath)}/`);
|
|
61
|
-
shell.cd(path.dirname(packageJsonPath));
|
|
62
|
-
|
|
63
|
-
shell.exec('tar -xzvf ./node_modules.tar.gz -C ./', shellJsOption);
|
|
64
|
-
shell.exec('rm -rf ./node_modules.tar.gz', shellJsOption);
|
|
65
|
-
return { missCache, key };
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
// 遍历安装指定目录下所有项目的npm依赖
|
|
70
|
-
const mpNpmInstallAll = async (modules, contextDir, cacheDir) => {
|
|
71
|
-
const packageJsonFiles = await findAllPackageJson(modules, contextDir);
|
|
72
|
-
await Promise.all(packageJsonFiles.map(file => install(file, true, cacheDir)));
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* 递归查找指定条件的文件
|
|
77
|
-
* @param {String} startPath 开始查找的根路径
|
|
78
|
-
* @param {String} filter 匹配的字符串
|
|
79
|
-
* @returns {Array<String>} 查找到的文件路径列表
|
|
80
|
-
*/
|
|
81
|
-
const findFilesByFilter = (startPath, filter) => {
|
|
82
|
-
const result = [];
|
|
83
|
-
/**
|
|
84
|
-
* 根据指定的筛选器查找文件
|
|
85
|
-
* @param {String} startPath 开始查找的文件夹路径
|
|
86
|
-
* @param {String} filter 筛选器
|
|
87
|
-
* @returns {Undefined} 无需返回值
|
|
88
|
-
*/
|
|
89
|
-
const find = (startPath, filter) => {
|
|
90
|
-
// 目录不存在
|
|
91
|
-
if (!fs.existsSync(startPath)) {
|
|
92
|
-
LOG.fail(`${startPath}目录不存在`);
|
|
93
|
-
process.exit(-1);
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// 当前目录下的所有文件 / 文件夹
|
|
98
|
-
const exceptDir = ['node_modules', 'miniprogram_npm'];
|
|
99
|
-
if (exceptDir.find(item => startPath.indexOf(item) > -1)) {
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
const files = fs.readdirSync(startPath);
|
|
103
|
-
files.forEach((file) => {
|
|
104
|
-
const filename = path.join(startPath, file);
|
|
105
|
-
const stat = fs.lstatSync(filename);
|
|
106
|
-
// 当前文件是文件夹类型,继续递归
|
|
107
|
-
if (stat.isDirectory()) {
|
|
108
|
-
find(filename, filter);
|
|
109
|
-
} else if (filename.indexOf(filter) >= 0) {
|
|
110
|
-
// 文件类型
|
|
111
|
-
result.push(filename);
|
|
112
|
-
};
|
|
113
|
-
});
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
find(startPath, filter);
|
|
117
|
-
return result;
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* 找到项目中所有的package.json文件
|
|
122
|
-
* @param {Array<String>} subRoots 需要安装npm依赖的路径
|
|
123
|
-
* @param {String} contextDir 命令运行的目录
|
|
124
|
-
* @returns {Array<String>} 找到的所有package.json文件的路径
|
|
125
|
-
*/
|
|
126
|
-
const findAllPackageJson = (subRoots = [], contextDir) => {
|
|
127
|
-
const packageJsonName = 'package.json'; // 查找文件名
|
|
128
|
-
const cwd = contextDir || dirPath;
|
|
129
|
-
const result = [path.join(cwd, packageJsonName)]; // 默认填充根目录下的package.json
|
|
130
|
-
|
|
131
|
-
subRoots.forEach((subRoot) => {
|
|
132
|
-
if (!subRoot.root) {
|
|
133
|
-
LOG.fail(`请检查${subRoot.name}的module.config.json是否有root字段`);
|
|
134
|
-
process.exit(1);
|
|
135
|
-
}
|
|
136
|
-
const toppath = path.join(cwd, subRoot.root); // 从该目录开始查找package.json文件
|
|
137
|
-
const list = findFilesByFilter(toppath, packageJsonName);
|
|
138
|
-
|
|
139
|
-
result.push(...list);
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
return result;
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
function cloudNpmInstall(contextDir) {
|
|
146
|
-
return new Promise((resolve, reject) => {
|
|
147
|
-
glob(`${contextDir}/**/package.json`, ['node_modules', 'miniprogram_npm'], (err, files) => {
|
|
148
|
-
if (err) {
|
|
149
|
-
reject(err);
|
|
150
|
-
}
|
|
151
|
-
files.forEach((file) => {
|
|
152
|
-
const dir = path.dirname(file);
|
|
153
|
-
shell.cd(dir);
|
|
154
|
-
shell.exec('npx npm install --production --registry http://mirrors.tencent.com/npm/', { silent: false });
|
|
155
|
-
});
|
|
156
|
-
resolve();
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
module.exports = {
|
|
163
|
-
cloudNpmInstall,
|
|
164
|
-
mpNpmInstallAll,
|
|
165
|
-
findAllPackageJson,
|
|
166
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* 本文件主要负责项目或者分包依赖的npm的安装
|
|
3
|
+
*/
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const fsExtra = require('fs-extra');
|
|
6
|
+
const crypto = require('crypto');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const shell = require('shelljs');
|
|
9
|
+
const glob = require('glob-ignore');
|
|
10
|
+
const LOG = require('./log');
|
|
11
|
+
|
|
12
|
+
const shellJsOption = { async: false, silent: true };
|
|
13
|
+
const dirPath = process.cwd(); // 项目根目录
|
|
14
|
+
|
|
15
|
+
const install = async (packageJsonPath = '', retry = true, cacheDir) => {
|
|
16
|
+
const obj = {};
|
|
17
|
+
const packageContent = fs.readFileSync(packageJsonPath);
|
|
18
|
+
const packageJson = JSON.parse(packageContent);
|
|
19
|
+
obj.dependencies = packageJson.dependencies || {};
|
|
20
|
+
// obj.devDependencies = packageJson.devDependencies || {};
|
|
21
|
+
|
|
22
|
+
// dependencies和devDependencies字段为空,没有需要安装的npm包,直接return
|
|
23
|
+
// if (Object.keys(obj.dependencies).length === 0 && Object.keys(obj.devDependencies).length === 0) {
|
|
24
|
+
if (Object.keys(obj.dependencies).length === 0) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// 以package.json中dependencies字段stringify后的md5值作为缓存key
|
|
29
|
+
// 任意包名或者版本号的差异,将导致md5后的差异,从而导致缓存失效,重新下载
|
|
30
|
+
// 如此来保证npm缓存的准确性
|
|
31
|
+
const str = JSON.stringify(obj);
|
|
32
|
+
const key = crypto.createHash('md5').update(str)
|
|
33
|
+
.digest('hex');
|
|
34
|
+
const keyPath = path.join(cacheDir, key);
|
|
35
|
+
const tarFile = path.join(keyPath, 'node_modules.tar.gz');
|
|
36
|
+
|
|
37
|
+
// npm缓存路径不存在
|
|
38
|
+
// 或者缓存的包大小小于512byte,认为缓存不合法
|
|
39
|
+
// 清空缓存目录,重新下载npm包缓存
|
|
40
|
+
const missCache = !fsExtra.pathExistsSync(keyPath)
|
|
41
|
+
|| !fsExtra.existsSync(tarFile)
|
|
42
|
+
|| fsExtra.statSync(tarFile).size < 512;
|
|
43
|
+
if (missCache) {
|
|
44
|
+
console.log(`未命中缓存,下载${packageJsonPath}依赖`);
|
|
45
|
+
fsExtra.emptydirSync(keyPath);
|
|
46
|
+
shell.cp('-f', packageJsonPath, keyPath);
|
|
47
|
+
shell.cd(keyPath);
|
|
48
|
+
try {
|
|
49
|
+
shell.exec('npx yarn --production --registry http://mirrors.tencent.com/npm/', shellJsOption);
|
|
50
|
+
} catch (err) {
|
|
51
|
+
console.log('err', err);
|
|
52
|
+
if (retry) {
|
|
53
|
+
return await install(packageJsonPath, false);
|
|
54
|
+
}
|
|
55
|
+
throw err;
|
|
56
|
+
}
|
|
57
|
+
shell.exec('tar -zcvf ./node_modules.tar.gz ./node_modules', shellJsOption);
|
|
58
|
+
shell.exec('rm -rf ./node_modules', shellJsOption);
|
|
59
|
+
}
|
|
60
|
+
shell.cp('-Rf', tarFile, `${path.dirname(packageJsonPath)}/`);
|
|
61
|
+
shell.cd(path.dirname(packageJsonPath));
|
|
62
|
+
|
|
63
|
+
shell.exec('tar -xzvf ./node_modules.tar.gz -C ./', shellJsOption);
|
|
64
|
+
shell.exec('rm -rf ./node_modules.tar.gz', shellJsOption);
|
|
65
|
+
return { missCache, key };
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
// 遍历安装指定目录下所有项目的npm依赖
|
|
70
|
+
const mpNpmInstallAll = async (modules, contextDir, cacheDir) => {
|
|
71
|
+
const packageJsonFiles = await findAllPackageJson(modules, contextDir);
|
|
72
|
+
await Promise.all(packageJsonFiles.map(file => install(file, true, cacheDir)));
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 递归查找指定条件的文件
|
|
77
|
+
* @param {String} startPath 开始查找的根路径
|
|
78
|
+
* @param {String} filter 匹配的字符串
|
|
79
|
+
* @returns {Array<String>} 查找到的文件路径列表
|
|
80
|
+
*/
|
|
81
|
+
const findFilesByFilter = (startPath, filter) => {
|
|
82
|
+
const result = [];
|
|
83
|
+
/**
|
|
84
|
+
* 根据指定的筛选器查找文件
|
|
85
|
+
* @param {String} startPath 开始查找的文件夹路径
|
|
86
|
+
* @param {String} filter 筛选器
|
|
87
|
+
* @returns {Undefined} 无需返回值
|
|
88
|
+
*/
|
|
89
|
+
const find = (startPath, filter) => {
|
|
90
|
+
// 目录不存在
|
|
91
|
+
if (!fs.existsSync(startPath)) {
|
|
92
|
+
LOG.fail(`${startPath}目录不存在`);
|
|
93
|
+
process.exit(-1);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// 当前目录下的所有文件 / 文件夹
|
|
98
|
+
const exceptDir = ['node_modules', 'miniprogram_npm'];
|
|
99
|
+
if (exceptDir.find(item => startPath.indexOf(item) > -1)) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const files = fs.readdirSync(startPath);
|
|
103
|
+
files.forEach((file) => {
|
|
104
|
+
const filename = path.join(startPath, file);
|
|
105
|
+
const stat = fs.lstatSync(filename);
|
|
106
|
+
// 当前文件是文件夹类型,继续递归
|
|
107
|
+
if (stat.isDirectory()) {
|
|
108
|
+
find(filename, filter);
|
|
109
|
+
} else if (filename.indexOf(filter) >= 0) {
|
|
110
|
+
// 文件类型
|
|
111
|
+
result.push(filename);
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
find(startPath, filter);
|
|
117
|
+
return result;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* 找到项目中所有的package.json文件
|
|
122
|
+
* @param {Array<String>} subRoots 需要安装npm依赖的路径
|
|
123
|
+
* @param {String} contextDir 命令运行的目录
|
|
124
|
+
* @returns {Array<String>} 找到的所有package.json文件的路径
|
|
125
|
+
*/
|
|
126
|
+
const findAllPackageJson = (subRoots = [], contextDir) => {
|
|
127
|
+
const packageJsonName = 'package.json'; // 查找文件名
|
|
128
|
+
const cwd = contextDir || dirPath;
|
|
129
|
+
const result = [path.join(cwd, packageJsonName)]; // 默认填充根目录下的package.json
|
|
130
|
+
|
|
131
|
+
subRoots.forEach((subRoot) => {
|
|
132
|
+
if (!subRoot.root) {
|
|
133
|
+
LOG.fail(`请检查${subRoot.name}的module.config.json是否有root字段`);
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
const toppath = path.join(cwd, subRoot.root); // 从该目录开始查找package.json文件
|
|
137
|
+
const list = findFilesByFilter(toppath, packageJsonName);
|
|
138
|
+
|
|
139
|
+
result.push(...list);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
return result;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
function cloudNpmInstall(contextDir) {
|
|
146
|
+
return new Promise((resolve, reject) => {
|
|
147
|
+
glob(`${contextDir}/**/package.json`, ['node_modules', 'miniprogram_npm'], (err, files) => {
|
|
148
|
+
if (err) {
|
|
149
|
+
reject(err);
|
|
150
|
+
}
|
|
151
|
+
files.forEach((file) => {
|
|
152
|
+
const dir = path.dirname(file);
|
|
153
|
+
shell.cd(dir);
|
|
154
|
+
shell.exec('npx npm install --production --registry http://mirrors.tencent.com/npm/', { silent: false });
|
|
155
|
+
});
|
|
156
|
+
resolve();
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
module.exports = {
|
|
163
|
+
cloudNpmInstall,
|
|
164
|
+
mpNpmInstallAll,
|
|
165
|
+
findAllPackageJson,
|
|
166
|
+
};
|