@tmsfe/tmskit 0.0.5-beta.4 → 0.0.6
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 +2 -0
- package/dist/index.cjs.js +603 -414
- package/package.json +8 -2
- package/src/config/constant.js +2 -1
- package/src/config/defaultTmsConfig.js +8 -10
- package/src/gulp/build.js +0 -3
- package/src/gulp/compile.js +7 -7
- package/src/gulp/dev.js +12 -18
- package/src/gulp/plugins/mpCommonDep.js +6 -6
- package/src/gulp/plugins/mpJsonDep.js +6 -6
- package/src/gulp/plugins/mpWxmlDep.js +6 -6
- package/src/gulp/plugins/postcss-font-base64.js +1 -1
- package/src/gulp/{replaceEnv.js → plugins/replaceEnv.js} +1 -1
- package/src/index.js +0 -1
- package/src/scripts/run/build/index.js +3 -2
- package/src/scripts/run/dev/index.js +28 -11
- package/src/scripts/run/index.js +26 -21
- package/src/scripts/run/init/index.js +23 -16
- package/src/scripts/run/install/index.js +3 -5
- package/src/utils/buildAppJson.js +46 -25
- package/src/utils/checkDependencies.js +6 -6
- package/src/utils/cloneModules.js +39 -13
- package/src/utils/handleError.js +16 -0
- package/src/utils/io.js +1 -1
- package/src/utils/mpCiUtils.js +0 -1
- package/src/utils/npmUtils.js +53 -35
- package/src/utils/tkitUtils.js +90 -16
- package/src/utils/widgets.js +11 -14
- package/src/webpack/base.js +0 -65
- package/src/webpack/build.js +0 -21
- package/src/webpack/buildServer.js +0 -34
- package/src/webpack/dev.js +0 -31
- package/src/webpack/devServer.js +0 -37
- package/src/webpack/plugins/entryExtractPlugin/index.js +0 -28
- package/src/webpack/utils.js +0 -244
|
@@ -1,25 +1,23 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
-
const {
|
|
2
|
+
const { MODULE_CONFIG_FILENAME, MODULE_CONFIG_INVALID_KEY } = require('../config/constant');
|
|
3
3
|
const { fail } = require('./log');
|
|
4
4
|
const { resolve, isObject, isArray } = require('./widgets');
|
|
5
|
+
const { handleError } = require('./handleError');
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* 获取每个模块下面的信息,并且收集,后续更新到appJson里面
|
|
8
9
|
* @param { object } file 操作目录下面所有的文件
|
|
9
10
|
* @param { string } appName 小程序的名称
|
|
10
11
|
*/
|
|
11
|
-
|
|
12
|
+
|
|
13
|
+
function setModuleConfig(file, appName) {
|
|
12
14
|
const content = file.contents ? JSON.parse(file.contents.toString()) : JSON.parse(file);
|
|
13
15
|
|
|
14
|
-
if (isObject(content)) {
|
|
15
|
-
content.root = content.root.indexOf(moduleDir) > -1 ? content.root : `${moduleDir}/${content.root}`;
|
|
16
|
-
}
|
|
17
16
|
|
|
18
17
|
if (isArray(content)) {
|
|
19
18
|
let i = content.length - 1;
|
|
20
19
|
while (i >= 0) {
|
|
21
20
|
let current = content[i];
|
|
22
|
-
current.root = current.root.indexOf(moduleDir) > -1 ? current.root : `${moduleDir}/${current.root}`;
|
|
23
21
|
|
|
24
22
|
if (appName && current.mpConfig && current.mpConfig[appName]) {
|
|
25
23
|
current = { ...current, ...current.mpConfig[appName] };
|
|
@@ -38,16 +36,17 @@ function setModuleConfig(file, appName, moduleDir) {
|
|
|
38
36
|
/**
|
|
39
37
|
* 递归获取本地所有模块的配置信息
|
|
40
38
|
*/
|
|
41
|
-
function getLocalModuleConfig(modules = [], appName,
|
|
39
|
+
function getLocalModuleConfig(modules = [], appName, moduleConfigFilename) {
|
|
42
40
|
const modulesConfig = {};
|
|
43
41
|
|
|
44
42
|
modules.forEach(({ path }) => {
|
|
45
43
|
const moduleConfigPath = resolve(path, moduleConfigFilename);
|
|
46
44
|
if (fs.existsSync(moduleConfigPath)) {
|
|
47
45
|
const content = fs.readFileSync(moduleConfigPath, 'utf-8');
|
|
48
|
-
modulesConfig[moduleConfigPath] = setModuleConfig(content, appName
|
|
46
|
+
modulesConfig[moduleConfigPath] = setModuleConfig(content, appName);
|
|
49
47
|
}
|
|
50
48
|
});
|
|
49
|
+
|
|
51
50
|
return modulesConfig;
|
|
52
51
|
}
|
|
53
52
|
|
|
@@ -111,10 +110,22 @@ const updateSubpackages = (appJson, modulesConfig) => {
|
|
|
111
110
|
// eslint-disable-next-line
|
|
112
111
|
for (const name in modulesConfig) {
|
|
113
112
|
const moduleInfo = isObject(modulesConfig[name]) ? [modulesConfig[name]] : modulesConfig[name];
|
|
113
|
+
// 过滤 pages 为空的情况
|
|
114
|
+
const validModules = getValidModules(moduleInfo);
|
|
114
115
|
// eslint-disable-next-line
|
|
115
|
-
appJson.subpackages = appJson.subpackages.concat(
|
|
116
|
+
appJson.subpackages = appJson.subpackages.concat(validModules);
|
|
116
117
|
}
|
|
117
118
|
};
|
|
119
|
+
/**
|
|
120
|
+
* 过滤页面为空的分包
|
|
121
|
+
* @param {Array} moduleCfg 模块配置内容
|
|
122
|
+
* @returns pages不为空的分包
|
|
123
|
+
*/
|
|
124
|
+
const getValidModules = (moduleCfg) => {
|
|
125
|
+
// 过滤 pages 为空的情况
|
|
126
|
+
const validModules = moduleCfg.filter(item => item.pages.length > 0);
|
|
127
|
+
return validModules;
|
|
128
|
+
};
|
|
118
129
|
|
|
119
130
|
/**
|
|
120
131
|
* 处理合并subpackages后的appjson, 整理重复不合法的地方
|
|
@@ -127,6 +138,11 @@ const processAppJson = (appJson) => {
|
|
|
127
138
|
const subps = subpackages.map((subp) => {
|
|
128
139
|
const invalidKeys = [];
|
|
129
140
|
Object.keys(subp).forEach((key) => {
|
|
141
|
+
if (key === 'dependencies') {
|
|
142
|
+
// eslint-disable-next-line
|
|
143
|
+
delete subp.dependencies;
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
130
146
|
if (key === 'plugins') {
|
|
131
147
|
Object.keys(subp.plugins).forEach((pk) => {
|
|
132
148
|
pluginsMap[pk] ? pluginsMap[pk].push(`分包${subp.name}`) : pluginsMap[pk] = [`分包${subp.name}`];
|
|
@@ -164,7 +180,7 @@ const processAppJson = (appJson) => {
|
|
|
164
180
|
})
|
|
165
181
|
.reduce((pre, cur) => pre + cur, '');
|
|
166
182
|
if (pluginsErrMsg) {
|
|
167
|
-
fail(pluginsErrMsg);
|
|
183
|
+
fail(`plugins配置出现错误:${pluginsErrMsg}`);
|
|
168
184
|
}
|
|
169
185
|
// eslint-disable-next-line
|
|
170
186
|
appJson.subpackages = subps;
|
|
@@ -177,24 +193,29 @@ const processAppJson = (appJson) => {
|
|
|
177
193
|
* @param {array} modules
|
|
178
194
|
* @returns
|
|
179
195
|
*/
|
|
180
|
-
function buildOutputAppJson(tmsConfig, modules) {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
196
|
+
function buildOutputAppJson(tmsConfig, modules, isDev) {
|
|
197
|
+
try {
|
|
198
|
+
// 获取当前 modules 下的所有子模块的配置内容
|
|
199
|
+
const modulesConfig = getLocalModuleConfig(modules, tmsConfig.appName, MODULE_CONFIG_FILENAME);
|
|
200
|
+
// 获取app.json的配置
|
|
201
|
+
const appJson = getAppJsonContent(resolve('./app.json'));
|
|
202
|
+
// 更新app.json中的subpackages
|
|
203
|
+
updateSubpackages(appJson, modulesConfig);
|
|
204
|
+
// 处理appJson中重复||冲突的地方
|
|
205
|
+
processAppJson(appJson);
|
|
206
|
+
// 更新主包,需在subpackages处理完成后执行, pages/
|
|
207
|
+
updateMainPackages(appJson, tmsConfig.mainPackages);
|
|
208
|
+
|
|
209
|
+
fs.writeFileSync(resolve(`${tmsConfig.outputDir}/app.json`), JSON.stringify(appJson, null, 2), 'utf8');
|
|
210
|
+
|
|
211
|
+
return appJson;
|
|
212
|
+
} catch (e) {
|
|
213
|
+
handleError(`生成app.json出现错误: ${e}`, isDev);
|
|
214
|
+
}
|
|
195
215
|
}
|
|
196
216
|
|
|
197
217
|
module.exports = {
|
|
198
218
|
setModuleConfig,
|
|
219
|
+
getValidModules,
|
|
199
220
|
buildOutputAppJson,
|
|
200
221
|
};
|
|
@@ -2,8 +2,8 @@ const fs = require('fs');
|
|
|
2
2
|
const semver = require('semver');
|
|
3
3
|
const { resolve } = require('./widgets');
|
|
4
4
|
const path = require('path');
|
|
5
|
-
const { fail } = require('./log');
|
|
6
5
|
const shelljs = require('shelljs');
|
|
6
|
+
const { handleError } = require('./handleError');
|
|
7
7
|
|
|
8
8
|
const getLatestVersion = (npmName) => {
|
|
9
9
|
const data = shelljs.exec(`npm view ${npmName} version`);
|
|
@@ -17,7 +17,7 @@ const getLatestVersion = (npmName) => {
|
|
|
17
17
|
* @param {*} outputDir 待检查node_modules存放的目录 (eg: dist/node_modules)
|
|
18
18
|
* @returns
|
|
19
19
|
*/
|
|
20
|
-
const checkDependencies = (modules, cwd, outputDir) => {
|
|
20
|
+
const checkDependencies = (modules, cwd, outputDir, isDev) => {
|
|
21
21
|
// 步骤1. 收集package.json
|
|
22
22
|
const packageJsonName = 'package.json'; // 查找文件名
|
|
23
23
|
// 1.1根目录的package.json
|
|
@@ -41,12 +41,12 @@ const checkDependencies = (modules, cwd, outputDir) => {
|
|
|
41
41
|
// 步骤2. 比较package.json的依赖与node_modules依赖的版本号
|
|
42
42
|
for (const item of packageArr) {
|
|
43
43
|
const packageJson = fs.readFileSync(item.srcPackageDir, 'utf-8');
|
|
44
|
-
let dependencies;
|
|
44
|
+
let dependencies = {};
|
|
45
45
|
try {
|
|
46
|
-
|
|
46
|
+
const json = JSON.parse(packageJson);
|
|
47
|
+
dependencies = json?.dependencies ? json?.dependencies : {};
|
|
47
48
|
} catch (e) {
|
|
48
|
-
|
|
49
|
-
process.exit(1);
|
|
49
|
+
handleError(`解析${item.srcPackageDir}报错,请检查是否是正确的json配置项`, isDev);
|
|
50
50
|
}
|
|
51
51
|
const dependenciesKeys = Object.keys(dependencies);
|
|
52
52
|
for (const key of dependenciesKeys) {
|
|
@@ -1,9 +1,29 @@
|
|
|
1
1
|
const MetalSmith = require('metalsmith');
|
|
2
2
|
const { getGlobalInstance } = require('./global.js');
|
|
3
3
|
const { downloadRepoForGit, resolve } = require('./widgets');
|
|
4
|
+
const { readTmsPrivateCf } = require('../utils/tkitUtils');
|
|
4
5
|
const { fail } = require('./log');
|
|
5
6
|
const fs = require('fs');
|
|
6
7
|
const shelljs = require('shelljs');
|
|
8
|
+
const { handleError } = require('./handleError.js');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 处理用户没有clone git仓库权限问题——拼接账号信息
|
|
12
|
+
* @param {*} httpRepoUrl
|
|
13
|
+
* @param {*} moduleName
|
|
14
|
+
* @returns
|
|
15
|
+
*/
|
|
16
|
+
function replaceGitUrlAccount(httpRepoUrl, moduleName, privateCf) {
|
|
17
|
+
let gitUrl = httpRepoUrl;
|
|
18
|
+
const { username = '', pass = '' } = privateCf?.gitAccout?.[moduleName] || {};
|
|
19
|
+
|
|
20
|
+
const urlPrefixReg = /http(s)?:\/\//;
|
|
21
|
+
if (username && pass && urlPrefixReg.test(gitUrl)) {
|
|
22
|
+
gitUrl = gitUrl.replace(urlPrefixReg, val => `${val}${encodeURIComponent(username)}:${pass}@`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return gitUrl;
|
|
26
|
+
}
|
|
7
27
|
|
|
8
28
|
/**
|
|
9
29
|
* 对克隆下来的模块进行相应的文件处理操作,比如收集处理模块信息,进行信息缓存等操作
|
|
@@ -14,15 +34,15 @@ const shelljs = require('shelljs');
|
|
|
14
34
|
*/
|
|
15
35
|
function moveFile(sourceDir, targetDir, ignore = []) {
|
|
16
36
|
// 删除不是文件夹的文件
|
|
17
|
-
return new Promise((resolve) => {
|
|
37
|
+
return new Promise((resolve, reject) => {
|
|
18
38
|
MetalSmith(__dirname)
|
|
19
39
|
.ignore(ignore)
|
|
20
40
|
.source(sourceDir)
|
|
21
41
|
.destination(targetDir)
|
|
22
42
|
.build((e) => {
|
|
23
43
|
if (e) {
|
|
24
|
-
fail(e);
|
|
25
|
-
|
|
44
|
+
fail(`${sourceDir} moveFile ${targetDir}出现错误: ${e}`);
|
|
45
|
+
reject(e);
|
|
26
46
|
}
|
|
27
47
|
resolve();
|
|
28
48
|
});
|
|
@@ -33,13 +53,17 @@ function moveFile(sourceDir, targetDir, ignore = []) {
|
|
|
33
53
|
* 下载目标模块
|
|
34
54
|
* @param { string } sourceDir 缓存文件夹
|
|
35
55
|
* @param { string } targetDir 目标文件夹
|
|
56
|
+
* @param { boolean } isDev 是否是dev
|
|
36
57
|
* @returns { array } modules 描述模块的列表
|
|
37
58
|
*/
|
|
38
|
-
async function cloneModules(sourceDir, targetDir, modules) {
|
|
59
|
+
async function cloneModules(sourceDir, targetDir, modules, isDev) {
|
|
60
|
+
// 用户本地的私有项目配置(用来配置环境\模块信息\账号信息)
|
|
61
|
+
const privateCf = readTmsPrivateCf();
|
|
62
|
+
|
|
39
63
|
// 根据小程序的配置文件下载模块, 并且处理信息
|
|
40
|
-
for (const moduleInfo of modules) {
|
|
64
|
+
for (const moduleInfo of modules) {
|
|
41
65
|
if (moduleInfo.repoInfo) {
|
|
42
|
-
await downLoadAndMoveModule(sourceDir, targetDir, moduleInfo);
|
|
66
|
+
await downLoadAndMoveModule(sourceDir, targetDir, moduleInfo, privateCf, isDev);
|
|
43
67
|
}
|
|
44
68
|
}
|
|
45
69
|
}
|
|
@@ -48,13 +72,14 @@ async function cloneModules(sourceDir, targetDir, modules) {
|
|
|
48
72
|
* 下载模块信息并且将它移动到对应的位置
|
|
49
73
|
* @param { string } sourceDir 代码缓存文件夹
|
|
50
74
|
* @param { string } targetDir 代码要放到的目标文件夹
|
|
75
|
+
* @param { boolean } isDev 是否是dev
|
|
51
76
|
* @returns { array } moduleInfo 描述模块的信息
|
|
52
77
|
*/
|
|
53
|
-
async function downLoadAndMoveModule(sourceDir, targetDir, moduleInfo) {
|
|
54
|
-
const { repoInfo: { buildGitTag, httpRepoUrl }, path } = moduleInfo;
|
|
78
|
+
async function downLoadAndMoveModule(sourceDir, targetDir, moduleInfo, privateCf, isDev) {
|
|
79
|
+
const { repoInfo: { buildGitTag, httpRepoUrl }, path, name } = moduleInfo;
|
|
55
80
|
|
|
56
81
|
// 源码临时存在的源目录
|
|
57
|
-
let sourcePath = resolve(sourceDir,
|
|
82
|
+
let sourcePath = resolve(sourceDir, name);
|
|
58
83
|
// 源码要放到目标目录
|
|
59
84
|
const targetPath = resolve(targetDir, path);
|
|
60
85
|
// 设置模块的构建分支
|
|
@@ -66,22 +91,23 @@ async function downLoadAndMoveModule(sourceDir, targetDir, moduleInfo) {
|
|
|
66
91
|
|
|
67
92
|
try {
|
|
68
93
|
if (!moduleInCache) {
|
|
69
|
-
|
|
94
|
+
// 处理仓库权限问题
|
|
95
|
+
const gitUrl = replaceGitUrlAccount(httpRepoUrl, name, privateCf);
|
|
96
|
+
await downloadRepoForGit(gitUrl, sourcePath, cloneBranch);
|
|
70
97
|
globalInstance.setModuleCache(httpRepoUrl, cloneBranch, sourcePath);
|
|
71
98
|
} else {
|
|
72
99
|
sourcePath = globalInstance.getModuleCache(httpRepoUrl, cloneBranch).dest;
|
|
73
100
|
}
|
|
74
101
|
|
|
75
102
|
if (fs.existsSync(targetPath)) {
|
|
76
|
-
shelljs.rm('-rf', targetPath);
|
|
103
|
+
shelljs.rm('-rf', `${targetPath}/*`);
|
|
77
104
|
}
|
|
78
105
|
await moveFile(sourcePath, targetPath, [
|
|
79
106
|
'node_modules',
|
|
80
107
|
'.git',
|
|
81
108
|
]);
|
|
82
109
|
} catch (e) {
|
|
83
|
-
|
|
84
|
-
process.exit(-1);
|
|
110
|
+
handleError(e, isDev);
|
|
85
111
|
}
|
|
86
112
|
}
|
|
87
113
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const { fail } = require('./log');
|
|
2
|
+
|
|
3
|
+
function handleError(error, isDev = false) {
|
|
4
|
+
const errMsg = typeof error === 'object' ? error.message : error;
|
|
5
|
+
if (isDev) {
|
|
6
|
+
fail(errMsg);
|
|
7
|
+
} else {
|
|
8
|
+
fail(errMsg);
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
module.exports = {
|
|
14
|
+
handleError,
|
|
15
|
+
};
|
|
16
|
+
|
package/src/utils/io.js
CHANGED
package/src/utils/mpCiUtils.js
CHANGED
package/src/utils/npmUtils.js
CHANGED
|
@@ -2,55 +2,74 @@
|
|
|
2
2
|
* 本文件主要负责项目或者分包依赖的npm的安装
|
|
3
3
|
*/
|
|
4
4
|
const fs = require('fs');
|
|
5
|
+
const fsExtra = require('fs-extra');
|
|
6
|
+
const crypto = require('crypto');
|
|
5
7
|
const path = require('path');
|
|
6
8
|
const shell = require('shelljs');
|
|
7
9
|
const glob = require('glob-ignore');
|
|
8
10
|
const LOG = require('./log');
|
|
9
11
|
|
|
10
|
-
const
|
|
12
|
+
const shellJsOption = { async: false, silent: true };
|
|
13
|
+
const dirPath = process.cwd(); // 项目根目录
|
|
11
14
|
|
|
12
|
-
const
|
|
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 || {};
|
|
13
21
|
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
if (
|
|
17
|
-
|
|
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;
|
|
18
26
|
}
|
|
19
|
-
const tarNpmFilename = getTarNpmFilename(targetDir);
|
|
20
|
-
const tarNpmFilePath = `${cacheDir}/${tarNpmFilename}`;
|
|
21
|
-
if (fs.existsSync(tarNpmFilePath)) {
|
|
22
|
-
shell.rm('-rf', tarNpmFilePath);
|
|
23
|
-
}
|
|
24
|
-
const cmd = `tar -zcvf ${tarNpmFilePath} ./node_modules`;
|
|
25
|
-
shell.exec(cmd, { async: true, silent: true });
|
|
26
|
-
// tar -zcvf /Users/odile/.tmskit/node_modules.tar.gz ./node_modules
|
|
27
|
-
};
|
|
28
27
|
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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);
|
|
36
59
|
}
|
|
37
|
-
|
|
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 };
|
|
38
66
|
};
|
|
39
67
|
|
|
40
68
|
|
|
41
69
|
// 遍历安装指定目录下所有项目的npm依赖
|
|
42
70
|
const mpNpmInstallAll = async (modules, contextDir, cacheDir) => {
|
|
43
71
|
const packageJsonFiles = await findAllPackageJson(modules, contextDir);
|
|
44
|
-
await Promise.all(packageJsonFiles.map(file =>
|
|
45
|
-
const dir = path.dirname(file);
|
|
46
|
-
shell.cd(dir);
|
|
47
|
-
if (!fs.existsSync(`${dir}/node_modules`)) {
|
|
48
|
-
getNpmCache(dir, cacheDir);
|
|
49
|
-
}
|
|
50
|
-
shell.exec('npx pnpm install --prod --registry http://mirrors.tencent.com/npm/', { silent: false });
|
|
51
|
-
resolve();
|
|
52
|
-
npmCache(dir, cacheDir);
|
|
53
|
-
})));
|
|
72
|
+
await Promise.all(packageJsonFiles.map(file => install(file, true, cacheDir)));
|
|
54
73
|
};
|
|
55
74
|
|
|
56
75
|
/**
|
|
@@ -106,10 +125,9 @@ const findFilesByFilter = (startPath, filter) => {
|
|
|
106
125
|
*/
|
|
107
126
|
const findAllPackageJson = (subRoots = [], contextDir) => {
|
|
108
127
|
const packageJsonName = 'package.json'; // 查找文件名
|
|
109
|
-
const cwd = contextDir ||
|
|
128
|
+
const cwd = contextDir || dirPath;
|
|
110
129
|
const result = [path.join(cwd, packageJsonName)]; // 默认填充根目录下的package.json
|
|
111
130
|
|
|
112
|
-
|
|
113
131
|
subRoots.forEach((subRoot) => {
|
|
114
132
|
if (!subRoot.root) {
|
|
115
133
|
LOG.fail(`请检查${subRoot.name}的module.config.json是否有root字段`);
|
package/src/utils/tkitUtils.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
const loadash = require('lodash');
|
|
2
2
|
const fs = require('fs');
|
|
3
|
-
const { TMS_NAME, TMS_CONFIG_FILENAME, MODULE_CONFIG_FILENAME } = require('../config/constant');
|
|
3
|
+
const { TMS_NAME, TMS_CONFIG_FILENAME, MODULE_CONFIG_FILENAME, TMS_PRIVATE_FILENAME } = require('../config/constant');
|
|
4
4
|
const { resolve, isObject } = require('./widgets');
|
|
5
|
-
const { setModuleConfig } = require('./buildAppJson');
|
|
5
|
+
const { setModuleConfig, getValidModules } = require('./buildAppJson');
|
|
6
6
|
const defaultTmsConfig = require('../config/defaultTmsConfig');
|
|
7
7
|
const { fail } = require('./log');
|
|
8
|
+
const path = require('path');
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
|
-
* 读取tms.config.
|
|
11
|
+
* 读取tms.config.js
|
|
11
12
|
* @param env {string} 环境变量
|
|
12
13
|
*/
|
|
13
14
|
const readTmsConfig = function (env) {
|
|
@@ -22,9 +23,45 @@ const readTmsConfig = function (env) {
|
|
|
22
23
|
});
|
|
23
24
|
// 合并默认值
|
|
24
25
|
loadash.mergeWith(tmsConfig, defaultTmsConfig);
|
|
26
|
+
// modules兼容处理
|
|
27
|
+
tmsConfig.modules = convertModules(tmsConfig.modules);
|
|
25
28
|
return tmsConfig;
|
|
26
29
|
};
|
|
27
30
|
|
|
31
|
+
// convertModules 处理默认值
|
|
32
|
+
const convertModules = (modules) => {
|
|
33
|
+
const newModules = [];
|
|
34
|
+
modules.forEach((module, index) => {
|
|
35
|
+
const newModule = {};
|
|
36
|
+
if (typeof module === 'string') {
|
|
37
|
+
// 路径字符串
|
|
38
|
+
Object.assign(newModule, {
|
|
39
|
+
name: path.basename(module),
|
|
40
|
+
path: module,
|
|
41
|
+
});
|
|
42
|
+
} else if (typeof module === 'object') {
|
|
43
|
+
Object.assign(newModule, module);
|
|
44
|
+
if (module.name === undefined) {
|
|
45
|
+
newModule.name = path.basename(module.path);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
newModules.push(newModule);
|
|
49
|
+
});
|
|
50
|
+
return newModules;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 读取tms.private.js
|
|
55
|
+
*/
|
|
56
|
+
const readTmsPrivateCf = function () {
|
|
57
|
+
let tmsPrivateCg;
|
|
58
|
+
const tmsPrivatePath = resolve(TMS_PRIVATE_FILENAME);
|
|
59
|
+
if (fs.existsSync(tmsPrivatePath)) {
|
|
60
|
+
tmsPrivateCg = require(tmsPrivatePath);
|
|
61
|
+
}
|
|
62
|
+
return tmsPrivateCg;
|
|
63
|
+
};
|
|
64
|
+
|
|
28
65
|
/**
|
|
29
66
|
* 从tms.config.json中检索用户传入的有效modules
|
|
30
67
|
* @param { object } tmsConfig
|
|
@@ -32,7 +69,7 @@ const readTmsConfig = function (env) {
|
|
|
32
69
|
* @returns
|
|
33
70
|
*/
|
|
34
71
|
const checkModules = function (tmsConfig, modules) {
|
|
35
|
-
const targetModules =
|
|
72
|
+
const targetModules = [];
|
|
36
73
|
modules.forEach((moduleName) => {
|
|
37
74
|
const module = tmsConfig.modules.find(module => module.name === moduleName);
|
|
38
75
|
module && targetModules.push(module);
|
|
@@ -51,22 +88,29 @@ const checkModules = function (tmsConfig, modules) {
|
|
|
51
88
|
* @param {string} moduleDir
|
|
52
89
|
* @returns
|
|
53
90
|
*/
|
|
54
|
-
const tmsModulesMergeLocalModuleCfg = (modules, appName
|
|
91
|
+
const tmsModulesMergeLocalModuleCfg = (modules, appName) => {
|
|
55
92
|
const newModules = [];
|
|
56
93
|
modules.forEach(({ path: relativePath, name: moduleName }, moduleIndex) => {
|
|
57
94
|
const moduleConfigPath = resolve(relativePath, MODULE_CONFIG_FILENAME);
|
|
58
95
|
if (fs.existsSync(moduleConfigPath)) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
96
|
+
try {
|
|
97
|
+
let moduleConfigContent = fs.readFileSync(moduleConfigPath, 'utf-8');
|
|
98
|
+
moduleConfigContent = setModuleConfig(moduleConfigContent, appName);
|
|
99
|
+
const moduleContentArr = isObject(moduleConfigContent) ? [moduleConfigContent] : moduleConfigContent;
|
|
100
|
+
getValidModules(moduleContentArr).forEach(({ name }, moduleContentArrIndex) => {
|
|
101
|
+
if (name === moduleName) {
|
|
102
|
+
newModules.push({
|
|
103
|
+
...modules[moduleIndex],
|
|
104
|
+
...moduleContentArr[moduleContentArrIndex],
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
} catch (e) {
|
|
109
|
+
fail(`${moduleConfigPath}配置错误: ${e}`);
|
|
110
|
+
newModules.push({
|
|
111
|
+
...modules[moduleIndex],
|
|
112
|
+
});
|
|
113
|
+
}
|
|
70
114
|
} else {
|
|
71
115
|
newModules.push({
|
|
72
116
|
...modules[moduleIndex],
|
|
@@ -76,9 +120,39 @@ const tmsModulesMergeLocalModuleCfg = (modules, appName, moduleDir) => {
|
|
|
76
120
|
return newModules;
|
|
77
121
|
};
|
|
78
122
|
|
|
123
|
+
/**
|
|
124
|
+
* 分包依赖了分包的模块 合并所依赖的modules
|
|
125
|
+
* @param { object } tmsConfig
|
|
126
|
+
* @param {array} modules
|
|
127
|
+
* @param {string} moduleDir
|
|
128
|
+
* @returns
|
|
129
|
+
*/
|
|
130
|
+
const subModulesMergeDepModules = (tmsConfig, modules) => {
|
|
131
|
+
const moduleNames = [];
|
|
132
|
+
modules.forEach(({ name: moduleName }) => {
|
|
133
|
+
moduleNames.push(moduleName);
|
|
134
|
+
});
|
|
135
|
+
let mergeModules = modules;
|
|
136
|
+
let isOver = true;
|
|
137
|
+
modules.forEach(({ dependencies: dependencyModules }) => {
|
|
138
|
+
dependencyModules?.forEach((item) => {
|
|
139
|
+
// 如果所有模块的dep都在moduleNames内,则所有依赖都齐了
|
|
140
|
+
// 否则递归处理,根据name找到相关配置加到modules里
|
|
141
|
+
if (moduleNames.indexOf(item) === -1) {
|
|
142
|
+
isOver = false;
|
|
143
|
+
const tmpModules = checkModules(tmsConfig, [...new Set([item])]);
|
|
144
|
+
mergeModules = [...mergeModules, ...tmpModules];
|
|
145
|
+
mergeModules = tmsModulesMergeLocalModuleCfg(mergeModules, tmsConfig.appName);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
return isOver ? mergeModules : subModulesMergeDepModules(tmsConfig, mergeModules);
|
|
150
|
+
};
|
|
79
151
|
|
|
80
152
|
module.exports = {
|
|
81
153
|
readTmsConfig,
|
|
154
|
+
readTmsPrivateCf,
|
|
82
155
|
checkModules,
|
|
83
156
|
tmsModulesMergeLocalModuleCfg,
|
|
157
|
+
subModulesMergeDepModules,
|
|
84
158
|
};
|
package/src/utils/widgets.js
CHANGED
|
@@ -7,7 +7,7 @@ const fs = require('fs');
|
|
|
7
7
|
const shelljs = require('shelljs');
|
|
8
8
|
const download = require('download-git-repo');
|
|
9
9
|
const chalk = require('chalk');
|
|
10
|
-
const
|
|
10
|
+
const shelljsOptions = { slient: true };
|
|
11
11
|
|
|
12
12
|
// 获取当前目录
|
|
13
13
|
const cwd = process.cwd();
|
|
@@ -96,7 +96,7 @@ function downloadRepo(dest, downloadOptions = { repoUrl: '', gitUrl: '', branch:
|
|
|
96
96
|
function downloadRepoForGit(url, dest, branch) {
|
|
97
97
|
const cwd = process.cwd();
|
|
98
98
|
|
|
99
|
-
return new Promise((resolve) => {
|
|
99
|
+
return new Promise((resolve, reject) => {
|
|
100
100
|
// 如果目标目录不存在
|
|
101
101
|
if (fs.existsSync(dest)) {
|
|
102
102
|
shelljs.rm('-rf', path.join(dest));
|
|
@@ -105,7 +105,10 @@ function downloadRepoForGit(url, dest, branch) {
|
|
|
105
105
|
shelljs.mkdir('-p', dest);
|
|
106
106
|
shelljs.cd(dest);
|
|
107
107
|
|
|
108
|
-
shelljs.exec(`git clone ${url} ${dest} --branch ${branch} --depth 1`,
|
|
108
|
+
const gitCloneRes = shelljs.exec(`git clone ${url} ${dest} --branch ${branch} --depth 1`, shelljsOptions);
|
|
109
|
+
if (gitCloneRes.code !== 0) {
|
|
110
|
+
reject(gitCloneRes.stderr);
|
|
111
|
+
}
|
|
109
112
|
|
|
110
113
|
shelljs.cd(cwd);
|
|
111
114
|
resolve();
|
|
@@ -129,22 +132,16 @@ const cost = start => Date.now() - start;
|
|
|
129
132
|
function createTask(task, startText, endText) {
|
|
130
133
|
return async (...args) => {
|
|
131
134
|
const start = Date.now();
|
|
132
|
-
let result;
|
|
133
135
|
|
|
134
136
|
const spinner = ora(startText);
|
|
137
|
+
|
|
135
138
|
spinner.start();
|
|
139
|
+
console.log('\n');
|
|
136
140
|
|
|
137
|
-
|
|
138
|
-
result = await task(...args);
|
|
139
|
-
} catch (e) {
|
|
140
|
-
result = e;
|
|
141
|
-
console.log(chalk.red(e));
|
|
141
|
+
const result = await task(...args);
|
|
142
142
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
endText && spinner.succeed(`${endText}, ${cost(start)}ms`);
|
|
146
|
-
spinner.stop();
|
|
147
|
-
}
|
|
143
|
+
endText && spinner.succeed(`${endText}, ${cost(start)}ms`);
|
|
144
|
+
spinner.stop();
|
|
148
145
|
|
|
149
146
|
return result;
|
|
150
147
|
};
|