@tmsfe/tmskit 0.0.18 → 0.0.19

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tmsfe/tmskit",
3
- "version": "0.0.18",
3
+ "version": "0.0.19",
4
4
  "description": "tmskit",
5
5
  "main": "dist/index.cjs",
6
6
  "bin": {
@@ -7,6 +7,9 @@ const HOME_DIR = os.homedir();
7
7
  // 所有文件的缓存目录
8
8
  const CACHE_DIR = path.resolve(HOME_DIR, '.tmskit');
9
9
 
10
+ // 缓存文件
11
+ const CACHE_FILE = 'cache_file.json';
12
+
10
13
  // 脚手架模板代码所在目录
11
14
  const TEMPLATE_DIR = path.resolve(CACHE_DIR, 'template');
12
15
 
@@ -48,9 +51,11 @@ const ENV = {
48
51
 
49
52
  const TEMPLATE_TKIT_DIR = '_tmskit';
50
53
 
54
+
51
55
  export {
52
56
  HOME_DIR,
53
57
  CACHE_DIR,
58
+ CACHE_FILE,
54
59
  TEMPLATE_DIR,
55
60
  TEMPLATE_PATH,
56
61
  TMS_NAME,
@@ -0,0 +1,36 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { CACHE_FILE, CACHE_DIR } = require('../config/constant');
4
+ const { ensureDirExist } = require('../utils/io');
5
+
6
+ function getCache(projectDir, type) {
7
+ const filePath = `${CACHE_DIR}/${CACHE_FILE}`;
8
+ if (!fs.existsSync(filePath)) {
9
+ return null;
10
+ }
11
+ const content = require(filePath);
12
+ return content?.[projectDir]?.[type];
13
+ }
14
+
15
+
16
+ function setCache(projectDir, type = 'miniprogram_npm', data) {
17
+ const filePath = `${CACHE_DIR}/${CACHE_FILE}`;
18
+ if (!fs.existsSync(filePath)) {
19
+ const dir = path.dirname(filePath);
20
+ ensureDirExist(dir);
21
+ fs.writeFileSync(filePath, '{}');
22
+ }
23
+ const content = require(filePath);
24
+ if (!content[projectDir]) {
25
+ content[projectDir] = {};
26
+ }
27
+ content[projectDir] = {
28
+ [type]: data,
29
+ };
30
+ fs.writeFileSync(filePath, JSON.stringify(content, null, 2));
31
+ }
32
+
33
+ module.exports = {
34
+ setCache,
35
+ getCache,
36
+ };
@@ -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 isDependenciesUpdate = (modules, cwd, outputDir) => {
21
21
  // 步骤1. 收集package.json
22
22
  const packageJsonName = 'package.json'; // 查找文件名
23
23
  // 1.1根目录的package.json
@@ -73,5 +73,5 @@ const checkDependencies = (modules, cwd, outputDir) => {
73
73
  };
74
74
 
75
75
  module.exports = {
76
- checkDependencies,
76
+ isDependenciesUpdate,
77
77
  };
package/src/core/npm.js CHANGED
@@ -99,7 +99,7 @@ const collectNpmTasksMap = (packageJsonFiles, cacheDir) => {
99
99
 
100
100
 
101
101
  // 遍历安装指定目录下所有项目的npm依赖
102
- const mpNpmInstallAll = async (modules, contextDir, cacheDir) => {
102
+ const npmInstallAll = async (modules, contextDir, cacheDir) => {
103
103
  const cwd = process.cwd();
104
104
  const packageJsonFiles = await findAllPackageJson(modules, contextDir);
105
105
 
@@ -124,6 +124,7 @@ const mpNpmInstallAll = async (modules, contextDir, cacheDir) => {
124
124
 
125
125
  await Promise.all(arrPromises);
126
126
  shell.cd(cwd);
127
+ return packageJsonFiles;
127
128
  };
128
129
 
129
130
  /**
@@ -215,7 +216,7 @@ function cloudNpmInstall(contextDir) {
215
216
 
216
217
  module.exports = {
217
218
  cloudNpmInstall,
218
- mpNpmInstallAll,
219
+ npmInstallAll,
219
220
  findAllPackageJson,
220
221
  };
221
222
 
@@ -22,10 +22,9 @@ const readTmsConfig = function (env) {
22
22
  const tmsConfig = tmsConfigFn({
23
23
  env,
24
24
  });
25
- // 合并默认值
26
- loadash.mergeWith(tmsConfig, defaultTmsConfig);
27
25
 
28
- return tmsConfig;
26
+ // 合并默认值
27
+ return loadash.mergeWith(defaultTmsConfig, tmsConfig);
29
28
  };
30
29
 
31
30
 
@@ -14,7 +14,7 @@ function delOtherModule(tmsConfig, targetModules) {
14
14
  const targetModulesName = targetModules.map(item => item.name);
15
15
  modules.forEach((item) => {
16
16
  if (item.root && targetModulesName.indexOf(item.name) === -1) {
17
- const moduleRootDir = resolve(`dist/${item.root}`);
17
+ const moduleRootDir = resolve(`${tmsConfig.outputDir}/${item.root}`);
18
18
  shelljs.rm('-rf', `${moduleRootDir}/*`, { silent: true });
19
19
  // 解决微信开发者工具(dist/app.json: ["subpackages"][0]["root"] 字段需为 目录)错误 - 提前创建该目录
20
20
  // io.ensureDirExist(moduleRootDir);
@@ -109,7 +109,7 @@ async function run(commandName, cmd) {
109
109
  cloud(tmsConfig, env);
110
110
  return;
111
111
  case 'install':
112
- install(tmsConfig, newModules, env);
112
+ install(tmsConfig, newModules, env, false);
113
113
  return;
114
114
  case 'build':
115
115
  global.setData('isDev', false);
@@ -8,7 +8,6 @@ const { cloneModules } = require('../../../core/cloneModules');
8
8
  const { tmsModulesMergeLocalModuleCfg, subModulesMergeDepModules } = require('../../../core/tmsMpconfig');
9
9
  const { fail, info } = require('../../../utils/log');
10
10
  const install = require('../install');
11
- const { checkDependencies } = require('../../../core/checkDependencies');
12
11
 
13
12
  /**
14
13
  * 拷贝相关配置文件到编译输出目录
@@ -69,9 +68,8 @@ async function task(tmsConfig, targetModules) {
69
68
  )(tmsConfig, DEFAULT_COPY_CONFIG);
70
69
 
71
70
  // install
72
- if (checkDependencies(newModules, resolve('./'), tmsConfig.outputDir)) {
73
- await install(tmsConfig, newModules);
74
- }
71
+ await install(tmsConfig, newModules);
72
+
75
73
 
76
74
  // 动态生成编译后的app.json;
77
75
  await createTask(
@@ -1,13 +1,49 @@
1
1
  const shelljs = require('shelljs');
2
2
  const fs = require('fs');
3
+ const path = require('path');
3
4
  const io = require('../../../utils/io');
4
5
  const { createTask, resolve } = require('../../../utils/widgets');
5
6
  const { buildMpNpm } = require('../../../core/mpCi');
7
+ const { setCache, getCache } = require('../../../core/cache');
6
8
  const { CACHE_DIR } = require('../../../config/constant');
7
- const { mpNpmInstallAll } = require('../../../core/npm');
8
- const { fail } = require('../../../utils/log');
9
+ const { npmInstallAll } = require('../../../core/npm');
10
+ const { fail, info } = require('../../../utils/log');
11
+ const { fileMd5 } = require('../../../utils/md5');
12
+ const { isDependenciesUpdate } = require('../../../core/checkDependencies');
9
13
 
10
- async function install(tmsConfig, modules) {
14
+ async function install(tmsConfig, modules, env, useCache = true) {
15
+ const cwd = process.cwd();
16
+ const npmInstallRes = await createTask(
17
+ npmInstall,
18
+ '小程序 开始npm install',
19
+ '小程序npm install 完成',
20
+ )(tmsConfig, modules, useCache);
21
+
22
+ // 如果npm install 没有命中缓存,则说明node_module有更新,此时必须构建miniprogram_npm
23
+ if (!npmInstallRes.isCache) {
24
+ // 构建miniprogram_npm, 不使用缓存
25
+ await createTask(
26
+ mpCiInstall,
27
+ '开始构建miniprogram_npm',
28
+ '构建miniprogram_npm 完成',
29
+ )(tmsConfig, modules, false);
30
+ } else {
31
+ // 构建miniprogram_npm
32
+ await createTask(
33
+ mpCiInstall,
34
+ '开始构建miniprogram_npm',
35
+ '构建miniprogram_npm 完成',
36
+ )(tmsConfig, modules, useCache);
37
+ }
38
+ shelljs.cd(cwd);
39
+ }
40
+
41
+ async function npmInstall(tmsConfig, modules, useCache) {
42
+ // 如果依赖没有更新和使用缓存数据(则命中缓存)
43
+ if (!isDependenciesUpdate(modules, resolve('./'), tmsConfig.outputDir) && useCache) {
44
+ info('node_modules命中缓存');
45
+ return { isCache: true };
46
+ }
11
47
  // 拷贝模块的package.json到编译输出目录
12
48
  modules.forEach((item) => {
13
49
  const outputModuleDir = resolve(`${tmsConfig.outputDir}/${item.root}`);
@@ -20,19 +56,76 @@ async function install(tmsConfig, modules) {
20
56
  if (fs.existsSync(modulePackagePath)) shelljs.cp('-Rf', modulePackagePath, outputModuleDir);
21
57
  });
22
58
 
23
- // 小程序npm install
24
- await createTask(
25
- mpNpmInstallAll,
26
- '小程序 开始npm install',
27
- '小程序npm install 完成',
28
- )(modules, resolve(tmsConfig.outputDir), `${CACHE_DIR}/node_modules`);
29
-
30
- // 构建miniprogram_npm
31
- await createTask(
32
- buildMpNpm,
33
- '开始构建miniprogram_npm',
34
- '构建miniprogram_npm 完成',
35
- )({ appId: tmsConfig.appId, projectPath: resolve('./'), privateKey: tmsConfig.privateKey });
59
+ await npmInstallAll(modules, resolve(tmsConfig.outputDir), `${CACHE_DIR}/node_modules`);
60
+ return { isCache: false };
61
+ }
62
+
63
+ // 构建miniprogram_npm
64
+ async function mpCiInstall(tmsConfig, modules, useCache) {
65
+ const packageJsonFiles = [];
66
+ const rootPackFile = resolve(`${tmsConfig.outputDir}/package.json`);
67
+ if (fs.existsSync(rootPackFile)) {
68
+ packageJsonFiles.push(rootPackFile);
69
+ }
70
+ modules.forEach((item) => {
71
+ const packageJsonFile = resolve(`${tmsConfig.outputDir}/${item.root}/package.json`);
72
+ if (fs.existsSync(packageJsonFile)) {
73
+ packageJsonFiles.push(packageJsonFile);
74
+ }
75
+ });
76
+
77
+ let isCache = false;
78
+ const statusMap = { success: 1, doing: 2 };
79
+ if (useCache) {
80
+ let flag = true;
81
+ await Promise.all(packageJsonFiles.map(async (item) => {
82
+ const packageDir = path.dirname(item);
83
+ const mpDir = resolve(`${packageDir}/miniprogram_npm`);
84
+ const md5Value = await getMNPMd5(packageDir);
85
+ const preCache = getCache(mpDir, 'miniprogram_npm');
86
+ // console.log('miniprogram_npm', preCache, md5Value);
87
+ // 上一次构建成功 && 上次md5与当前本地的miniprogram_npm的md5 一致,才可以进入缓存
88
+ if (preCache?.status !== statusMap.success || preCache?.md5 !== md5Value) {
89
+ flag = false;
90
+ }
91
+ }));
92
+ isCache = flag;
93
+ }
94
+
95
+ if (isCache) {
96
+ info('miniprogram_npm命中缓存');
97
+ return;
98
+ }
99
+
100
+ // 即将构建,在cache中标记开始
101
+ await Promise.all(packageJsonFiles.map(async (item) => {
102
+ const packageDir = path.dirname(item);
103
+ const mpDir = resolve(`${packageDir}/miniprogram_npm`);
104
+ setCache(mpDir, 'miniprogram_npm', { md5: '', status: statusMap.doing });
105
+ }));
106
+
107
+ await buildMpNpm({ appId: tmsConfig.appId, projectPath: resolve('./'), privateKey: tmsConfig.privateKey });
108
+
109
+ // 构建成功后,计算md5写入cache
110
+ await Promise.all(packageJsonFiles.map(async (item) => {
111
+ const packageDir = path.dirname(item);
112
+ const mpDir = resolve(`${packageDir}/miniprogram_npm`);
113
+ const md5Value = await getMNPMd5(packageDir);
114
+ setCache(mpDir, 'miniprogram_npm', { md5: md5Value, status: statusMap.success });
115
+ }));
116
+ }
117
+
118
+ // 计算miniprogram_npm压缩文件的md5值
119
+ async function getMNPMd5(cwd) {
120
+ const shellJsOption = { async: false, silent: true };
121
+ shelljs.cd(cwd);
122
+ if (fs.existsSync('miniprogram_npm')) {
123
+ shelljs.exec('tar -cvf ./miniprogram_npm.tar.gz ./miniprogram_npm', { cwd, ...shellJsOption });
124
+ const md5Value = await fileMd5('./miniprogram_npm.tar.gz');
125
+ shelljs.rm('-rf', path.join(cwd, './miniprogram_npm.tar.gz'));
126
+ return md5Value;
127
+ }
128
+ return '';
36
129
  }
37
130
 
38
131
  module.exports = install;
@@ -0,0 +1,25 @@
1
+ const crypto = require('crypto');
2
+ const fs = require('fs');
3
+
4
+ function fileMd5(filePath) {
5
+ return new Promise((resolve, reject) => {
6
+ const md5sum = crypto.createHash('md5');
7
+ const stream = fs.ReadStream(filePath);
8
+ stream.on('data', (d) => {
9
+ md5sum.update(d);
10
+ });
11
+
12
+ stream.on('error', (err) => {
13
+ reject(err);
14
+ });
15
+
16
+ stream.on('end', () => {
17
+ const hash = md5sum.digest('hex');
18
+ resolve(hash);
19
+ });
20
+ });
21
+ }
22
+
23
+ module.exports = {
24
+ fileMd5,
25
+ };
@@ -5,6 +5,7 @@ const ora = require('ora');
5
5
  const path = require('path');
6
6
  const fs = require('fs');
7
7
  const shelljs = require('shelljs');
8
+ const glob = require('glob-ignore');
8
9
  const { info } = require('./log');
9
10
  const chalk = require('chalk');
10
11
  const shelljsOptions = { slient: true, async: false };
@@ -196,6 +197,18 @@ const filterField = (obj, filterNames = []) => {
196
197
  return newObj;
197
198
  };
198
199
 
200
+ // 检索出文件列表
201
+ function findFiles(globPath, filter = []) {
202
+ return new Promise((resolve, reject) => {
203
+ glob(globPath, filter, (err, files) => {
204
+ if (err) {
205
+ reject(err);
206
+ }
207
+ resolve(files);
208
+ });
209
+ });
210
+ }
211
+
199
212
  module.exports = {
200
213
  resolve,
201
214
  isObject,
@@ -209,4 +222,5 @@ module.exports = {
209
222
  mergeMap,
210
223
  relativeCwdPath,
211
224
  filterField,
225
+ findFiles,
212
226
  };
@@ -1,65 +0,0 @@
1
- const fs = require('fs');
2
- const { resolve } = require('../utils/widgets');
3
- const { MODULE_CODE_DIR } = require('../config/constant');
4
- const { checkRemoteModGitUrlBranch } = require('./cloneModules');
5
- const { checkDependencies } = require('./checkDependencies');
6
- const { fail } = require('../utils/log');
7
-
8
- function checkModule(targetModules) {
9
- // 判断\源码\dist\是否存在用户指定的模块
10
- for (const item of targetModules) {
11
- // 此模块没有root字段(原因:没有merge到module.config.json的配置项。第三方模块的代码可能还没有下载)
12
- if (!item.root) {
13
- return true;
14
- }
15
-
16
- // 判断第三方远程模块git地址与branch是否有更新
17
- if (checkRemoteModGitUrlBranch(MODULE_CODE_DIR, item)) {
18
- return true;
19
- }
20
-
21
- // 判断源码目录是否有该模块
22
- if (item.path && !fs.existsSync(resolve(item.path))) {
23
- fail(`${item.path}模块代码路径不存在, 请检查tms.config.js的${item.name}模块的path`);
24
- process.exit(1);
25
- }
26
- }
27
- return false;
28
- }
29
-
30
- function isInit(tmsConfig, targetModules, contextDir) {
31
- // 判断是否存在dist目录
32
- if (!fs.existsSync(contextDir)) {
33
- return true;
34
- }
35
- // 判断dist是否存在node_modules
36
- if (!fs.existsSync(`${contextDir}/node_modules`)) {
37
- return true;
38
- }
39
-
40
- // 判断dist是否存在miniprogram_npm
41
- if (!fs.existsSync(`${contextDir}/miniprogram_npm`)) {
42
- return true;
43
- }
44
-
45
- // 判断dist是否存在app.json
46
- if (!fs.existsSync(`${contextDir}/app.json`)) {
47
- return true;
48
- }
49
-
50
- // 判断模块信息
51
- if (checkModule(targetModules, contextDir)) {
52
- return true;
53
- }
54
-
55
- // 判断package.json的版本是否有新的版本
56
- if (checkDependencies(targetModules, resolve('./'), tmsConfig.outputDir)) {
57
- return true;
58
- }
59
- return false;
60
- }
61
-
62
-
63
- module.exports = {
64
- isInit,
65
- };