@tmsfe/tmskit 0.0.5-beta.3 → 0.0.5-beta.4

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.
@@ -0,0 +1,194 @@
1
+ /* eslint-disable no-param-reassign */
2
+ const through = require('through2');
3
+ const htmlparser2 = require('htmlparser2');
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const { diffContentCopyFile, ext, fileInDir } = require('../../utils/io');
7
+ const { resolve } = require('../../utils/widgets');
8
+ const { dfsFindCommonDep } = require('./mpCommonDep');
9
+ const { pluginError } = require('./utils/pluginError');
10
+
11
+ // 处理后缀(源码引入依赖时,不带后缀的情况)
12
+ const extFile = function (name, file) {
13
+ const extMap = {
14
+ import: '.wxml',
15
+ include: '.wxml',
16
+ wxs: '.wxs',
17
+ };
18
+ let extObj = {};
19
+
20
+ if (Object.keys(extMap).indexOf(name) > -1 && !file.endsWith(extMap[name])) {
21
+ extObj = ext(file, [extMap[name]]);
22
+ }
23
+ return {
24
+ extPath: extObj.extPath || '',
25
+ ext: extObj.ext || '',
26
+ file: extObj.file || file,
27
+ };
28
+ };
29
+
30
+ const dfsFindWxmlDep = function (anaFileOriginFile, anaFileDestFile, isWatch = true) {
31
+ const resDep = {
32
+ image: new Map(),
33
+ wxml: new Map(),
34
+ wxs: new Map(),
35
+ };
36
+ function dfs(anaFileOriginFile, anaFileDestFile) {
37
+ let contents = '';
38
+ try {
39
+ contents = fs.readFileSync(anaFileOriginFile, 'utf8');
40
+ } catch (e) {
41
+ pluginError(e, isWatch);
42
+ }
43
+ const parser = new htmlparser2.Parser({
44
+ onopentag(name, attributes) {
45
+ if (attributes?.src?.startsWith('.')) {
46
+ const depOriginPath = path.join(path.dirname(anaFileOriginFile), attributes.src);
47
+ // 被依赖文件加上后缀
48
+ const { ext, file: depOriginFile, extPath } = extFile(name, depOriginPath);
49
+
50
+ if (!fs.existsSync(depOriginFile)) {
51
+ pluginError(
52
+ new Error(`${anaFileOriginFile}引用的路径${depOriginFile}找不到应用文件,请检查引用路径`),
53
+ isWatch,
54
+ );
55
+ return;
56
+ }
57
+
58
+ const depDestPath = path.join(path.dirname(anaFileDestFile), attributes.src);
59
+ const depDestFile = depDestPath.endsWith(ext) ? depDestPath : depDestPath + extPath;
60
+
61
+ // 收集wxml依赖
62
+ if (['import', 'include'].indexOf(name) > -1) {
63
+ resDep.wxml.set(depDestFile, {
64
+ anaFileOriginFile,
65
+ anaFileDestFile,
66
+ depDestFile,
67
+ depOriginFile,
68
+ });
69
+ dfs(depOriginFile, depDestFile);
70
+ }
71
+ // 收集image依赖
72
+ // if (name === 'image') {
73
+ // resDep.image.set(attributes.src, {
74
+ // anaFileOriginFile,
75
+ // anaFileDestFile,
76
+ // depDestFile,
77
+ // depOriginFile,
78
+ // });
79
+ // dfs(depOriginFile, depDestFile);
80
+ // }
81
+ // 收集wxs依赖
82
+ if (name === 'wxs') {
83
+ resDep.wxs.set(depDestFile, {
84
+ anaFileOriginFile,
85
+ anaFileDestFile,
86
+ depDestFile,
87
+ depOriginFile,
88
+ });
89
+ const defs = dfsFindCommonDep(depOriginFile, depDestFile, ['.wxs']);
90
+ defs.forEach((item, key) => {
91
+ resDep.wxs.set(key, item);
92
+ });
93
+ }
94
+ }
95
+ },
96
+ });
97
+ parser.write(contents);
98
+ parser.end();
99
+ }
100
+ dfs(anaFileOriginFile, anaFileDestFile);
101
+
102
+ return resDep;
103
+ };
104
+
105
+ function mpWxmlDep(tmsConfig, module, isWatch) {
106
+ const stream = through.obj(function (file, enc, cb) {
107
+ // 依赖分析的文件
108
+ const anaFileOriginFile = file.history[0];
109
+ const anaFileRelativeModule = path.relative(resolve(module.from), anaFileOriginFile);
110
+ const anaFileDestFile = resolve(tmsConfig.gulp.outputDir, module.to, anaFileRelativeModule);
111
+
112
+ if (file.isBuffer()) {
113
+ let contents = String(file.contents);
114
+ const copyModules = new Map();
115
+ const parser = new htmlparser2.Parser({
116
+ onopentag(name, attributes) {
117
+ const nameFilter = ['import', 'include', 'wxs'];
118
+ if (nameFilter.indexOf(name) > -1 && attributes.src) {
119
+ const depOriginPath = path.join(path.dirname(anaFileOriginFile), attributes.src);
120
+ // 处理后缀(源码引入依赖时,后缀不全的情况)
121
+ const { ext, file: depOriginFile, extPath } = extFile(name, depOriginPath);
122
+
123
+ Object.keys(tmsConfig.gulp.dependencies).forEach((includeName) => {
124
+ if (attributes.src.indexOf(includeName) > -1) {
125
+ const includePath = tmsConfig.gulp.dependencies[includeName];
126
+
127
+ if (!fileInDir(includePath, depOriginFile)) {
128
+ pluginError(
129
+ new Error(`${anaFileOriginFile}引用路径${depOriginFile}不在${includePath}不在文件夹内, 请检查应用路径`),
130
+ isWatch,
131
+ );
132
+ return;
133
+ }
134
+
135
+ // eslint-disable-next-line
136
+ const reg = new RegExp(`^(\.\.\/)+.*\/${includeName}\/(.*)`);
137
+ const regRes = attributes.src.match(reg) || [];
138
+ if (regRes[2]) {
139
+ const depDestPath = resolve(tmsConfig.gulp.outputDir, module.to, includeName, regRes[2]);
140
+ const depDestFile = depDestPath.endsWith(ext) ? depDestPath : depDestPath + extPath;
141
+ if (!copyModules.has(depDestFile)) {
142
+ copyModules.set(depDestFile, {
143
+ depOriginFile,
144
+ depDestFile,
145
+ beforeDepPath: attributes.src,
146
+ afterDepPath: path.relative(path.dirname(anaFileDestFile), depDestFile),
147
+ });
148
+ }
149
+ }
150
+ }
151
+ });
152
+ }
153
+ },
154
+ });
155
+ parser.write(contents);
156
+ parser.end();
157
+
158
+ // console.log('wxml copyModules', copyModules);
159
+ copyModules.forEach(({ depOriginFile, depDestFile, beforeDepPath, afterDepPath }) => {
160
+ if (fs.existsSync(depOriginFile)) {
161
+ diffContentCopyFile(depOriginFile, depDestFile);
162
+ const reg = new RegExp(`['"]${beforeDepPath}["']`, 'g');
163
+ contents = contents.replace(reg, `"${afterDepPath}"`);
164
+ }
165
+ if (depOriginFile.endsWith('.wxml')) {
166
+ const defs = dfsFindWxmlDep(depOriginFile, depDestFile, isWatch);
167
+ // console.log('wxml defs', defs);
168
+ [...defs.wxml, ...defs.wxs].forEach(([, item]) => {
169
+ diffContentCopyFile(item.depOriginFile, item.depDestFile);
170
+ });
171
+ }
172
+ if (depOriginFile.endsWith('.wxs')) {
173
+ const defs = dfsFindCommonDep(depOriginFile, depDestFile, ['.wxs'], isWatch);
174
+ // console.log('wxs defs', defs);
175
+ defs.forEach((item) => {
176
+ diffContentCopyFile(item.depOriginFile, item.depDestFile);
177
+ });
178
+ }
179
+ });
180
+
181
+ file.contents = new Buffer(contents);
182
+ }
183
+
184
+ this.push(file);
185
+ cb();
186
+ });
187
+
188
+ return stream;
189
+ }
190
+
191
+ module.exports = {
192
+ mpWxmlDep,
193
+ dfsFindWxmlDep,
194
+ };
@@ -0,0 +1,72 @@
1
+ /* eslint-disable no-param-reassign */
2
+ const postcss = require('postcss');
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { fail } = require('../../utils/log');
6
+
7
+ module.exports = postcss.plugin('postcss-font-base64', (options) => {
8
+ options = {
9
+ ...options,
10
+ ...{
11
+ match: { Scrabble: ['fakefont'] },
12
+ format: ['eot', 'woff', 'woff2', 'ttf'],
13
+ },
14
+ };
15
+
16
+ return function (css, result) {
17
+ css.walkAtRules('font-face', (fontFace) => {
18
+ const fileTypeRegex = getRegexStringForFileTypes(options.format);
19
+
20
+ fontFace.replaceValues(new RegExp(`url\\(["']?.+\\.${fileTypeRegex}["']?\\)`), (attr) => {
21
+ const fontRePath = attr.replace(/(url|'|"|\(|\)|\?#iefix)/g, '');
22
+ const fontAbPath = path.join(path.dirname(result.opts.from), fontRePath);
23
+ const res64 = base64Encode(fontAbPath);
24
+ const newUrlStr = 'url(data:'.concat(getMimeType(attr)).concat(';charset=utf-8;base64,')
25
+ .concat(res64)
26
+ .concat(')');
27
+ return res64 ? newUrlStr : attr;
28
+ });
29
+ });
30
+
31
+ function getRegexStringForFileTypes(fileTypes) {
32
+ const regex = fileTypes.map(fileType => (
33
+ fileType === 'eot'
34
+ ? fileType.concat('(\\?#iefix)?')
35
+ : fileType)).join('|');
36
+ return regex ? `(${regex})` : '';
37
+ }
38
+
39
+ // helper functions
40
+ function getMimeType(attribute) {
41
+ const formats = {
42
+ '.woff': 'application/font-woff',
43
+ '.woff2': 'font/woff2',
44
+ '.ttf': 'application/font-sfnt',
45
+ '.eot': 'application/vnd.ms-fontobject',
46
+ '.otf': 'application/font-sfnt',
47
+ };
48
+
49
+ let match = '';
50
+ const extension = attribute.match(/\.[a-z]{3,4}/)[0];
51
+
52
+ if (extension in formats) {
53
+ match = formats[extension];
54
+ };
55
+ return match;
56
+ };
57
+
58
+ function base64Encode(file) {
59
+ if (fs.existsSync(file)) {
60
+ return readAndEncodeFile(file);
61
+ }
62
+
63
+ fail(`${file} does not exist.`);
64
+ return '';
65
+ }
66
+
67
+ function readAndEncodeFile(file) {
68
+ const bitmap = fs.readFileSync(file);
69
+ return new Buffer(bitmap).toString('base64');
70
+ }
71
+ };
72
+ });
@@ -0,0 +1,25 @@
1
+ /* eslint-disable no-param-reassign */
2
+ const { fail } = require('../../../utils/log');
3
+
4
+ function pluginError(error, isWatch) {
5
+ const errorOptions = { showStack: true };
6
+
7
+ errorOptions.error = error;
8
+ errorOptions.fileName = error.file;
9
+ errorOptions.lineNumber = error.line;
10
+ errorOptions.showProperties = false;
11
+ errorOptions.showStack = false;
12
+
13
+ const errMsg = error.message;
14
+
15
+ if (isWatch) {
16
+ fail(errMsg);
17
+ } else {
18
+ fail(errMsg);
19
+ process.exit(1);
20
+ }
21
+ }
22
+
23
+ module.exports = {
24
+ pluginError,
25
+ };
@@ -1,5 +1,5 @@
1
1
  const fs = require('fs');
2
- const { DEFAULT_MODULE_DIR, MODULE_CONFIG_FILENAME } = require('../config/constant');
2
+ const { DEFAULT_MODULE_DIR, 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
5
 
@@ -98,7 +98,7 @@ const getAppJsonContent = (sourceAppJsonPath) => {
98
98
  // 加入默认值
99
99
  appJson.subpackages = [];
100
100
  appJson.pages = [];
101
- appJson.plugins = {};
101
+ // appJson.plugins = {};
102
102
  delete appJson.entranceDeclare;
103
103
  return appJson;
104
104
  };
@@ -116,6 +116,60 @@ const updateSubpackages = (appJson, modulesConfig) => {
116
116
  }
117
117
  };
118
118
 
119
+ /**
120
+ * 处理合并subpackages后的appjson, 整理重复不合法的地方
121
+ * @param {Object} appJson appjson
122
+ */
123
+ const processAppJson = (appJson) => {
124
+ const { subpackages } = appJson;
125
+ const pluginsMap = {};
126
+ Object.keys(appJson.plugins || {}).forEach(key => pluginsMap[key] = ['app.json']);
127
+ const subps = subpackages.map((subp) => {
128
+ const invalidKeys = [];
129
+ Object.keys(subp).forEach((key) => {
130
+ if (key === 'plugins') {
131
+ Object.keys(subp.plugins).forEach((pk) => {
132
+ pluginsMap[pk] ? pluginsMap[pk].push(`分包${subp.name}`) : pluginsMap[pk] = [`分包${subp.name}`];
133
+ });
134
+ return;
135
+ }
136
+ if (MODULE_CONFIG_INVALID_KEY.indexOf(key) > -1) {
137
+ // 如果分包配置中有不支持的key,则错误提醒
138
+ invalidKeys.push(key);
139
+ return;
140
+ }
141
+ if (['requiredBackgroundModes', 'embeddedAppIdList'].indexOf(key) > -1) {
142
+ // 提到appjson最上层处理
143
+ const preVal = appJson[key];
144
+ // eslint-disable-next-line
145
+ preVal ? appJson[key] = Array.from(new Set(preVal
146
+ // eslint-disable-next-line
147
+ .slice(0).concat(subp[key]))) : appJson[key] = subp[key].slice(0);
148
+ return;
149
+ }
150
+ });
151
+ if (invalidKeys.length) {
152
+ fail(`不支持分包${subp?.name}配置${invalidKeys.join(',')}\n`);
153
+ }
154
+ // eslint-disable-next-line
155
+ invalidKeys.concat(['requiredBackgroundModes', 'embeddedAppIdList']).forEach(k => delete subp[k]);
156
+ return subp;
157
+ });
158
+ // 如果plugins重复,则错误提示
159
+ const pluginsErrMsg = Object.keys(pluginsMap).map((pk) => {
160
+ if (pluginsMap[pk].length > 1) {
161
+ return `${pluginsMap[pk].join(',')}重复配置plugin(${pk});`;
162
+ }
163
+ return '';
164
+ })
165
+ .reduce((pre, cur) => pre + cur, '');
166
+ if (pluginsErrMsg) {
167
+ fail(pluginsErrMsg);
168
+ }
169
+ // eslint-disable-next-line
170
+ appJson.subpackages = subps;
171
+ };
172
+
119
173
 
120
174
  /**
121
175
  * 动态生成编译后的app.json
@@ -130,6 +184,8 @@ function buildOutputAppJson(tmsConfig, modules) {
130
184
  const appJson = getAppJsonContent(resolve('./app.json'));
131
185
  // 更新app.json中的subpackages
132
186
  updateSubpackages(appJson, modulesConfig);
187
+ // 处理appJson中重复||冲突的地方
188
+ processAppJson(appJson);
133
189
  // 更新主包,需在subpackages处理完成后执行, pages/
134
190
  updateMainPackages(appJson, tmsConfig.mainPackages, DEFAULT_MODULE_DIR);
135
191
 
@@ -0,0 +1,30 @@
1
+ /* eslint-disable no-param-reassign */
2
+ const strip = require('strip-comments');
3
+ // 匹配规则
4
+ const MATCH_RULE = new RegExp(/@import *(?:url\(['"]?([^'")]+)['"]?\)|['"]([^'"]+)['"]);?/g);
5
+
6
+ /**
7
+ * 获取样式文件中的@import语句
8
+ * @param code 代码片段
9
+ * @returns 结果数组
10
+ */
11
+ const findCssImports = (code) => {
12
+ // 将buffer转成字符串
13
+ code = code.toString();
14
+ // 去除注释
15
+ code = strip.block(code);
16
+ // 定义最后返回的结果
17
+ const result = [];
18
+ let matchList;
19
+ // 循环遍历代码段,直至匹配结果为空
20
+ while ((matchList = MATCH_RULE.exec(code))) {
21
+ // 存入结果数组
22
+ result.push(matchList?.[1] || matchList?.[2]);
23
+ }
24
+ // 返回结果
25
+ return result;
26
+ };
27
+
28
+ module.exports = {
29
+ findCssImports,
30
+ };
package/src/utils/io.js CHANGED
@@ -6,6 +6,17 @@ const path = require('path');
6
6
  * @returns
7
7
  */
8
8
  const isDirEmpty = dirname => fs.promises.readdir(dirname).then(files => files.length === 0);
9
+
10
+ // 判断是否是文件
11
+ const isFile = (pathName) => {
12
+ try {
13
+ const stat = fs.lstatSync(pathName);
14
+ return stat.isFile();
15
+ } catch {
16
+ return false;
17
+ }
18
+ };
19
+
9
20
  /**
10
21
  * 确保目录存在,不存在就创建一个
11
22
  * @param {*} dirname 目录名
@@ -26,13 +37,31 @@ const copyFile = function (src, dest) {
26
37
  fs.copyFileSync(src, dest);
27
38
  };
28
39
 
40
+ // 判断文件内容是否一致,不一致再进行拷贝
41
+ function diffContentCopyFile(originFile, destFile) {
42
+ if (fs.existsSync(destFile)) {
43
+ const depDestContent = fs.readFileSync(destFile, 'utf8');
44
+ const depOriginContent = fs.readFileSync(originFile, 'utf8');
45
+ if (depDestContent !== depOriginContent) {
46
+ console.log(`拷贝${originFile}内容到${destFile}`);
47
+ copyFile(originFile, destFile);
48
+ }
49
+ } else {
50
+ console.log(`拷贝${originFile}内容到${destFile}`);
51
+ copyFile(originFile, destFile);
52
+ }
53
+ }
54
+
29
55
  // 添加后缀
30
56
  function ext(filePath, extensions) {
31
57
  let newFilePath = filePath;
58
+ let extPath = '';
59
+ // try catch需要包裹:用来处理'./lib/timer'没有后缀的情况
32
60
  try {
33
61
  const stat = fs.lstatSync(newFilePath);
34
62
  if (stat.isDirectory()) {
35
- newFilePath += (newFilePath[newFilePath.length - 1] === '/') ? 'index' : '/index';
63
+ extPath = newFilePath[newFilePath.length - 1] === '/' ? 'index' : '/index';
64
+ newFilePath += extPath;
36
65
  }
37
66
  } catch (e) {}
38
67
 
@@ -40,16 +69,24 @@ function ext(filePath, extensions) {
40
69
  const file = newFilePath.endsWith(ext) ? newFilePath : newFilePath + ext;
41
70
  if (fs.existsSync(file)) {
42
71
  return {
43
- file,
44
72
  ext,
73
+ extPath: extPath + ext,
74
+ file,
45
75
  };
46
76
  }
47
77
  }
48
- return null;
78
+ return {
79
+ ext: '',
80
+ extPath,
81
+ file: filePath,
82
+ };
49
83
  }
50
84
 
51
85
  // 判断文件是否在某个目录
52
86
  const fileInDir = (dir, file) => {
87
+ if (!fs.existsSync(dir) || !fs.existsSync(file)) {
88
+ return false;
89
+ }
53
90
  const relativePath = path.relative(dir, file);
54
91
  if (relativePath.startsWith('..')) {
55
92
  return false;
@@ -57,10 +94,13 @@ const fileInDir = (dir, file) => {
57
94
  return true;
58
95
  };
59
96
 
97
+
60
98
  module.exports = {
61
99
  isDirEmpty,
62
100
  copyFile,
101
+ diffContentCopyFile,
63
102
  ensureDirExist,
64
103
  ext,
65
104
  fileInDir,
105
+ isFile,
66
106
  };
@@ -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
+ };