@tmsfe/tmskit 0.0.1
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 +0 -0
- package/README.md +24 -0
- package/dist/index.cjs.js +2248 -0
- package/main.js +3 -0
- package/package.json +72 -0
- package/rollup.config.js +179 -0
- package/src/config/constant.js +65 -0
- package/src/config/defaultTmsConfig.js +17 -0
- package/src/entry.js +20 -0
- package/src/index.js +47 -0
- package/src/init.js +38 -0
- package/src/scripts/create/ask.js +61 -0
- package/src/scripts/create/generator.js +27 -0
- package/src/scripts/create/ignoreFiles.js +7 -0
- package/src/scripts/create/index.js +65 -0
- package/src/scripts/create/render.js +19 -0
- package/src/scripts/run/build/index.js +16 -0
- package/src/scripts/run/dev/index.js +67 -0
- package/src/scripts/run/index.js +57 -0
- package/src/scripts/run/init/index.js +97 -0
- package/src/utils/buildAppJson.js +144 -0
- package/src/utils/checkDependencies.js +77 -0
- package/src/utils/cliUtils.js +35 -0
- package/src/utils/cloneModules.js +90 -0
- package/src/utils/global.js +36 -0
- package/src/utils/io.js +21 -0
- package/src/utils/log.js +44 -0
- package/src/utils/mpCiUtils.js +74 -0
- package/src/utils/npmUtils.js +126 -0
- package/src/utils/tkitUtils.js +84 -0
- package/src/utils/widgets.js +177 -0
- package/src/webpack/base.js +65 -0
- package/src/webpack/build.js +21 -0
- package/src/webpack/buildServer.js +34 -0
- package/src/webpack/dev.js +31 -0
- package/src/webpack/devServer.js +37 -0
- package/src/webpack/plugins/entryExtractPlugin/index.js +29 -0
- package/src/webpack/plugins/px2rpx/index.js +14 -0
- package/src/webpack/utils.js +244 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/* eslint-disable require-jsdoc */
|
|
2
|
+
const ci = require('miniprogram-ci');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 获取小程序ci的Project对象
|
|
7
|
+
* @returns {Object} 小程序ci对象
|
|
8
|
+
*/
|
|
9
|
+
const getMpCi = ({ appId, projectPath, type = 'miniProgram', privateKey = 'TODO' }) => {
|
|
10
|
+
const cfgJsonContent = require(path.join(projectPath, 'project.config.json'));
|
|
11
|
+
const ignores = cfgJsonContent?.packOptions?.ignore.map(({ value }) => value) || [];
|
|
12
|
+
|
|
13
|
+
return new ci.Project({
|
|
14
|
+
appid: appId,
|
|
15
|
+
privateKey,
|
|
16
|
+
type,
|
|
17
|
+
projectPath,
|
|
18
|
+
ignores: ['node_modules/**/*', ...ignores],
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
// 用小程序ci工具构建小程序
|
|
24
|
+
const packMpProject = async (project) => {
|
|
25
|
+
await ci.packNpm(project, {
|
|
26
|
+
ignores: ['cloud/**/*'],
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 格式化构建npm结果信息
|
|
32
|
+
* @param {Array<String>} warning 构建时的告警信息
|
|
33
|
+
* @returns {String} npm构建错误信息
|
|
34
|
+
*/
|
|
35
|
+
const formatPackNpmWarning = (warning) => {
|
|
36
|
+
if (!warning) {
|
|
37
|
+
return '';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const result = warning.map((it, index) => `${index + 1}. ${it.msg}
|
|
41
|
+
\t@ ${it.jsPath}:${it.tips}`).join('---------------\n');
|
|
42
|
+
|
|
43
|
+
return result;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 构建miniprogram_npm
|
|
48
|
+
* @returns {Object} 小程序ci对象
|
|
49
|
+
*/
|
|
50
|
+
const buildMpNpm = async ({
|
|
51
|
+
appId,
|
|
52
|
+
projectPath,
|
|
53
|
+
privateKey,
|
|
54
|
+
}) => {
|
|
55
|
+
const mpCi = await getMpCi({
|
|
56
|
+
appId,
|
|
57
|
+
projectPath,
|
|
58
|
+
privateKey,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const packNpmWarning = await packMpProject(mpCi);
|
|
62
|
+
|
|
63
|
+
const packNpmMsg = formatPackNpmWarning(packNpmWarning);
|
|
64
|
+
if (packNpmMsg) {
|
|
65
|
+
return Promise.reject(packNpmMsg);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return Promise.resolve();
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
module.exports = {
|
|
73
|
+
buildMpNpm,
|
|
74
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 本文件主要负责项目或者分包依赖的npm的安装
|
|
3
|
+
*/
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const shell = require('shelljs');
|
|
7
|
+
const LOG = require('./log');
|
|
8
|
+
|
|
9
|
+
const dirpath = process.cwd(); // 项目根目录
|
|
10
|
+
|
|
11
|
+
const getTarNpmFilename = targetDir => `${targetDir.replaceAll('/', '-')}.tar.gz`;
|
|
12
|
+
|
|
13
|
+
// 缓存npm包
|
|
14
|
+
const npmCache = function (targetDir, cacheDir) {
|
|
15
|
+
if (!fs.existsSync(cacheDir)) {
|
|
16
|
+
fs.mkdirSync(cacheDir);
|
|
17
|
+
}
|
|
18
|
+
const tarNpmFilename = getTarNpmFilename(targetDir);
|
|
19
|
+
const tarNpmFilePath = `${cacheDir}/${tarNpmFilename}`;
|
|
20
|
+
if (fs.existsSync(tarNpmFilePath)) {
|
|
21
|
+
shell.rm('-rf', tarNpmFilePath);
|
|
22
|
+
}
|
|
23
|
+
const cmd = `tar -zcvf ${tarNpmFilePath} ./node_modules`;
|
|
24
|
+
shell.exec(cmd, { async: true, silent: true });
|
|
25
|
+
// tar -zcvf /Users/odile/.tmskit/node_modules.tar.gz ./node_modules
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// 获取缓存npm包
|
|
29
|
+
const getNpmCache = function (targetDir, cacheDir) {
|
|
30
|
+
const tarNpmFilename = getTarNpmFilename(targetDir);
|
|
31
|
+
const tarNpmFilePath = `${cacheDir}/${tarNpmFilename}`;
|
|
32
|
+
if (fs.existsSync(tarNpmFilePath)) {
|
|
33
|
+
const cmd = `tar -zxvf ${tarNpmFilePath} -C ./`;
|
|
34
|
+
shell.exec(cmd, { async: false, silent: true });
|
|
35
|
+
}
|
|
36
|
+
// tar -zxvf /Users/odile/.tmskit/node_modules.tar.gz -C ./
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
// 遍历安装指定目录下所有项目的npm依赖
|
|
41
|
+
const npmInstallAll = async (modules, contextDir, cacheDir) => {
|
|
42
|
+
const packageJsonFiles = await findAllPackageJson(modules, contextDir);
|
|
43
|
+
|
|
44
|
+
await Promise.all(packageJsonFiles.map(file => new Promise((resolve) => {
|
|
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
|
+
})));
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 递归查找指定条件的文件
|
|
58
|
+
* @param {String} startPath 开始查找的根路径
|
|
59
|
+
* @param {String} filter 匹配的字符串
|
|
60
|
+
* @returns {Array<String>} 查找到的文件路径列表
|
|
61
|
+
*/
|
|
62
|
+
const findFilesByFilter = (startPath, filter) => {
|
|
63
|
+
const result = [];
|
|
64
|
+
/**
|
|
65
|
+
* 根据指定的筛选器查找文件
|
|
66
|
+
* @param {String} startPath 开始查找的文件夹路径
|
|
67
|
+
* @param {String} filter 筛选器
|
|
68
|
+
* @returns {Undefined} 无需返回值
|
|
69
|
+
*/
|
|
70
|
+
const find = (startPath, filter) => {
|
|
71
|
+
// 目录不存在
|
|
72
|
+
if (!fs.existsSync(startPath)) {
|
|
73
|
+
LOG.fail(`${startPath}目录不存在`);
|
|
74
|
+
process.exit(-1);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// 当前目录下的所有文件 / 文件夹
|
|
79
|
+
const exceptDir = ['node_modules', 'miniprogram_npm'];
|
|
80
|
+
if (exceptDir.find(item => startPath.indexOf(item) > -1)) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const files = fs.readdirSync(startPath);
|
|
84
|
+
files.forEach((file) => {
|
|
85
|
+
const filename = path.join(startPath, file);
|
|
86
|
+
const stat = fs.lstatSync(filename);
|
|
87
|
+
// 当前文件是文件夹类型,继续递归
|
|
88
|
+
if (stat.isDirectory()) {
|
|
89
|
+
find(filename, filter);
|
|
90
|
+
} else if (filename.indexOf(filter) >= 0) {
|
|
91
|
+
// 文件类型
|
|
92
|
+
result.push(filename);
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
find(startPath, filter);
|
|
98
|
+
return result;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* 找到项目中所有的package.json文件
|
|
103
|
+
* @param {Array<String>} subRoots 需要安装npm依赖的路径
|
|
104
|
+
* @param {String} contextDir 命令运行的目录
|
|
105
|
+
* @returns {Array<String>} 找到的所有package.json文件的路径
|
|
106
|
+
*/
|
|
107
|
+
const findAllPackageJson = (subRoots = [], contextDir) => {
|
|
108
|
+
const packageJsonName = 'package.json'; // 查找文件名
|
|
109
|
+
const cwd = contextDir || dirpath;
|
|
110
|
+
const result = [path.join(cwd, packageJsonName)]; // 默认填充根目录下的package.json
|
|
111
|
+
|
|
112
|
+
subRoots.forEach((subRoot) => {
|
|
113
|
+
const toppath = path.join(cwd, subRoot.root); // 从该目录开始查找package.json文件
|
|
114
|
+
const list = findFilesByFilter(toppath, packageJsonName);
|
|
115
|
+
|
|
116
|
+
result.push(...list);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
return result;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
module.exports = {
|
|
124
|
+
npmInstallAll,
|
|
125
|
+
findAllPackageJson,
|
|
126
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
const loadash = require('lodash');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const { TMS_NAME, TMS_CONFIG_FILENAME, MODULE_CONFIG_FILENAME } = require('../config/constant');
|
|
4
|
+
const { resolve, isObject } = require('./widgets');
|
|
5
|
+
const { setModuleConfig } = require('./buildAppJson');
|
|
6
|
+
const defaultTmsConfig = require('../config/defaultTmsConfig');
|
|
7
|
+
const { fail } = require('./log');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 读取tms.config.json
|
|
11
|
+
* @param env {string} 环境变量
|
|
12
|
+
*/
|
|
13
|
+
const readTmsConfig = function (env) {
|
|
14
|
+
const tmsConfigPath = resolve(TMS_CONFIG_FILENAME);
|
|
15
|
+
if (!fs.existsSync(tmsConfigPath)) {
|
|
16
|
+
fail('当前执行目录没有tms.config.js的配置项,请进行配置');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
const tmsConfigFn = require(tmsConfigPath);
|
|
20
|
+
const tmsConfig = tmsConfigFn({
|
|
21
|
+
env,
|
|
22
|
+
});
|
|
23
|
+
// 合并默认值
|
|
24
|
+
loadash.mergeWith(tmsConfig, defaultTmsConfig);
|
|
25
|
+
return tmsConfig;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 从tms.config.json中检索用户传入的有效modules
|
|
30
|
+
* @param { object } tmsConfig
|
|
31
|
+
* @param { array } modules
|
|
32
|
+
* @returns
|
|
33
|
+
*/
|
|
34
|
+
const checkModules = function (tmsConfig, modules) {
|
|
35
|
+
const targetModules = [];
|
|
36
|
+
modules.forEach((moduleName) => {
|
|
37
|
+
const module = tmsConfig.modules.find(module => module.name === moduleName);
|
|
38
|
+
module && targetModules.push(module);
|
|
39
|
+
});
|
|
40
|
+
if (targetModules.length === 0) {
|
|
41
|
+
fail(`你启动的模块无效,尝试 ${TMS_NAME} -m moduleName`);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
return targetModules;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* tms.config.js的modules 合并 module.config.json的配置项
|
|
49
|
+
* @param {array} modules
|
|
50
|
+
* @param {string} appName
|
|
51
|
+
* @param {string} moduleDir
|
|
52
|
+
* @returns
|
|
53
|
+
*/
|
|
54
|
+
const tmsModulesMergeLocalModuleCfg = (modules, appName, moduleDir) => {
|
|
55
|
+
const newModules = [];
|
|
56
|
+
modules.forEach(({ path: relativePath, name: moduleName }, moduleIndex) => {
|
|
57
|
+
const moduleConfigPath = resolve(relativePath, MODULE_CONFIG_FILENAME);
|
|
58
|
+
if (fs.existsSync(moduleConfigPath)) {
|
|
59
|
+
let moduleConfigContent = fs.readFileSync(moduleConfigPath, 'utf-8');
|
|
60
|
+
moduleConfigContent = setModuleConfig(moduleConfigContent, appName, moduleDir);
|
|
61
|
+
const moduleContentArr = isObject(moduleConfigContent) ? [moduleConfigContent] : moduleConfigContent;
|
|
62
|
+
moduleContentArr.forEach(({ name }, moduleContentArrIndex) => {
|
|
63
|
+
if (name === moduleName) {
|
|
64
|
+
newModules.push({
|
|
65
|
+
...modules[moduleIndex],
|
|
66
|
+
...moduleContentArr[moduleContentArrIndex],
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
} else {
|
|
71
|
+
newModules.push({
|
|
72
|
+
...modules[moduleIndex],
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return newModules;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
module.exports = {
|
|
81
|
+
readTmsConfig,
|
|
82
|
+
checkModules,
|
|
83
|
+
tmsModulesMergeLocalModuleCfg,
|
|
84
|
+
};
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
|
|
2
|
+
const program = require('commander');
|
|
3
|
+
const leven = require('leven');
|
|
4
|
+
const ora = require('ora');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const shelljs = require('shelljs');
|
|
8
|
+
const download = require('download-git-repo');
|
|
9
|
+
const chalk = require('chalk');
|
|
10
|
+
const shelljsOptons = { slient: true };
|
|
11
|
+
|
|
12
|
+
// 获取当前目录
|
|
13
|
+
const cwd = process.cwd();
|
|
14
|
+
function resolve(...args) {
|
|
15
|
+
return path.resolve(cwd, ...args);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 封装logs
|
|
20
|
+
* @returns {Undefined} 无需返回值
|
|
21
|
+
*/
|
|
22
|
+
const log = (...args) => console.log(...args);
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 用户输入命令时,进行提示
|
|
26
|
+
* @param {String} unknownCommand 非预期的命令
|
|
27
|
+
* @returns {Undefined} 无需返回值
|
|
28
|
+
*/
|
|
29
|
+
const suggestCommands = (unknownCommand) => {
|
|
30
|
+
const availableCommands = program.commands.map(cmd => cmd._name);
|
|
31
|
+
|
|
32
|
+
let suggestion;
|
|
33
|
+
availableCommands.forEach((cmd) => {
|
|
34
|
+
const isBestMatch = leven(cmd, unknownCommand) < leven(suggestion || '', unknownCommand);
|
|
35
|
+
if (leven(cmd, unknownCommand) < 3 && isBestMatch) {
|
|
36
|
+
suggestion = cmd;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (suggestion) {
|
|
41
|
+
log(` ${chalk.red(`Did you mean ${chalk.yellow(suggestion)}?`)}`);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 判断变量是否是一个数组
|
|
47
|
+
* @param { unknown } obj 变量
|
|
48
|
+
* @returns { boolean } 是否是一个数组
|
|
49
|
+
*/
|
|
50
|
+
function isObject(obj) {
|
|
51
|
+
return Object.prototype.toString.call(obj) === '[object Object]';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 判断变量是否是一个对象
|
|
56
|
+
* @param { unknown } obj 变量
|
|
57
|
+
* @returns { boolean } 是否是一个对象
|
|
58
|
+
*/
|
|
59
|
+
function isArray(obj) {
|
|
60
|
+
return Object.prototype.toString.call(obj) === '[object Array]';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 下载模块到目标目录
|
|
65
|
+
* @param { string } dest 目标地址
|
|
66
|
+
* @param { object } downloadOptions 模块下载配置 { repoUrl-仓库地址, gitUrl-git地址, branch-分支或者tag }
|
|
67
|
+
* @returns { undefined } no return
|
|
68
|
+
*/
|
|
69
|
+
function downloadRepo(dest, downloadOptions = { repoUrl: '', gitUrl: '', branch: '' }) {
|
|
70
|
+
const { repoUrl, gitUrl, branch } = downloadOptions;
|
|
71
|
+
|
|
72
|
+
if (fs.existsSync(dest)) {
|
|
73
|
+
shelljs.rm('-rf', dest);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
shelljs.mkdir('-p', dest);
|
|
77
|
+
return new Promise((resolve) => {
|
|
78
|
+
download(`${repoUrl}#${branch}`, dest, { clone: true }, async (e) => {
|
|
79
|
+
if (e) {
|
|
80
|
+
console.log(e) // eslint-disable-line
|
|
81
|
+
await downloadRepoForGit(gitUrl, dest, branch);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
resolve();
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* 下载模块到目标目录备用方案
|
|
91
|
+
* @param { string } url 模块地址
|
|
92
|
+
* @param { string } dest 目标地址
|
|
93
|
+
* @param { string } branch 分支名
|
|
94
|
+
* @returns { undefined } no return
|
|
95
|
+
*/
|
|
96
|
+
function downloadRepoForGit(url, dest, branch) {
|
|
97
|
+
const cwd = process.cwd();
|
|
98
|
+
|
|
99
|
+
return new Promise((resolve, reject) => {
|
|
100
|
+
// 如果目标目录不存在
|
|
101
|
+
if (fs.existsSync(dest)) {
|
|
102
|
+
shelljs.rm('-rf', path.join(dest));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
shelljs.mkdir('-p', dest);
|
|
106
|
+
shelljs.cd(dest);
|
|
107
|
+
|
|
108
|
+
shelljs.exec(`git clone ${url} ${dest} --depth=1`, shelljsOptons);
|
|
109
|
+
|
|
110
|
+
shelljs.exec(`git checkout ${branch}`, (code) => {
|
|
111
|
+
if (code === 0) {
|
|
112
|
+
shelljs.cd(cwd);
|
|
113
|
+
|
|
114
|
+
resolve();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
reject();
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* 计算各项任务耗时
|
|
124
|
+
* @param {Number} start 任务开始时间
|
|
125
|
+
* @returns {Undefined} 无需返回值
|
|
126
|
+
*/
|
|
127
|
+
const cost = start => Date.now() - start;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* 创建构建子任务
|
|
131
|
+
* @param {Function} task 子任务执行函数
|
|
132
|
+
* @param {String} startText 任务开始前提示语
|
|
133
|
+
* @param {String} endText 任务结束后提示语
|
|
134
|
+
* @returns {Undefined} 无需返回值
|
|
135
|
+
*/
|
|
136
|
+
function createTask(task, startText, endText) {
|
|
137
|
+
return async (...args) => {
|
|
138
|
+
const start = Date.now();
|
|
139
|
+
let result;
|
|
140
|
+
|
|
141
|
+
const spinner = ora(startText);
|
|
142
|
+
spinner.start();
|
|
143
|
+
|
|
144
|
+
try {
|
|
145
|
+
result = await task(...args);
|
|
146
|
+
} catch (e) {
|
|
147
|
+
result = e;
|
|
148
|
+
console.log(chalk.red(e));
|
|
149
|
+
|
|
150
|
+
process.exit(-1);
|
|
151
|
+
} finally {
|
|
152
|
+
endText && spinner.succeed(`${endText}, ${cost(start)}ms`);
|
|
153
|
+
spinner.stop();
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return result;
|
|
157
|
+
};
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* 字符串驼峰化处理
|
|
162
|
+
* @param {String} str 需要处理的字符串
|
|
163
|
+
* @returns {String} 经过驼峰处理的字符串
|
|
164
|
+
*/
|
|
165
|
+
const camelize = str => str.replace(/-(\w)/g, (a, c) => (c ? c.toUpperCase() : ''));
|
|
166
|
+
|
|
167
|
+
module.exports = {
|
|
168
|
+
resolve,
|
|
169
|
+
log,
|
|
170
|
+
isObject,
|
|
171
|
+
isArray,
|
|
172
|
+
createTask,
|
|
173
|
+
downloadRepo,
|
|
174
|
+
downloadRepoForGit,
|
|
175
|
+
suggestCommands,
|
|
176
|
+
camelize,
|
|
177
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const WebpackChain = require('webpack-chain');
|
|
2
|
+
const webpack = require('webpack');
|
|
3
|
+
const { getEntry, stringified, getAlias } = require('./utils');
|
|
4
|
+
const { resolve } = require('../utils/widgets');
|
|
5
|
+
const { DEFAULT_WEBPACK_ENTRY, DEFAULT_MODULE_DIR } = require('../config/constant');
|
|
6
|
+
|
|
7
|
+
module.exports = (tmsConfig, modules) => {
|
|
8
|
+
const { envData = {}, webpack: tmsWebpack } = tmsConfig;
|
|
9
|
+
let webpackConfig = new WebpackChain();
|
|
10
|
+
|
|
11
|
+
const alias = getAlias(modules);
|
|
12
|
+
const entry = getEntry(DEFAULT_WEBPACK_ENTRY, modules, tmsConfig, DEFAULT_MODULE_DIR);
|
|
13
|
+
webpackConfig.merge({
|
|
14
|
+
entry,
|
|
15
|
+
output: {
|
|
16
|
+
path: resolve(`./${tmsWebpack.outputDir}`),
|
|
17
|
+
libraryTarget: 'commonjs2',
|
|
18
|
+
filename: '[name]',
|
|
19
|
+
},
|
|
20
|
+
// TODO 有报错,先注释掉
|
|
21
|
+
// cache: {
|
|
22
|
+
// type: 'filesystem',
|
|
23
|
+
// cacheDirectory: resolve(`./${tmsConfig.webpack.outputDir}/node_modules/.cache`),
|
|
24
|
+
// },
|
|
25
|
+
resolve: {
|
|
26
|
+
extensions: ['.tsx', '.ts', '.js'],
|
|
27
|
+
alias: Object.assign(tmsWebpack.alias, alias),
|
|
28
|
+
},
|
|
29
|
+
devtool: tmsWebpack.sourceMap ? 'source-map' : false,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
webpackConfig.module
|
|
33
|
+
.rule('ts-loader')
|
|
34
|
+
.test(/\.ts$/)
|
|
35
|
+
.use('ts-loader')
|
|
36
|
+
.loader(require.resolve('ts-loader'))
|
|
37
|
+
.options({
|
|
38
|
+
configFile: resolve('./tsconfig.json'),
|
|
39
|
+
// 只进行语法转换,不进行类型校验,提高构建速度
|
|
40
|
+
transpileOnly: true,
|
|
41
|
+
})
|
|
42
|
+
.end();
|
|
43
|
+
|
|
44
|
+
// webpackConfig.module
|
|
45
|
+
// .rule('babel')
|
|
46
|
+
// .test(/\.(js|mjs|jsx|ts|tsx)$/)
|
|
47
|
+
// .pre()
|
|
48
|
+
// .exclude.add(/(node_modules|miniprogram_npm)/).end()
|
|
49
|
+
// .use(require.resolve('babel-loader'))
|
|
50
|
+
// .loader(require.resolve('babel-loader'));
|
|
51
|
+
|
|
52
|
+
webpackConfig
|
|
53
|
+
.plugin('definePlugin')
|
|
54
|
+
.use(webpack.DefinePlugin, [stringified(envData)])
|
|
55
|
+
.end();
|
|
56
|
+
|
|
57
|
+
// 执行tms.config.js自定义的webpackChain
|
|
58
|
+
if (tmsWebpack.webpackChain) {
|
|
59
|
+
webpackConfig = tmsWebpack.webpackChain(webpackConfig, {
|
|
60
|
+
modules,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return webpackConfig;
|
|
65
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const webpackConfig = require('./base');
|
|
2
|
+
const { DEFAULT_COPY_CONFIG } = require('../config/constant');
|
|
3
|
+
const { getCopyPlugin } = require('./utils');
|
|
4
|
+
|
|
5
|
+
module.exports = (...args) => {
|
|
6
|
+
const [tmsConfig, modules] = args;
|
|
7
|
+
const webpackBuildConfig = webpackConfig(...args);
|
|
8
|
+
|
|
9
|
+
webpackBuildConfig.mode('production');
|
|
10
|
+
|
|
11
|
+
const copyPluginParams = getCopyPlugin(DEFAULT_COPY_CONFIG, modules, tmsConfig, 'build');
|
|
12
|
+
// console.log('copyPluginParams', copyPluginParams);
|
|
13
|
+
webpackBuildConfig
|
|
14
|
+
.plugin('copy-webpack-plugin')
|
|
15
|
+
.use(require('copy-webpack-plugin'), [{
|
|
16
|
+
patterns: copyPluginParams,
|
|
17
|
+
}])
|
|
18
|
+
.end();
|
|
19
|
+
|
|
20
|
+
return webpackBuildConfig;
|
|
21
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const webpack = require('webpack');
|
|
2
|
+
const webBuildConfig = require('./build');
|
|
3
|
+
const { createTask } = require('../utils/widgets');
|
|
4
|
+
const { fail } = require('../utils/log');
|
|
5
|
+
|
|
6
|
+
function compilerRun(compiler) {
|
|
7
|
+
return new Promise((resolve) => {
|
|
8
|
+
compiler.run((err, stats) => {
|
|
9
|
+
resolve({ err, stats });
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
module.exports = async (...args) => {
|
|
15
|
+
const config = webBuildConfig(...args);
|
|
16
|
+
const compiler = webpack(config.toConfig());
|
|
17
|
+
|
|
18
|
+
const { err, stats } = await createTask(compilerRun, '开始webpack打包编译', 'webpack打包编译完成')(compiler);;
|
|
19
|
+
|
|
20
|
+
if (err) {
|
|
21
|
+
fail(err);
|
|
22
|
+
console.log('详细的错误信息:', err);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (stats.hasErrors() || stats.hasWarnings()) {
|
|
26
|
+
console.log(stats.toString({
|
|
27
|
+
// 增加控制台颜色开关
|
|
28
|
+
colors: true,
|
|
29
|
+
errorDetails: true,
|
|
30
|
+
}));
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return compiler;
|
|
34
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const webpackConfig = require('./base');
|
|
2
|
+
const { DEFAULT_COPY_CONFIG } = require('../config/constant');
|
|
3
|
+
const { getCopyPlugin } = require('./utils');
|
|
4
|
+
|
|
5
|
+
module.exports = (...args) => {
|
|
6
|
+
const [tmsConfig, modules] = args;
|
|
7
|
+
const webpackDevConfig = webpackConfig(...args);
|
|
8
|
+
|
|
9
|
+
webpackDevConfig.devtool('source-map');
|
|
10
|
+
|
|
11
|
+
webpackDevConfig.mode('development');
|
|
12
|
+
|
|
13
|
+
const copyPluginParams = getCopyPlugin(DEFAULT_COPY_CONFIG, modules, tmsConfig, 'dev');
|
|
14
|
+
// console.log('copyPluginParams', copyPluginParams);
|
|
15
|
+
webpackDevConfig
|
|
16
|
+
.plugin('copy-webpack-plugin')
|
|
17
|
+
.use(require('copy-webpack-plugin'), [{
|
|
18
|
+
patterns: copyPluginParams,
|
|
19
|
+
}])
|
|
20
|
+
.end();
|
|
21
|
+
|
|
22
|
+
webpackDevConfig
|
|
23
|
+
.plugin('ExtractPlugin')
|
|
24
|
+
.use(require('./plugins/entryExtractPlugin'), [{
|
|
25
|
+
tmsConfig,
|
|
26
|
+
modules,
|
|
27
|
+
}])
|
|
28
|
+
.end();
|
|
29
|
+
|
|
30
|
+
return webpackDevConfig;
|
|
31
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const webpack = require('webpack');
|
|
2
|
+
const webDevConfig = require('./dev');
|
|
3
|
+
const { setupDevWebPackHooks } = require('./utils');
|
|
4
|
+
const { fail } = require('../utils/log');
|
|
5
|
+
|
|
6
|
+
module.exports = (...args) => {
|
|
7
|
+
const config = webDevConfig(...args);
|
|
8
|
+
const compiler = webpack(config.toConfig());
|
|
9
|
+
|
|
10
|
+
setupDevWebPackHooks({
|
|
11
|
+
compiler,
|
|
12
|
+
}, () => {
|
|
13
|
+
// TODO 判断open参数,打开微信开发者工具
|
|
14
|
+
// openDevtool(api.resolve(config.outputDir || 'dist'))
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
compiler.watch(
|
|
18
|
+
{
|
|
19
|
+
aggregateTimeout: 1000,
|
|
20
|
+
poll: undefined,
|
|
21
|
+
},
|
|
22
|
+
(err, stats) => {
|
|
23
|
+
if (err) {
|
|
24
|
+
fail(err);
|
|
25
|
+
console.log('详细的错误信息:', err);
|
|
26
|
+
}
|
|
27
|
+
if (stats.hasErrors() || stats.hasWarnings()) {
|
|
28
|
+
console.log(stats.toString({
|
|
29
|
+
// 增加控制台颜色开关
|
|
30
|
+
colors: true,
|
|
31
|
+
}));
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
return compiler;
|
|
37
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const SingleEntryPlugin = require('webpack/lib/SingleEntryPlugin');
|
|
2
|
+
const { DEFAULT_WEBPACK_ENTRY, DEFAULT_MODULE_DIR } = require('../../../config/constant');
|
|
3
|
+
const { getEntry } = require('../../utils');
|
|
4
|
+
|
|
5
|
+
class EntryExtraPlugin {
|
|
6
|
+
constructor(options = {}) {
|
|
7
|
+
this.options = options;
|
|
8
|
+
this.scriptExtensions = options.scriptExtensions || ['.ts', '.js'];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
applyEntry(compiler, entry) {
|
|
12
|
+
const { context } = compiler.options;
|
|
13
|
+
|
|
14
|
+
Object.keys(entry).forEach((key) => {
|
|
15
|
+
new SingleEntryPlugin(context, entry[key], key).apply(compiler);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
apply(compiler) {
|
|
20
|
+
const { tmsConfig = {}, modules = [] } = this.options;
|
|
21
|
+
|
|
22
|
+
compiler.hooks.watchRun.tap('EntryExtraPlugin', () => {
|
|
23
|
+
const entry = getEntry(DEFAULT_WEBPACK_ENTRY, modules, tmsConfig, DEFAULT_MODULE_DIR);
|
|
24
|
+
this.applyEntry(compiler, entry);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
module.exports = EntryExtraPlugin;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const px2rpx = postcss.plugin('postcss-px2rpx', (opts = {}) => {
|
|
2
|
+
const { proportion = 1, minPixelValue = 0 } = opts;
|
|
3
|
+
|
|
4
|
+
return (root) => {
|
|
5
|
+
root.replaceValues(pxRegExp, { fast: 'px' }, (string) => {
|
|
6
|
+
const pixels = parseInt(string, 10);
|
|
7
|
+
if (pixels < minPixelValue) return `${pixels}px`;
|
|
8
|
+
return `${proportion * parseInt(string, 10)}rpx`;
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
export default px2rpx;
|