@tarojs/webpack5-runner 3.5.0-alpha.0
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 +3 -0
- package/dist/dependencies/TaroSingleEntryDependency.js +18 -0
- package/dist/dependencies/TaroSingleEntryDependency.js.map +1 -0
- package/dist/index.h5.js +224 -0
- package/dist/index.h5.js.map +1 -0
- package/dist/index.mini.js +69 -0
- package/dist/index.mini.js.map +1 -0
- package/dist/loaders/miniTemplateLoader.js +63 -0
- package/dist/loaders/miniTemplateLoader.js.map +1 -0
- package/dist/plugins/BuildNativePlugin.js +124 -0
- package/dist/plugins/BuildNativePlugin.js.map +1 -0
- package/dist/plugins/H5Plugin.js +91 -0
- package/dist/plugins/H5Plugin.js.map +1 -0
- package/dist/plugins/MiniPlugin.js +1027 -0
- package/dist/plugins/MiniPlugin.js.map +1 -0
- package/dist/plugins/MiniSplitChunksPlugin.js +678 -0
- package/dist/plugins/MiniSplitChunksPlugin.js.map +1 -0
- package/dist/plugins/TaroLoadChunksPlugin.js +176 -0
- package/dist/plugins/TaroLoadChunksPlugin.js.map +1 -0
- package/dist/plugins/TaroNormalModule.js +51 -0
- package/dist/plugins/TaroNormalModule.js.map +1 -0
- package/dist/plugins/TaroNormalModulesPlugin.js +63 -0
- package/dist/plugins/TaroNormalModulesPlugin.js.map +1 -0
- package/dist/plugins/TaroSingleEntryPlugin.js +26 -0
- package/dist/plugins/TaroSingleEntryPlugin.js.map +1 -0
- package/dist/plugins/WebpackBarPlugin.js +26 -0
- package/dist/plugins/WebpackBarPlugin.js.map +1 -0
- package/dist/postcss/postcss.h5.js +70 -0
- package/dist/postcss/postcss.h5.js.map +1 -0
- package/dist/postcss/postcss.mini.js +75 -0
- package/dist/postcss/postcss.mini.js.map +1 -0
- package/dist/prebundle/bundle.js +167 -0
- package/dist/prebundle/bundle.js.map +1 -0
- package/dist/prebundle/constant.js +60 -0
- package/dist/prebundle/constant.js.map +1 -0
- package/dist/prebundle/index.js +234 -0
- package/dist/prebundle/index.js.map +1 -0
- package/dist/prebundle/scanImports.js +193 -0
- package/dist/prebundle/scanImports.js.map +1 -0
- package/dist/prebundle/utils.js +170 -0
- package/dist/prebundle/utils.js.map +1 -0
- package/dist/prebundle/webpack/TaroContainerEntryModule.js +76 -0
- package/dist/prebundle/webpack/TaroContainerEntryModule.js.map +1 -0
- package/dist/prebundle/webpack/TaroContainerPlugin.js +75 -0
- package/dist/prebundle/webpack/TaroContainerPlugin.js.map +1 -0
- package/dist/prebundle/webpack/TaroContainerReferencePlugin.js +124 -0
- package/dist/prebundle/webpack/TaroContainerReferencePlugin.js.map +1 -0
- package/dist/prebundle/webpack/index.js +1 -0
- package/dist/prebundle/webpack/index.js.map +1 -0
- package/dist/prerender/prerender.js +228 -0
- package/dist/prerender/prerender.js.map +1 -0
- package/dist/template/comp.js +4 -0
- package/dist/template/component.js +10 -0
- package/dist/template/component.js.map +1 -0
- package/dist/template/custom-wrapper.js +7 -0
- package/dist/template/custom-wrapper.js.map +1 -0
- package/dist/utils/H5AppInstance.js +110 -0
- package/dist/utils/H5AppInstance.js.map +1 -0
- package/dist/utils/index.js +53 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logHelper.js +153 -0
- package/dist/utils/logHelper.js.map +1 -0
- package/dist/utils/types.js +3 -0
- package/dist/utils/types.js.map +1 -0
- package/dist/utils/webpack.js +12 -0
- package/dist/utils/webpack.js.map +1 -0
- package/dist/webpack/BaseConfig.js +155 -0
- package/dist/webpack/BaseConfig.js.map +1 -0
- package/dist/webpack/BuildNativePlugin.js +57 -0
- package/dist/webpack/BuildNativePlugin.js.map +1 -0
- package/dist/webpack/Combination.js +69 -0
- package/dist/webpack/Combination.js.map +1 -0
- package/dist/webpack/H5BaseConfig.js +30 -0
- package/dist/webpack/H5BaseConfig.js.map +1 -0
- package/dist/webpack/H5Combination.js +106 -0
- package/dist/webpack/H5Combination.js.map +1 -0
- package/dist/webpack/H5WebpackModule.js +261 -0
- package/dist/webpack/H5WebpackModule.js.map +1 -0
- package/dist/webpack/H5WebpackPlugin.js +85 -0
- package/dist/webpack/H5WebpackPlugin.js.map +1 -0
- package/dist/webpack/MiniBaseConfig.js +73 -0
- package/dist/webpack/MiniBaseConfig.js.map +1 -0
- package/dist/webpack/MiniCombination.js +115 -0
- package/dist/webpack/MiniCombination.js.map +1 -0
- package/dist/webpack/MiniWebpackModule.js +204 -0
- package/dist/webpack/MiniWebpackModule.js.map +1 -0
- package/dist/webpack/MiniWebpackPlugin.js +154 -0
- package/dist/webpack/MiniWebpackPlugin.js.map +1 -0
- package/dist/webpack/WebpackModule.js +174 -0
- package/dist/webpack/WebpackModule.js.map +1 -0
- package/dist/webpack/WebpackPlugin.js +84 -0
- package/dist/webpack/WebpackPlugin.js.map +1 -0
- package/index.js +7 -0
- package/package.json +103 -0
|
@@ -0,0 +1,1027 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const path = require("path");
|
|
13
|
+
const fs = require("fs-extra");
|
|
14
|
+
const webpack = require("webpack");
|
|
15
|
+
const EntryDependency = require("webpack/lib/dependencies/EntryDependency");
|
|
16
|
+
const webpack_sources_1 = require("webpack-sources");
|
|
17
|
+
const loader_utils_1 = require("loader-utils");
|
|
18
|
+
const helper_1 = require("@tarojs/helper");
|
|
19
|
+
const TaroSingleEntryPlugin_1 = require("./TaroSingleEntryPlugin");
|
|
20
|
+
const TaroSingleEntryDependency_1 = require("../dependencies/TaroSingleEntryDependency");
|
|
21
|
+
const TaroNormalModulesPlugin_1 = require("./TaroNormalModulesPlugin");
|
|
22
|
+
const TaroLoadChunksPlugin_1 = require("./TaroLoadChunksPlugin");
|
|
23
|
+
const component_1 = require("../template/component");
|
|
24
|
+
const prerender_1 = require("../prerender/prerender");
|
|
25
|
+
const PLUGIN_NAME = 'TaroMiniPlugin';
|
|
26
|
+
function isLoaderExist(loaders, loaderName) {
|
|
27
|
+
return loaders.some(item => item.loader === loaderName);
|
|
28
|
+
}
|
|
29
|
+
class TaroMiniPlugin {
|
|
30
|
+
constructor(options = {}) {
|
|
31
|
+
/** app、页面、组件的配置集合 */
|
|
32
|
+
this.filesConfig = {};
|
|
33
|
+
this.isWatch = false;
|
|
34
|
+
/** 页面列表 */
|
|
35
|
+
this.pages = new Set();
|
|
36
|
+
this.components = new Set();
|
|
37
|
+
/** tabbar icon 图片路径列表 */
|
|
38
|
+
this.tabBarIcons = new Set();
|
|
39
|
+
this.dependencies = new Map();
|
|
40
|
+
this.pageLoaderName = '@tarojs/taro-loader/lib/page';
|
|
41
|
+
this.independentPackages = new Map();
|
|
42
|
+
this.options = Object.assign({
|
|
43
|
+
sourceDir: '',
|
|
44
|
+
framework: 'nerv',
|
|
45
|
+
commonChunks: ['runtime', 'vendors'],
|
|
46
|
+
isBuildPlugin: false,
|
|
47
|
+
fileType: {
|
|
48
|
+
style: '.wxss',
|
|
49
|
+
config: '.json',
|
|
50
|
+
script: '.js',
|
|
51
|
+
templ: '.wxml',
|
|
52
|
+
xs: '.wxs'
|
|
53
|
+
},
|
|
54
|
+
minifyXML: {},
|
|
55
|
+
hot: false
|
|
56
|
+
}, options);
|
|
57
|
+
const { template, baseLevel } = this.options;
|
|
58
|
+
if (template.isSupportRecursive === false && baseLevel > 0) {
|
|
59
|
+
template.baseLevel = baseLevel;
|
|
60
|
+
}
|
|
61
|
+
this.prerenderPages = new Set();
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* 自动驱动 tapAsync
|
|
65
|
+
*/
|
|
66
|
+
tryAsync(fn) {
|
|
67
|
+
return (arg, callback) => __awaiter(this, void 0, void 0, function* () {
|
|
68
|
+
try {
|
|
69
|
+
yield fn(arg);
|
|
70
|
+
callback();
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
callback(err);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* 插件入口
|
|
79
|
+
*/
|
|
80
|
+
apply(compiler) {
|
|
81
|
+
this.context = compiler.context;
|
|
82
|
+
this.appEntry = this.getAppEntry(compiler);
|
|
83
|
+
const { commonChunks, addChunkPages, framework, isBuildPlugin } = this.options;
|
|
84
|
+
/** build mode */
|
|
85
|
+
compiler.hooks.run.tapAsync(PLUGIN_NAME, this.tryAsync((compiler) => __awaiter(this, void 0, void 0, function* () {
|
|
86
|
+
yield this.run(compiler);
|
|
87
|
+
new TaroLoadChunksPlugin_1.default({
|
|
88
|
+
commonChunks: commonChunks,
|
|
89
|
+
isBuildPlugin,
|
|
90
|
+
addChunkPages: addChunkPages,
|
|
91
|
+
pages: this.pages,
|
|
92
|
+
framework: framework
|
|
93
|
+
}).apply(compiler);
|
|
94
|
+
})));
|
|
95
|
+
/** watch mode */
|
|
96
|
+
compiler.hooks.watchRun.tapAsync(PLUGIN_NAME, this.tryAsync((compiler) => __awaiter(this, void 0, void 0, function* () {
|
|
97
|
+
const changedFiles = this.getChangedFiles(compiler);
|
|
98
|
+
if ((changedFiles === null || changedFiles === void 0 ? void 0 : changedFiles.size) > 0) {
|
|
99
|
+
this.isWatch = true;
|
|
100
|
+
}
|
|
101
|
+
yield this.run(compiler);
|
|
102
|
+
if (!this.loadChunksPlugin) {
|
|
103
|
+
this.loadChunksPlugin = new TaroLoadChunksPlugin_1.default({
|
|
104
|
+
commonChunks: commonChunks,
|
|
105
|
+
isBuildPlugin,
|
|
106
|
+
addChunkPages: addChunkPages,
|
|
107
|
+
pages: this.pages,
|
|
108
|
+
framework: framework
|
|
109
|
+
});
|
|
110
|
+
this.loadChunksPlugin.apply(compiler);
|
|
111
|
+
}
|
|
112
|
+
})));
|
|
113
|
+
/** compilation.addEntry */
|
|
114
|
+
compiler.hooks.make.tapAsync(PLUGIN_NAME, this.tryAsync((compilation) => __awaiter(this, void 0, void 0, function* () {
|
|
115
|
+
var _a, _b;
|
|
116
|
+
const dependencies = this.dependencies;
|
|
117
|
+
const promises = [];
|
|
118
|
+
this.compileIndependentPages(compiler, compilation, dependencies, promises);
|
|
119
|
+
dependencies.forEach(dep => {
|
|
120
|
+
promises.push(new Promise((resolve, reject) => {
|
|
121
|
+
compilation.addEntry(this.options.sourceDir, dep, Object.assign({ name: dep.name }, dep.options), err => err ? reject(err) : resolve(null));
|
|
122
|
+
}));
|
|
123
|
+
});
|
|
124
|
+
yield Promise.all(promises);
|
|
125
|
+
yield ((_b = (_a = this.options).onCompilerMake) === null || _b === void 0 ? void 0 : _b.call(_a, compilation));
|
|
126
|
+
})));
|
|
127
|
+
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation, { normalModuleFactory }) => {
|
|
128
|
+
/** For Webpack compilation get factory from compilation.dependencyFactories by denpendence's constructor */
|
|
129
|
+
compilation.dependencyFactories.set(EntryDependency, normalModuleFactory);
|
|
130
|
+
compilation.dependencyFactories.set(TaroSingleEntryDependency_1.default, normalModuleFactory);
|
|
131
|
+
/**
|
|
132
|
+
* webpack NormalModule 在 runLoaders 真正解析资源的前一刻,
|
|
133
|
+
* 往 NormalModule.loaders 中插入对应的 Taro Loader
|
|
134
|
+
*/
|
|
135
|
+
webpack.NormalModule.getCompilationHooks(compilation).loader.tap(PLUGIN_NAME, (_loaderContext, module) => {
|
|
136
|
+
const { framework, loaderMeta, designWidth, deviceRatio } = this.options;
|
|
137
|
+
if (module.miniType === helper_1.META_TYPE.ENTRY) {
|
|
138
|
+
const loaderName = '@tarojs/taro-loader';
|
|
139
|
+
if (!isLoaderExist(module.loaders, loaderName)) {
|
|
140
|
+
module.loaders.unshift({
|
|
141
|
+
loader: loaderName,
|
|
142
|
+
options: {
|
|
143
|
+
framework,
|
|
144
|
+
loaderMeta,
|
|
145
|
+
prerender: this.prerenderPages.size > 0,
|
|
146
|
+
config: this.appConfig,
|
|
147
|
+
runtimePath: this.options.runtimePath,
|
|
148
|
+
blended: this.options.blended,
|
|
149
|
+
pxTransformConfig: {
|
|
150
|
+
designWidth: designWidth || 750,
|
|
151
|
+
deviceRatio: deviceRatio || {
|
|
152
|
+
750: 1
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
else if (module.miniType === helper_1.META_TYPE.PAGE) {
|
|
160
|
+
let isIndependent = false;
|
|
161
|
+
this.independentPackages.forEach(pages => {
|
|
162
|
+
if (pages.includes(module.resource)) {
|
|
163
|
+
isIndependent = true;
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
const loaderName = isBuildPlugin ? '@tarojs/taro-loader/lib/native-component' : (isIndependent ? '@tarojs/taro-loader/lib/independentPage' : this.pageLoaderName);
|
|
167
|
+
if (!isLoaderExist(module.loaders, loaderName)) {
|
|
168
|
+
module.loaders.unshift({
|
|
169
|
+
loader: loaderName,
|
|
170
|
+
options: {
|
|
171
|
+
framework,
|
|
172
|
+
loaderMeta,
|
|
173
|
+
name: module.name,
|
|
174
|
+
prerender: this.prerenderPages.has(module.name),
|
|
175
|
+
config: this.filesConfig,
|
|
176
|
+
appConfig: this.appConfig,
|
|
177
|
+
runtimePath: this.options.runtimePath,
|
|
178
|
+
hot: this.options.hot
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else if (module.miniType === helper_1.META_TYPE.COMPONENT) {
|
|
184
|
+
const loaderName = isBuildPlugin ? '@tarojs/taro-loader/lib/native-component' : '@tarojs/taro-loader/lib/component';
|
|
185
|
+
if (!isLoaderExist(module.loaders, loaderName)) {
|
|
186
|
+
module.loaders.unshift({
|
|
187
|
+
loader: loaderName,
|
|
188
|
+
options: {
|
|
189
|
+
framework,
|
|
190
|
+
loaderMeta,
|
|
191
|
+
name: module.name,
|
|
192
|
+
prerender: this.prerenderPages.has(module.name),
|
|
193
|
+
runtimePath: this.options.runtimePath
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
compilation.hooks.processAssets.tapAsync({
|
|
200
|
+
name: PLUGIN_NAME,
|
|
201
|
+
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL
|
|
202
|
+
}, this.tryAsync(() => __awaiter(this, void 0, void 0, function* () {
|
|
203
|
+
yield this.generateMiniFiles(compilation);
|
|
204
|
+
})));
|
|
205
|
+
});
|
|
206
|
+
compiler.hooks.afterEmit.tapAsync(PLUGIN_NAME, this.tryAsync((compilation) => __awaiter(this, void 0, void 0, function* () {
|
|
207
|
+
yield this.addTarBarFilesToDependencies(compilation);
|
|
208
|
+
})));
|
|
209
|
+
new TaroNormalModulesPlugin_1.default(this.options.onParseCreateElement).apply(compiler);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* 根据 webpack entry 配置获取入口文件路径
|
|
213
|
+
* @returns app 入口文件路径
|
|
214
|
+
*/
|
|
215
|
+
getAppEntry(compiler) {
|
|
216
|
+
// const originalEntry = compiler.options.entry as webpack.Entry
|
|
217
|
+
// compiler.options.entry = {}
|
|
218
|
+
// return path.resolve(this.context, originalEntry.app[0])
|
|
219
|
+
const { entry } = compiler.options;
|
|
220
|
+
if (this.options.isBuildPlugin) {
|
|
221
|
+
const entryCopy = Object.assign({}, entry);
|
|
222
|
+
compiler.options.entry = {};
|
|
223
|
+
return entryCopy;
|
|
224
|
+
}
|
|
225
|
+
if (this.options.appEntry) {
|
|
226
|
+
compiler.options.entry = {};
|
|
227
|
+
return this.options.appEntry;
|
|
228
|
+
}
|
|
229
|
+
function getEntryPath(entry) {
|
|
230
|
+
const app = entry.app;
|
|
231
|
+
if (Array.isArray(app)) {
|
|
232
|
+
return app[0];
|
|
233
|
+
}
|
|
234
|
+
else if (Array.isArray(app.import)) {
|
|
235
|
+
return app.import[0];
|
|
236
|
+
}
|
|
237
|
+
return app;
|
|
238
|
+
}
|
|
239
|
+
const appEntryPath = getEntryPath(entry);
|
|
240
|
+
compiler.options.entry = {};
|
|
241
|
+
return appEntryPath;
|
|
242
|
+
}
|
|
243
|
+
getChangedFiles(compiler) {
|
|
244
|
+
return compiler.modifiedFiles;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* 分析 app 入口文件,搜集页面、组件信息,
|
|
248
|
+
* 往 this.dependencies 中添加资源模块
|
|
249
|
+
*/
|
|
250
|
+
run(compiler) {
|
|
251
|
+
if (this.options.isBuildPlugin) {
|
|
252
|
+
this.getPluginFiles();
|
|
253
|
+
this.getConfigFiles(compiler);
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
this.appConfig = this.getAppConfig();
|
|
257
|
+
this.getPages();
|
|
258
|
+
this.getPagesConfig();
|
|
259
|
+
this.getDarkMode();
|
|
260
|
+
this.getConfigFiles(compiler);
|
|
261
|
+
this.addEntries();
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
getPluginFiles() {
|
|
265
|
+
const fileList = new Set();
|
|
266
|
+
const { pluginConfig, template } = this.options;
|
|
267
|
+
const normalFiles = new Set();
|
|
268
|
+
Object.keys(this.appEntry).forEach(key => {
|
|
269
|
+
const filePath = this.appEntry[key][0] || this.appEntry[key].import[0];
|
|
270
|
+
if (key === this.options.pluginMainEntry) {
|
|
271
|
+
this.addEntry(filePath, key, helper_1.META_TYPE.EXPORTS);
|
|
272
|
+
}
|
|
273
|
+
if (pluginConfig) {
|
|
274
|
+
fileList.add({
|
|
275
|
+
name: key,
|
|
276
|
+
path: filePath,
|
|
277
|
+
isNative: false
|
|
278
|
+
});
|
|
279
|
+
let isPage = false;
|
|
280
|
+
let isComponent = false;
|
|
281
|
+
Object.keys(pluginConfig).forEach(pluginKey => {
|
|
282
|
+
if (pluginKey === 'pages') {
|
|
283
|
+
Object.keys(pluginConfig[pluginKey]).forEach(pageKey => {
|
|
284
|
+
if (`plugin/${pluginConfig[pluginKey][pageKey]}` === key) {
|
|
285
|
+
isPage = true;
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
if (pluginKey === 'publicComponents') {
|
|
290
|
+
Object.keys(pluginConfig[pluginKey]).forEach(pageKey => {
|
|
291
|
+
if (`plugin/${pluginConfig[pluginKey][pageKey]}` === key) {
|
|
292
|
+
isComponent = true;
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
if (isPage) {
|
|
298
|
+
this.pages.add({
|
|
299
|
+
name: key,
|
|
300
|
+
path: filePath,
|
|
301
|
+
isNative: false
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
else if (isComponent) {
|
|
305
|
+
this.components.add({
|
|
306
|
+
name: key,
|
|
307
|
+
path: filePath,
|
|
308
|
+
isNative: false
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
normalFiles.add({
|
|
313
|
+
name: key,
|
|
314
|
+
path: filePath,
|
|
315
|
+
isNative: true
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
if (!template.isSupportRecursive) {
|
|
321
|
+
this.addEntry(path.resolve(__dirname, '..', 'template/comp'), this.getIsBuildPluginPath('comp', true), helper_1.META_TYPE.STATIC);
|
|
322
|
+
}
|
|
323
|
+
this.addEntry(path.resolve(__dirname, '..', 'template/custom-wrapper'), this.getIsBuildPluginPath('custom-wrapper', true), helper_1.META_TYPE.STATIC);
|
|
324
|
+
normalFiles.forEach(item => {
|
|
325
|
+
this.addEntry(item.path, item.name, helper_1.META_TYPE.NORMAL, {
|
|
326
|
+
library: {
|
|
327
|
+
type: 'commonjs'
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
this.pages.forEach(item => {
|
|
332
|
+
var _a;
|
|
333
|
+
if (!this.isWatch && ((_a = this.options.logger) === null || _a === void 0 ? void 0 : _a.quiet) === false) {
|
|
334
|
+
helper_1.printLog("compile" /* COMPILE */, '发现页面', this.getShowPath(item.path));
|
|
335
|
+
}
|
|
336
|
+
this.compileFile(item);
|
|
337
|
+
if (item.isNative) {
|
|
338
|
+
this.addEntry(item.path, item.name, helper_1.META_TYPE.NORMAL);
|
|
339
|
+
if (item.stylePath && fs.existsSync(item.stylePath)) {
|
|
340
|
+
this.addEntry(item.stylePath, this.getStylePath(item.name), helper_1.META_TYPE.NORMAL);
|
|
341
|
+
}
|
|
342
|
+
if (item.templatePath && fs.existsSync(item.templatePath)) {
|
|
343
|
+
this.addEntry(item.templatePath, this.getTemplatePath(item.name), helper_1.META_TYPE.NORMAL);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
this.addEntry(item.path, item.name, helper_1.META_TYPE.PAGE);
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
this.components.forEach(item => {
|
|
351
|
+
this.compileFile(item);
|
|
352
|
+
if (item.isNative) {
|
|
353
|
+
this.addEntry(item.path, item.name, helper_1.META_TYPE.NORMAL);
|
|
354
|
+
if (item.stylePath && fs.existsSync(item.stylePath)) {
|
|
355
|
+
this.addEntry(item.stylePath, this.getStylePath(item.name), helper_1.META_TYPE.NORMAL);
|
|
356
|
+
}
|
|
357
|
+
if (item.templatePath && fs.existsSync(item.templatePath)) {
|
|
358
|
+
this.addEntry(item.templatePath, this.getTemplatePath(item.name), helper_1.META_TYPE.NORMAL);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
this.addEntry(item.path, item.name, helper_1.META_TYPE.COMPONENT);
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
modifyPluginJSON(pluginJSON) {
|
|
367
|
+
const { main, publicComponents } = pluginJSON;
|
|
368
|
+
if (main) {
|
|
369
|
+
pluginJSON.main = this.getTargetFilePath(main, '.js');
|
|
370
|
+
}
|
|
371
|
+
if (publicComponents) {
|
|
372
|
+
pluginJSON.publicComponents = Object.assign({}, publicComponents, {
|
|
373
|
+
'custom-wrapper': 'custom-wrapper'
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* 获取 app config 配置内容
|
|
379
|
+
* @returns app config 配置内容
|
|
380
|
+
*/
|
|
381
|
+
getAppConfig() {
|
|
382
|
+
const appName = path.basename(this.appEntry).replace(path.extname(this.appEntry), '');
|
|
383
|
+
this.compileFile({
|
|
384
|
+
name: appName,
|
|
385
|
+
path: this.appEntry,
|
|
386
|
+
isNative: false
|
|
387
|
+
});
|
|
388
|
+
const fileConfig = this.filesConfig[this.getConfigFilePath(appName)];
|
|
389
|
+
const appConfig = fileConfig ? fileConfig.content || {} : {};
|
|
390
|
+
if (helper_1.isEmptyObject(appConfig)) {
|
|
391
|
+
throw new Error('缺少 app 全局配置文件,请检查!');
|
|
392
|
+
}
|
|
393
|
+
return appConfig;
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* 根据 app config 的 pages 配置项,收集所有页面信息,
|
|
397
|
+
* 包括处理分包和 tabbar
|
|
398
|
+
*/
|
|
399
|
+
getPages() {
|
|
400
|
+
var _a;
|
|
401
|
+
if (helper_1.isEmptyObject(this.appConfig)) {
|
|
402
|
+
throw new Error('缺少 app 全局配置文件,请检查!');
|
|
403
|
+
}
|
|
404
|
+
const appPages = this.appConfig.pages;
|
|
405
|
+
if (!appPages || !appPages.length) {
|
|
406
|
+
throw new Error('全局配置缺少 pages 字段,请检查!');
|
|
407
|
+
}
|
|
408
|
+
if (!this.isWatch && ((_a = this.options.logger) === null || _a === void 0 ? void 0 : _a.quiet) === false) {
|
|
409
|
+
helper_1.printLog("compile" /* COMPILE */, '发现入口', this.getShowPath(this.appEntry));
|
|
410
|
+
}
|
|
411
|
+
const { framework, prerender } = this.options;
|
|
412
|
+
this.prerenderPages = new Set(prerender_1.validatePrerenderPages(appPages, prerender).map(p => p.path));
|
|
413
|
+
this.getTabBarFiles(this.appConfig);
|
|
414
|
+
this.pages = new Set([
|
|
415
|
+
...appPages.map(item => {
|
|
416
|
+
const pagePath = helper_1.resolveMainFilePath(path.join(this.options.sourceDir, item), helper_1.FRAMEWORK_EXT_MAP[framework]);
|
|
417
|
+
const pageTemplatePath = this.getTemplatePath(pagePath);
|
|
418
|
+
const isNative = this.isNativePageORComponent(pageTemplatePath);
|
|
419
|
+
return {
|
|
420
|
+
name: item,
|
|
421
|
+
path: pagePath,
|
|
422
|
+
isNative,
|
|
423
|
+
stylePath: isNative ? this.getStylePath(pagePath) : undefined,
|
|
424
|
+
templatePath: isNative ? this.getTemplatePath(pagePath) : undefined
|
|
425
|
+
};
|
|
426
|
+
})
|
|
427
|
+
]);
|
|
428
|
+
this.getSubPackages(this.appConfig);
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* 读取页面及其依赖的组件的配置
|
|
432
|
+
*/
|
|
433
|
+
getPagesConfig() {
|
|
434
|
+
this.pages.forEach(page => {
|
|
435
|
+
var _a;
|
|
436
|
+
if (!this.isWatch && ((_a = this.options.logger) === null || _a === void 0 ? void 0 : _a.quiet) === false) {
|
|
437
|
+
helper_1.printLog("compile" /* COMPILE */, '发现页面', this.getShowPath(page.path));
|
|
438
|
+
}
|
|
439
|
+
this.compileFile(page);
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* 往 this.dependencies 中新增或修改所有 config 配置模块
|
|
444
|
+
*/
|
|
445
|
+
getConfigFiles(compiler) {
|
|
446
|
+
const filesConfig = this.filesConfig;
|
|
447
|
+
Object.keys(filesConfig).forEach(item => {
|
|
448
|
+
if (fs.existsSync(filesConfig[item].path)) {
|
|
449
|
+
this.addEntry(filesConfig[item].path, item, helper_1.META_TYPE.CONFIG);
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
// webpack createChunkAssets 前一刻,去除所有 config chunks
|
|
453
|
+
compiler.hooks.compilation.tap(PLUGIN_NAME, compilation => {
|
|
454
|
+
compilation.hooks.beforeChunkAssets.tap(PLUGIN_NAME, () => {
|
|
455
|
+
const chunks = compilation.chunks;
|
|
456
|
+
const configNames = Object.keys(filesConfig);
|
|
457
|
+
for (const chunk of chunks) {
|
|
458
|
+
if (configNames.find(configName => configName === chunk.name))
|
|
459
|
+
chunks.delete(chunk);
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* 在 this.dependencies 中新增或修改模块
|
|
466
|
+
*/
|
|
467
|
+
addEntry(entryPath, entryName, entryType, options = {}) {
|
|
468
|
+
let dep;
|
|
469
|
+
if (this.dependencies.has(entryPath)) {
|
|
470
|
+
dep = this.dependencies.get(entryPath);
|
|
471
|
+
dep.name = entryName;
|
|
472
|
+
dep.loc = { name: entryName };
|
|
473
|
+
dep.request = entryPath;
|
|
474
|
+
dep.userRequest = entryPath;
|
|
475
|
+
dep.miniType = entryType;
|
|
476
|
+
dep.options = options;
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
dep = new TaroSingleEntryDependency_1.default(entryPath, entryName, { name: entryName }, entryType, options);
|
|
480
|
+
}
|
|
481
|
+
this.dependencies.set(entryPath, dep);
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* 在 this.dependencies 中新增或修改 app、模板组件、页面、组件等资源模块
|
|
485
|
+
*/
|
|
486
|
+
addEntries() {
|
|
487
|
+
const { template } = this.options;
|
|
488
|
+
this.addEntry(this.appEntry, 'app', helper_1.META_TYPE.ENTRY);
|
|
489
|
+
if (!template.isSupportRecursive) {
|
|
490
|
+
this.addEntry(path.resolve(__dirname, '..', 'template/comp'), 'comp', helper_1.META_TYPE.STATIC);
|
|
491
|
+
}
|
|
492
|
+
this.addEntry(path.resolve(__dirname, '..', 'template/custom-wrapper'), 'custom-wrapper', helper_1.META_TYPE.STATIC);
|
|
493
|
+
this.pages.forEach(item => {
|
|
494
|
+
if (item.isNative) {
|
|
495
|
+
this.addEntry(item.path, item.name, helper_1.META_TYPE.NORMAL);
|
|
496
|
+
if (item.stylePath && fs.existsSync(item.stylePath)) {
|
|
497
|
+
this.addEntry(item.stylePath, this.getStylePath(item.name), helper_1.META_TYPE.NORMAL);
|
|
498
|
+
}
|
|
499
|
+
if (item.templatePath && fs.existsSync(item.templatePath)) {
|
|
500
|
+
this.addEntry(item.templatePath, this.getTemplatePath(item.name), helper_1.META_TYPE.NORMAL);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
this.addEntry(item.path, item.name, helper_1.META_TYPE.PAGE);
|
|
505
|
+
}
|
|
506
|
+
});
|
|
507
|
+
this.components.forEach(item => {
|
|
508
|
+
if (item.isNative) {
|
|
509
|
+
this.addEntry(item.path, item.name, helper_1.META_TYPE.NORMAL);
|
|
510
|
+
if (item.stylePath && fs.existsSync(item.stylePath)) {
|
|
511
|
+
this.addEntry(item.stylePath, this.getStylePath(item.name), helper_1.META_TYPE.NORMAL);
|
|
512
|
+
}
|
|
513
|
+
if (item.templatePath && fs.existsSync(item.templatePath)) {
|
|
514
|
+
this.addEntry(item.templatePath, this.getTemplatePath(item.name), helper_1.META_TYPE.NORMAL);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
else {
|
|
518
|
+
this.addEntry(item.path, item.name, helper_1.META_TYPE.COMPONENT);
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
replaceExt(file, ext) {
|
|
523
|
+
return path.join(path.dirname(file), path.basename(file, path.extname(file)) + `${ext}`);
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* 读取页面、组件的配置,并递归读取依赖的组件的配置
|
|
527
|
+
*/
|
|
528
|
+
compileFile(file) {
|
|
529
|
+
const filePath = file.path;
|
|
530
|
+
const fileConfigPath = file.isNative ? this.replaceExt(filePath, '.json') : this.getConfigFilePath(filePath);
|
|
531
|
+
const fileConfig = helper_1.readConfig(fileConfigPath);
|
|
532
|
+
const usingComponents = fileConfig.usingComponents;
|
|
533
|
+
// 递归收集依赖的第三方组件
|
|
534
|
+
if (usingComponents) {
|
|
535
|
+
const componentNames = Object.keys(usingComponents);
|
|
536
|
+
const depComponents = [];
|
|
537
|
+
const alias = this.options.alias;
|
|
538
|
+
for (const compName of componentNames) {
|
|
539
|
+
let compPath = usingComponents[compName];
|
|
540
|
+
if (helper_1.isAliasPath(compPath, alias)) {
|
|
541
|
+
compPath = helper_1.replaceAliasPath(filePath, compPath, alias);
|
|
542
|
+
fileConfig.usingComponents[compName] = compPath;
|
|
543
|
+
}
|
|
544
|
+
depComponents.push({
|
|
545
|
+
name: compName,
|
|
546
|
+
path: compPath
|
|
547
|
+
});
|
|
548
|
+
if (!component_1.componentConfig.thirdPartyComponents.has(compName) && !file.isNative) {
|
|
549
|
+
component_1.componentConfig.thirdPartyComponents.set(compName, new Set());
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
depComponents.forEach(item => {
|
|
553
|
+
const componentPath = helper_1.resolveMainFilePath(path.resolve(path.dirname(file.path), item.path));
|
|
554
|
+
if (fs.existsSync(componentPath) && !Array.from(this.components).some(item => item.path === componentPath)) {
|
|
555
|
+
const componentName = this.getComponentName(componentPath);
|
|
556
|
+
const componentTempPath = this.getTemplatePath(componentPath);
|
|
557
|
+
const isNative = this.isNativePageORComponent(componentTempPath);
|
|
558
|
+
const componentObj = {
|
|
559
|
+
name: componentName,
|
|
560
|
+
path: componentPath,
|
|
561
|
+
isNative,
|
|
562
|
+
stylePath: isNative ? this.getStylePath(componentPath) : undefined,
|
|
563
|
+
templatePath: isNative ? this.getTemplatePath(componentPath) : undefined
|
|
564
|
+
};
|
|
565
|
+
this.components.add(componentObj);
|
|
566
|
+
this.compileFile(componentObj);
|
|
567
|
+
}
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
this.filesConfig[this.getConfigFilePath(file.name)] = {
|
|
571
|
+
content: fileConfig,
|
|
572
|
+
path: fileConfigPath
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* 收集分包配置中的页面
|
|
577
|
+
*/
|
|
578
|
+
getSubPackages(appConfig) {
|
|
579
|
+
const subPackages = appConfig.subPackages || appConfig.subpackages;
|
|
580
|
+
const { framework } = this.options;
|
|
581
|
+
if (subPackages && subPackages.length) {
|
|
582
|
+
subPackages.forEach(item => {
|
|
583
|
+
if (item.pages && item.pages.length) {
|
|
584
|
+
const root = item.root;
|
|
585
|
+
const isIndependent = !!item.independent;
|
|
586
|
+
if (isIndependent) {
|
|
587
|
+
this.independentPackages.set(root, []);
|
|
588
|
+
}
|
|
589
|
+
item.pages.forEach(page => {
|
|
590
|
+
let pageItem = `${root}/${page}`;
|
|
591
|
+
pageItem = pageItem.replace(/\/{2,}/g, '/');
|
|
592
|
+
let hasPageIn = false;
|
|
593
|
+
this.pages.forEach(({ name }) => {
|
|
594
|
+
if (name === pageItem) {
|
|
595
|
+
hasPageIn = true;
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
if (!hasPageIn) {
|
|
599
|
+
const pagePath = helper_1.resolveMainFilePath(path.join(this.options.sourceDir, pageItem), helper_1.FRAMEWORK_EXT_MAP[framework]);
|
|
600
|
+
const templatePath = this.getTemplatePath(pagePath);
|
|
601
|
+
const isNative = this.isNativePageORComponent(templatePath);
|
|
602
|
+
if (isIndependent) {
|
|
603
|
+
const independentPages = this.independentPackages.get(root);
|
|
604
|
+
independentPages === null || independentPages === void 0 ? void 0 : independentPages.push(pagePath);
|
|
605
|
+
}
|
|
606
|
+
this.pages.add({
|
|
607
|
+
name: pageItem,
|
|
608
|
+
path: pagePath,
|
|
609
|
+
isNative,
|
|
610
|
+
stylePath: isNative ? this.getStylePath(pagePath) : undefined,
|
|
611
|
+
templatePath: isNative ? this.getTemplatePath(pagePath) : undefined
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* 收集 dark mode 配置中的文件
|
|
621
|
+
*/
|
|
622
|
+
getDarkMode() {
|
|
623
|
+
const themeLocation = this.appConfig.themeLocation;
|
|
624
|
+
const darkMode = this.appConfig.darkmode;
|
|
625
|
+
if (darkMode && themeLocation && typeof themeLocation === 'string') {
|
|
626
|
+
this.themeLocation = themeLocation;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
compileIndependentPages(compiler, compilation, dependencies, promises) {
|
|
630
|
+
const independentPackages = this.independentPackages;
|
|
631
|
+
if (independentPackages.size) {
|
|
632
|
+
const JsonpTemplatePlugin = require('webpack/lib/web/JsonpTemplatePlugin');
|
|
633
|
+
const NaturalChunkIdsPlugin = require('webpack/lib/ids/NaturalChunkIdsPlugin');
|
|
634
|
+
const SplitChunksPlugin = require('webpack/lib/optimize/SplitChunksPlugin');
|
|
635
|
+
const RuntimeChunkPlugin = require('webpack/lib/optimize/RuntimeChunkPlugin');
|
|
636
|
+
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
637
|
+
independentPackages.forEach((pages, name) => {
|
|
638
|
+
const childCompiler = compilation.createChildCompiler(PLUGIN_NAME, {
|
|
639
|
+
path: `${compiler.options.output.path}/${name}`,
|
|
640
|
+
chunkLoadingGlobal: `subpackage_${name}`
|
|
641
|
+
});
|
|
642
|
+
const compPath = path.resolve(__dirname, '..', 'template/comp');
|
|
643
|
+
childCompiler.inputFileSystem = compiler.inputFileSystem;
|
|
644
|
+
childCompiler.outputFileSystem = compiler.outputFileSystem;
|
|
645
|
+
childCompiler.context = compiler.context;
|
|
646
|
+
new JsonpTemplatePlugin().apply(childCompiler);
|
|
647
|
+
new NaturalChunkIdsPlugin().apply(childCompiler);
|
|
648
|
+
new MiniCssExtractPlugin({
|
|
649
|
+
filename: `[name]${this.options.fileType.style}`,
|
|
650
|
+
chunkFilename: `[name]${this.options.fileType.style}`
|
|
651
|
+
}).apply(childCompiler);
|
|
652
|
+
new webpack.DefinePlugin(this.options.constantsReplaceList).apply(childCompiler);
|
|
653
|
+
if (compiler.options.optimization) {
|
|
654
|
+
new SplitChunksPlugin({
|
|
655
|
+
chunks: 'all',
|
|
656
|
+
maxInitialRequests: Infinity,
|
|
657
|
+
minSize: 0,
|
|
658
|
+
cacheGroups: {
|
|
659
|
+
vendors: {
|
|
660
|
+
name: `${name}/vendors`,
|
|
661
|
+
minChunks: 1,
|
|
662
|
+
test: module => {
|
|
663
|
+
return (/[\\/]node_modules[\\/]/.test(module.resource) && module.resource.indexOf(compPath) < 0);
|
|
664
|
+
},
|
|
665
|
+
priority: 10
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
}).apply(childCompiler);
|
|
669
|
+
new RuntimeChunkPlugin({
|
|
670
|
+
name: `${name}/runtime`
|
|
671
|
+
}).apply(childCompiler);
|
|
672
|
+
}
|
|
673
|
+
const childPages = new Set();
|
|
674
|
+
pages.forEach(pagePath => {
|
|
675
|
+
if (dependencies.has(pagePath)) {
|
|
676
|
+
const dep = dependencies.get(pagePath);
|
|
677
|
+
new TaroSingleEntryPlugin_1.default(compiler.context, dep === null || dep === void 0 ? void 0 : dep.request, dep === null || dep === void 0 ? void 0 : dep.name, dep === null || dep === void 0 ? void 0 : dep.miniType).apply(childCompiler);
|
|
678
|
+
}
|
|
679
|
+
this.pages.forEach(item => {
|
|
680
|
+
if (item.path === pagePath) {
|
|
681
|
+
childPages.add(item);
|
|
682
|
+
}
|
|
683
|
+
});
|
|
684
|
+
dependencies.delete(pagePath);
|
|
685
|
+
});
|
|
686
|
+
new TaroLoadChunksPlugin_1.default({
|
|
687
|
+
commonChunks: [`${name}/runtime`, `${name}/vendors`],
|
|
688
|
+
isBuildPlugin: false,
|
|
689
|
+
addChunkPages: this.options.addChunkPages,
|
|
690
|
+
pages: childPages,
|
|
691
|
+
framework: this.options.framework,
|
|
692
|
+
needAddCommon: [`${name}/comp`]
|
|
693
|
+
}).apply(childCompiler);
|
|
694
|
+
// 添加 comp 和 custom-wrapper 组件
|
|
695
|
+
new TaroSingleEntryPlugin_1.default(compiler.context, path.resolve(__dirname, '..', 'template/comp'), `${name}/comp`, helper_1.META_TYPE.STATIC).apply(childCompiler);
|
|
696
|
+
new TaroSingleEntryPlugin_1.default(compiler.context, path.resolve(__dirname, '..', 'template/custom-wrapper'), `${name}/custom-wrapper`, helper_1.META_TYPE.STATIC).apply(childCompiler);
|
|
697
|
+
promises.push(new Promise((resolve, reject) => {
|
|
698
|
+
childCompiler.runAsChild(err => {
|
|
699
|
+
if (err) {
|
|
700
|
+
return reject(err);
|
|
701
|
+
}
|
|
702
|
+
resolve(null);
|
|
703
|
+
});
|
|
704
|
+
}).catch(err => console.log(err)));
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* 搜集 tabbar icon 图标路径
|
|
710
|
+
* 收集自定义 tabbar 组件
|
|
711
|
+
*/
|
|
712
|
+
getTabBarFiles(appConfig) {
|
|
713
|
+
var _a;
|
|
714
|
+
const tabBar = appConfig.tabBar;
|
|
715
|
+
const { sourceDir, framework } = this.options;
|
|
716
|
+
if (tabBar && typeof tabBar === 'object' && !helper_1.isEmptyObject(tabBar)) {
|
|
717
|
+
// eslint-disable-next-line dot-notation
|
|
718
|
+
const list = tabBar['list'] || [];
|
|
719
|
+
list.forEach(item => {
|
|
720
|
+
// eslint-disable-next-line dot-notation
|
|
721
|
+
item['iconPath'] && this.tabBarIcons.add(item['iconPath']);
|
|
722
|
+
// eslint-disable-next-line dot-notation
|
|
723
|
+
item['selectedIconPath'] && this.tabBarIcons.add(item['selectedIconPath']);
|
|
724
|
+
});
|
|
725
|
+
if (tabBar.custom) {
|
|
726
|
+
const customTabBarPath = path.join(sourceDir, 'custom-tab-bar');
|
|
727
|
+
const customTabBarComponentPath = helper_1.resolveMainFilePath(customTabBarPath, [...helper_1.FRAMEWORK_EXT_MAP[framework], ...helper_1.SCRIPT_EXT]);
|
|
728
|
+
if (fs.existsSync(customTabBarComponentPath)) {
|
|
729
|
+
const customTabBarComponentTemplPath = this.getTemplatePath(customTabBarComponentPath);
|
|
730
|
+
const isNative = this.isNativePageORComponent(customTabBarComponentTemplPath);
|
|
731
|
+
if (!this.isWatch && ((_a = this.options.logger) === null || _a === void 0 ? void 0 : _a.quiet) === false) {
|
|
732
|
+
helper_1.printLog("compile" /* COMPILE */, '自定义 tabBar', this.getShowPath(customTabBarComponentPath));
|
|
733
|
+
}
|
|
734
|
+
const componentObj = {
|
|
735
|
+
name: 'custom-tab-bar/index',
|
|
736
|
+
path: customTabBarComponentPath,
|
|
737
|
+
isNative,
|
|
738
|
+
stylePath: isNative ? this.getStylePath(customTabBarComponentPath) : undefined,
|
|
739
|
+
templatePath: isNative ? this.getTemplatePath(customTabBarComponentPath) : undefined
|
|
740
|
+
};
|
|
741
|
+
this.compileFile(componentObj);
|
|
742
|
+
this.components.add(componentObj);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
/** 是否为小程序原生页面或组件 */
|
|
748
|
+
isNativePageORComponent(templatePath) {
|
|
749
|
+
return fs.existsSync(templatePath);
|
|
750
|
+
}
|
|
751
|
+
getShowPath(filePath) {
|
|
752
|
+
return filePath.replace(this.context, '').replace(/\\/g, '/').replace(/^\//, '');
|
|
753
|
+
}
|
|
754
|
+
/** 生成小程序相关文件 */
|
|
755
|
+
generateMiniFiles(compilation) {
|
|
756
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
757
|
+
const { template, modifyBuildAssets, modifyMiniConfigs, isBuildPlugin, sourceDir } = this.options;
|
|
758
|
+
const baseTemplateName = this.getIsBuildPluginPath('base', isBuildPlugin);
|
|
759
|
+
const baseCompName = 'comp';
|
|
760
|
+
const customWrapperName = 'custom-wrapper';
|
|
761
|
+
/**
|
|
762
|
+
* 与原生小程序混写时解析模板与样式
|
|
763
|
+
*/
|
|
764
|
+
compilation.getAssets().forEach(({ name: assetPath }) => {
|
|
765
|
+
const styleExt = this.options.fileType.style;
|
|
766
|
+
const templExt = this.options.fileType.templ;
|
|
767
|
+
if (new RegExp(`(\\${styleExt}|\\${templExt})\\.js(\\.map){0,1}$`).test(assetPath)) {
|
|
768
|
+
delete compilation.assets[assetPath];
|
|
769
|
+
}
|
|
770
|
+
else if (new RegExp(`${styleExt}${styleExt}$`).test(assetPath)) {
|
|
771
|
+
const assetObj = compilation.assets[assetPath];
|
|
772
|
+
const newAssetPath = assetPath.replace(styleExt, '');
|
|
773
|
+
compilation.assets[newAssetPath] = assetObj;
|
|
774
|
+
delete compilation.assets[assetPath];
|
|
775
|
+
}
|
|
776
|
+
});
|
|
777
|
+
if (typeof modifyMiniConfigs === 'function') {
|
|
778
|
+
yield modifyMiniConfigs(this.filesConfig);
|
|
779
|
+
}
|
|
780
|
+
if (!this.options.blended && !isBuildPlugin) {
|
|
781
|
+
const appConfigPath = this.getConfigFilePath(this.appEntry);
|
|
782
|
+
const appConfigName = path.basename(appConfigPath).replace(path.extname(appConfigPath), '');
|
|
783
|
+
this.generateConfigFile(compilation, this.appEntry, this.filesConfig[appConfigName].content);
|
|
784
|
+
}
|
|
785
|
+
if (!template.isSupportRecursive) {
|
|
786
|
+
// 如微信、QQ 不支持递归模版的小程序,需要使用自定义组件协助递归
|
|
787
|
+
this.generateTemplateFile(compilation, this.getIsBuildPluginPath(baseCompName, isBuildPlugin), template.buildBaseComponentTemplate, this.options.fileType.templ);
|
|
788
|
+
this.generateConfigFile(compilation, this.getIsBuildPluginPath(baseCompName, isBuildPlugin), {
|
|
789
|
+
component: true,
|
|
790
|
+
usingComponents: {
|
|
791
|
+
[baseCompName]: `./${baseCompName}`,
|
|
792
|
+
[customWrapperName]: `./${customWrapperName}`
|
|
793
|
+
}
|
|
794
|
+
});
|
|
795
|
+
this.generateConfigFile(compilation, this.getIsBuildPluginPath(customWrapperName, isBuildPlugin), {
|
|
796
|
+
component: true,
|
|
797
|
+
usingComponents: {
|
|
798
|
+
[baseCompName]: `./${baseCompName}`,
|
|
799
|
+
[customWrapperName]: `./${customWrapperName}`
|
|
800
|
+
}
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
else {
|
|
804
|
+
this.generateConfigFile(compilation, this.getIsBuildPluginPath(customWrapperName, isBuildPlugin), {
|
|
805
|
+
component: true,
|
|
806
|
+
usingComponents: {
|
|
807
|
+
[customWrapperName]: `./${customWrapperName}`
|
|
808
|
+
}
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
this.generateTemplateFile(compilation, baseTemplateName, template.buildTemplate, component_1.componentConfig);
|
|
812
|
+
this.generateTemplateFile(compilation, this.getIsBuildPluginPath(customWrapperName, isBuildPlugin), template.buildCustomComponentTemplate, this.options.fileType.templ);
|
|
813
|
+
this.generateXSFile(compilation, 'utils', isBuildPlugin);
|
|
814
|
+
// 为独立分包生成 base/comp/custom-wrapper
|
|
815
|
+
this.independentPackages.forEach((_pages, name) => {
|
|
816
|
+
this.generateTemplateFile(compilation, `${name}/${baseTemplateName}`, template.buildTemplate, component_1.componentConfig);
|
|
817
|
+
if (!template.isSupportRecursive) {
|
|
818
|
+
// 如微信、QQ 不支持递归模版的小程序,需要使用自定义组件协助递归
|
|
819
|
+
this.generateConfigFile(compilation, `${name}/${baseCompName}`, {
|
|
820
|
+
component: true,
|
|
821
|
+
usingComponents: {
|
|
822
|
+
[baseCompName]: `./${baseCompName}`,
|
|
823
|
+
[customWrapperName]: `./${customWrapperName}`
|
|
824
|
+
}
|
|
825
|
+
});
|
|
826
|
+
this.generateConfigFile(compilation, `${name}/${customWrapperName}`, {
|
|
827
|
+
component: true,
|
|
828
|
+
usingComponents: {
|
|
829
|
+
[baseCompName]: `./${baseCompName}`,
|
|
830
|
+
[customWrapperName]: `./${customWrapperName}`
|
|
831
|
+
}
|
|
832
|
+
});
|
|
833
|
+
this.generateTemplateFile(compilation, `${name}/${baseCompName}`, template.buildBaseComponentTemplate, this.options.fileType.templ);
|
|
834
|
+
}
|
|
835
|
+
this.generateTemplateFile(compilation, `${name}/${customWrapperName}`, template.buildCustomComponentTemplate, this.options.fileType.templ);
|
|
836
|
+
this.generateXSFile(compilation, `${name}/utils`, isBuildPlugin);
|
|
837
|
+
});
|
|
838
|
+
this.components.forEach(component => {
|
|
839
|
+
const importBaseTemplatePath = helper_1.promoteRelativePath(path.relative(component.path, path.join(sourceDir, this.getTemplatePath(baseTemplateName))));
|
|
840
|
+
const config = this.filesConfig[this.getConfigFilePath(component.name)];
|
|
841
|
+
if (config) {
|
|
842
|
+
this.generateConfigFile(compilation, component.path, config.content);
|
|
843
|
+
}
|
|
844
|
+
if (!component.isNative) {
|
|
845
|
+
this.generateTemplateFile(compilation, component.path, template.buildPageTemplate, importBaseTemplatePath);
|
|
846
|
+
}
|
|
847
|
+
});
|
|
848
|
+
this.pages.forEach(page => {
|
|
849
|
+
let importBaseTemplatePath = helper_1.promoteRelativePath(path.relative(page.path, path.join(sourceDir, this.getTemplatePath(baseTemplateName))));
|
|
850
|
+
const config = this.filesConfig[this.getConfigFilePath(page.name)];
|
|
851
|
+
let isIndependent = false;
|
|
852
|
+
let independentName = '';
|
|
853
|
+
this.independentPackages.forEach((pages, name) => {
|
|
854
|
+
if (pages.includes(page.path)) {
|
|
855
|
+
isIndependent = true;
|
|
856
|
+
independentName = name;
|
|
857
|
+
importBaseTemplatePath = helper_1.promoteRelativePath(path.relative(page.path, path.join(sourceDir, name, this.getTemplatePath(baseTemplateName))));
|
|
858
|
+
}
|
|
859
|
+
});
|
|
860
|
+
if (config) {
|
|
861
|
+
let importBaseCompPath = helper_1.promoteRelativePath(path.relative(page.path, path.join(sourceDir, this.getTargetFilePath(this.getIsBuildPluginPath(baseCompName, isBuildPlugin), ''))));
|
|
862
|
+
let importCustomWrapperPath = helper_1.promoteRelativePath(path.relative(page.path, path.join(sourceDir, this.getTargetFilePath(this.getIsBuildPluginPath(customWrapperName, isBuildPlugin), ''))));
|
|
863
|
+
if (isIndependent) {
|
|
864
|
+
importBaseCompPath = helper_1.promoteRelativePath(path.relative(page.path, path.join(sourceDir, independentName, this.getTargetFilePath(this.getIsBuildPluginPath(baseCompName, isBuildPlugin), ''))));
|
|
865
|
+
importCustomWrapperPath = helper_1.promoteRelativePath(path.relative(page.path, path.join(sourceDir, independentName, this.getTargetFilePath(this.getIsBuildPluginPath(customWrapperName, isBuildPlugin), ''))));
|
|
866
|
+
}
|
|
867
|
+
config.content.usingComponents = Object.assign({ [customWrapperName]: importCustomWrapperPath }, config.content.usingComponents);
|
|
868
|
+
if (!template.isSupportRecursive && !page.isNative) {
|
|
869
|
+
config.content.usingComponents[baseCompName] = importBaseCompPath;
|
|
870
|
+
}
|
|
871
|
+
this.generateConfigFile(compilation, page.path, config.content);
|
|
872
|
+
}
|
|
873
|
+
if (!page.isNative) {
|
|
874
|
+
this.generateTemplateFile(compilation, page.path, template.buildPageTemplate, importBaseTemplatePath);
|
|
875
|
+
}
|
|
876
|
+
});
|
|
877
|
+
this.generateTabBarFiles(compilation);
|
|
878
|
+
this.injectCommonStyles(compilation);
|
|
879
|
+
if (this.themeLocation) {
|
|
880
|
+
this.generateDarkModeFile(compilation);
|
|
881
|
+
}
|
|
882
|
+
if (isBuildPlugin) {
|
|
883
|
+
const pluginJSONPath = path.join(sourceDir, 'plugin', 'plugin.json');
|
|
884
|
+
if (fs.existsSync(pluginJSONPath)) {
|
|
885
|
+
const pluginJSON = fs.readJSONSync(pluginJSONPath);
|
|
886
|
+
this.modifyPluginJSON(pluginJSON);
|
|
887
|
+
const relativePath = pluginJSONPath.replace(sourceDir, '').replace(/\\/g, '/');
|
|
888
|
+
compilation.assets[relativePath] = new webpack_sources_1.RawSource(JSON.stringify(pluginJSON));
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
if (typeof modifyBuildAssets === 'function') {
|
|
892
|
+
yield modifyBuildAssets(compilation.assets, this);
|
|
893
|
+
}
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
generateConfigFile(compilation, filePath, config) {
|
|
897
|
+
const fileConfigName = this.getConfigPath(this.getComponentName(filePath));
|
|
898
|
+
const unOfficalConfigs = ['enableShareAppMessage', 'enableShareTimeline', 'components'];
|
|
899
|
+
unOfficalConfigs.forEach(item => {
|
|
900
|
+
delete config[item];
|
|
901
|
+
});
|
|
902
|
+
const fileConfigStr = JSON.stringify(config);
|
|
903
|
+
compilation.assets[fileConfigName] = new webpack_sources_1.RawSource(fileConfigStr);
|
|
904
|
+
}
|
|
905
|
+
generateTemplateFile(compilation, filePath, templateFn, ...options) {
|
|
906
|
+
var _a;
|
|
907
|
+
let templStr = templateFn(...options);
|
|
908
|
+
const fileTemplName = this.getTemplatePath(this.getComponentName(filePath));
|
|
909
|
+
if ((_a = this.options.minifyXML) === null || _a === void 0 ? void 0 : _a.collapseWhitespace) {
|
|
910
|
+
const minify = require('html-minifier').minify;
|
|
911
|
+
templStr = minify(templStr, {
|
|
912
|
+
collapseWhitespace: true,
|
|
913
|
+
keepClosingSlash: true
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
compilation.assets[fileTemplName] = new webpack_sources_1.RawSource(templStr);
|
|
917
|
+
}
|
|
918
|
+
generateXSFile(compilation, xsPath, isBuildPlugin) {
|
|
919
|
+
const ext = this.options.fileType.xs;
|
|
920
|
+
if (ext == null) {
|
|
921
|
+
return;
|
|
922
|
+
}
|
|
923
|
+
const xs = this.options.template.buildXScript();
|
|
924
|
+
const fileXsName = this.getTargetFilePath(xsPath, ext);
|
|
925
|
+
const filePath = this.getIsBuildPluginPath(fileXsName, isBuildPlugin);
|
|
926
|
+
compilation.assets[filePath] = new webpack_sources_1.RawSource(xs);
|
|
927
|
+
}
|
|
928
|
+
getComponentName(componentPath) {
|
|
929
|
+
let componentName;
|
|
930
|
+
if (helper_1.NODE_MODULES_REG.test(componentPath)) {
|
|
931
|
+
componentName = componentPath.replace(this.context, '').replace(/\\/g, '/').replace(path.extname(componentPath), '');
|
|
932
|
+
componentName = componentName.replace(/node_modules/gi, 'npm');
|
|
933
|
+
}
|
|
934
|
+
else {
|
|
935
|
+
componentName = componentPath.replace(this.options.sourceDir, '').replace(/\\/g, '/').replace(path.extname(componentPath), '');
|
|
936
|
+
}
|
|
937
|
+
return componentName.replace(/^(\/|\\)/, '');
|
|
938
|
+
}
|
|
939
|
+
getIsBuildPluginPath(filePath, isBuildPlugin) {
|
|
940
|
+
return isBuildPlugin ? `plugin/${filePath}` : filePath;
|
|
941
|
+
}
|
|
942
|
+
/**
|
|
943
|
+
* 根据 app、页面、组件的路径获取对应的 config 配置文件的路径
|
|
944
|
+
* @returns config 的路径
|
|
945
|
+
*/
|
|
946
|
+
getConfigFilePath(filePath) {
|
|
947
|
+
return helper_1.resolveMainFilePath(`${filePath.replace(path.extname(filePath), '')}.config`);
|
|
948
|
+
}
|
|
949
|
+
/** 处理 xml 文件后缀 */
|
|
950
|
+
getTemplatePath(filePath) {
|
|
951
|
+
return this.getTargetFilePath(filePath, this.options.fileType.templ);
|
|
952
|
+
}
|
|
953
|
+
/** 处理样式文件后缀 */
|
|
954
|
+
getStylePath(filePath) {
|
|
955
|
+
return this.getTargetFilePath(filePath, this.options.fileType.style);
|
|
956
|
+
}
|
|
957
|
+
/** 处理 config 文件后缀 */
|
|
958
|
+
getConfigPath(filePath) {
|
|
959
|
+
return this.getTargetFilePath(filePath, this.options.fileType.config);
|
|
960
|
+
}
|
|
961
|
+
/** 处理 extname */
|
|
962
|
+
getTargetFilePath(filePath, targetExtname) {
|
|
963
|
+
const extname = path.extname(filePath);
|
|
964
|
+
if (extname) {
|
|
965
|
+
return filePath.replace(extname, targetExtname);
|
|
966
|
+
}
|
|
967
|
+
return filePath + targetExtname;
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* 输出 themeLocation 文件
|
|
971
|
+
* @param compilation
|
|
972
|
+
*/
|
|
973
|
+
generateDarkModeFile(compilation) {
|
|
974
|
+
const themeLocationPath = path.resolve(this.options.sourceDir, this.themeLocation);
|
|
975
|
+
if (fs.existsSync(themeLocationPath)) {
|
|
976
|
+
const themeLocationSource = fs.readFileSync(themeLocationPath);
|
|
977
|
+
compilation.assets[this.themeLocation] = new webpack_sources_1.RawSource(themeLocationSource);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
/**
|
|
981
|
+
* 输出 tabbar icons 文件
|
|
982
|
+
*/
|
|
983
|
+
generateTabBarFiles(compilation) {
|
|
984
|
+
this.tabBarIcons.forEach(icon => {
|
|
985
|
+
const iconPath = path.resolve(this.options.sourceDir, icon);
|
|
986
|
+
if (fs.existsSync(iconPath)) {
|
|
987
|
+
const iconSource = fs.readFileSync(iconPath);
|
|
988
|
+
compilation.assets[icon] = new webpack_sources_1.RawSource(iconSource);
|
|
989
|
+
}
|
|
990
|
+
});
|
|
991
|
+
}
|
|
992
|
+
/**
|
|
993
|
+
* 小程序全局样式文件中引入 common chunks 中的公共样式文件
|
|
994
|
+
*/
|
|
995
|
+
injectCommonStyles({ assets }) {
|
|
996
|
+
const styleExt = this.options.fileType.style;
|
|
997
|
+
const appStyle = `app${styleExt}`;
|
|
998
|
+
const REG_STYLE_EXT = new RegExp(`\\.(${styleExt.replace('.', '')})(\\?.*)?$`);
|
|
999
|
+
if (!assets[appStyle])
|
|
1000
|
+
return;
|
|
1001
|
+
const originSource = assets[appStyle];
|
|
1002
|
+
const source = new webpack_sources_1.ConcatSource(originSource);
|
|
1003
|
+
Object.keys(assets).forEach(assetName => {
|
|
1004
|
+
const fileName = path.basename(assetName, path.extname(assetName));
|
|
1005
|
+
if ((helper_1.REG_STYLE.test(assetName) || REG_STYLE_EXT.test(assetName)) && this.options.commonChunks.includes(fileName)) {
|
|
1006
|
+
source.add('\n');
|
|
1007
|
+
source.add(`@import ${JSON.stringify(loader_utils_1.urlToRequest(assetName))};`);
|
|
1008
|
+
assets[appStyle] = source;
|
|
1009
|
+
}
|
|
1010
|
+
});
|
|
1011
|
+
}
|
|
1012
|
+
addTarBarFilesToDependencies(compilation) {
|
|
1013
|
+
const { fileDependencies, missingDependencies } = compilation;
|
|
1014
|
+
this.tabBarIcons.forEach(icon => {
|
|
1015
|
+
if (!fileDependencies.has(icon)) {
|
|
1016
|
+
fileDependencies.add(icon);
|
|
1017
|
+
}
|
|
1018
|
+
// 避免触发 watchpack 里 WatchpackFileWatcher 类的 "initial-missing" 事件中 _onRemove 逻辑,
|
|
1019
|
+
// 它会把 tabbar icon 当做已 remove 多次触发构建
|
|
1020
|
+
if (!missingDependencies.has(icon)) {
|
|
1021
|
+
missingDependencies.add(icon);
|
|
1022
|
+
}
|
|
1023
|
+
});
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
exports.default = TaroMiniPlugin;
|
|
1027
|
+
//# sourceMappingURL=MiniPlugin.js.map
|