@taro-minify-pack/plugin-async-pack 0.0.1-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/.eslintrc.js +21 -0
- package/LICENSE +21 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +75 -0
- package/dist/index.js.map +1 -0
- package/dist/merge-output.d.ts +12 -0
- package/dist/merge-output.js +26 -0
- package/dist/merge-output.js.map +1 -0
- package/dist/transform-app-stylesheet.d.ts +6 -0
- package/dist/transform-app-stylesheet.js +14 -0
- package/dist/transform-app-stylesheet.js.map +1 -0
- package/dist/transform-before-compression-plugin.d.ts +17 -0
- package/dist/transform-before-compression-plugin.js +31 -0
- package/dist/transform-before-compression-plugin.js.map +1 -0
- package/dist/transform-webpack-runtime.d.ts +6 -0
- package/dist/transform-webpack-runtime.js +160 -0
- package/dist/transform-webpack-runtime.js.map +1 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +51 -0
- package/src/index.ts +107 -0
- package/src/merge-output.ts +33 -0
- package/src/transform-app-stylesheet.ts +17 -0
- package/src/transform-before-compression-plugin.ts +45 -0
- package/src/transform-webpack-runtime.ts +138 -0
- package/src/types.ts +8 -0
- package/tsconfig.json +20 -0
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
env: {
|
|
3
|
+
node: true,
|
|
4
|
+
es6: true
|
|
5
|
+
},
|
|
6
|
+
extends: [
|
|
7
|
+
'standard',
|
|
8
|
+
'plugin:@typescript-eslint/recommended'
|
|
9
|
+
],
|
|
10
|
+
parser: '@typescript-eslint/parser',
|
|
11
|
+
plugins: ['@typescript-eslint'],
|
|
12
|
+
rules: {
|
|
13
|
+
'@typescript-eslint/no-empty-function': 'off',
|
|
14
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
15
|
+
'@typescript-eslint/no-var-requires': 'off',
|
|
16
|
+
'@typescript-eslint/no-non-null-assertion': 'off',
|
|
17
|
+
'@typescript-eslint/ban-ts-comment': 'off',
|
|
18
|
+
'@typescript-eslint/no-unused-vars': 'off',
|
|
19
|
+
'no-use-before-define': 'off'
|
|
20
|
+
}
|
|
21
|
+
}
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 yu.pan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const webpack_sources_1 = require("webpack-sources");
|
|
7
|
+
const transform_webpack_runtime_1 = require("./transform-webpack-runtime");
|
|
8
|
+
const transform_before_compression_plugin_1 = require("./transform-before-compression-plugin");
|
|
9
|
+
const merge_output_1 = require("./merge-output");
|
|
10
|
+
const transform_app_stylesheet_1 = require("./transform-app-stylesheet");
|
|
11
|
+
const fs_1 = __importDefault(require("fs"));
|
|
12
|
+
const path_1 = __importDefault(require("path"));
|
|
13
|
+
const dynamicPackOptsDefaultOpt = {
|
|
14
|
+
dynamicModuleJsDir: 'dynamic-common',
|
|
15
|
+
dynamicModuleStyleFile: 'dynamic-common'
|
|
16
|
+
};
|
|
17
|
+
exports.default = (ctx, pluginOpts) => {
|
|
18
|
+
const finalOpts = Object.assign(Object.assign({}, dynamicPackOptsDefaultOpt), pluginOpts);
|
|
19
|
+
if (process.env.TARO_ENV !== 'weapp')
|
|
20
|
+
return;
|
|
21
|
+
ctx.modifyWebpackChain(({ chain }) => {
|
|
22
|
+
// 动态获取现有的 splitChunks 配置
|
|
23
|
+
const existingSplitChunks = chain.optimization.get('splitChunks') || {};
|
|
24
|
+
const { common, vendors } = existingSplitChunks.cacheGroups;
|
|
25
|
+
const newCommonChunks = common ? Object.assign(Object.assign({}, common), { chunks: 'initial' }) : common;
|
|
26
|
+
const newVendorsChunks = vendors ? Object.assign(Object.assign({}, vendors), { chunks: 'initial' }) : vendors;
|
|
27
|
+
chain.optimization.merge({
|
|
28
|
+
splitChunks: Object.assign(Object.assign({}, existingSplitChunks), { cacheGroups: Object.assign(Object.assign({}, existingSplitChunks.cacheGroups), { common: newCommonChunks, vendors: newVendorsChunks }) })
|
|
29
|
+
});
|
|
30
|
+
chain.merge({
|
|
31
|
+
output: {
|
|
32
|
+
chunkFilename: `${finalOpts.dynamicModuleJsDir}/[chunkhash].js`, // 异步模块输出路径
|
|
33
|
+
path: ctx.paths.outputPath,
|
|
34
|
+
clean: true
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
chain.plugin('miniCssExtractPlugin')
|
|
38
|
+
.tap((args) => {
|
|
39
|
+
const [options] = args;
|
|
40
|
+
const finalOption = Object.assign(Object.assign({}, options), { chunkFilename: `${finalOpts.dynamicModuleStyleFile}/[chunkhash].wxss` });
|
|
41
|
+
return [finalOption];
|
|
42
|
+
});
|
|
43
|
+
chain.plugin(transform_before_compression_plugin_1.PLUGIN_NAME).use(transform_before_compression_plugin_1.TransformBeforeCompressionPlugin, [{
|
|
44
|
+
test: /^(runtime\.js|app\.wxss)$/,
|
|
45
|
+
transform: (opt) => {
|
|
46
|
+
const { source, assetName, assets } = opt;
|
|
47
|
+
const transformOpts = Object.assign(Object.assign({}, finalOpts), { assets });
|
|
48
|
+
if (/^app\.wxss$/.test(assetName))
|
|
49
|
+
return (0, transform_app_stylesheet_1.transformAppStylesheet)(source, transformOpts);
|
|
50
|
+
if (/^runtime\.js$/.test(assetName))
|
|
51
|
+
return (0, transform_webpack_runtime_1.transformWebpackRuntime)(source, transformOpts);
|
|
52
|
+
return source;
|
|
53
|
+
}
|
|
54
|
+
}]);
|
|
55
|
+
chain.plugin(merge_output_1.PLUGIN_NAME).use(merge_output_1.MergeOutputPlugin, [{
|
|
56
|
+
test: new RegExp(`^${finalOpts.dynamicModuleStyleFile}\\/.*\\.wxss$`),
|
|
57
|
+
outputFile: `${finalOpts.dynamicModuleStyleFile}.wxss`
|
|
58
|
+
}]);
|
|
59
|
+
});
|
|
60
|
+
ctx.modifyBuildAssets(({ assets }) => {
|
|
61
|
+
const curAppJSON = assets['app.json'];
|
|
62
|
+
if (!curAppJSON)
|
|
63
|
+
return;
|
|
64
|
+
const curAppJSONContent = JSON.parse(curAppJSON.source());
|
|
65
|
+
const dynamicPackagesConfig = { root: finalOpts.dynamicModuleJsDir, pages: [] };
|
|
66
|
+
const hasDynamicModule = (() => {
|
|
67
|
+
const isDynamicModuleDirExist = fs_1.default.existsSync(path_1.default.join(ctx.paths.outputPath, finalOpts.dynamicModuleJsDir));
|
|
68
|
+
return isDynamicModuleDirExist && fs_1.default.readdirSync(path_1.default.join(ctx.paths.outputPath, finalOpts.dynamicModuleJsDir)).length > 0;
|
|
69
|
+
})();
|
|
70
|
+
const { resolveAlias = {}, subpackages = [] } = curAppJSONContent;
|
|
71
|
+
const newAppJSONContent = Object.assign(Object.assign({}, curAppJSONContent), { subpackages: hasDynamicModule ? [...subpackages, dynamicPackagesConfig] : subpackages, resolveAlias: Object.assign(Object.assign({}, resolveAlias), { [`${finalOpts.dynamicModuleJsDir}/*`]: `/${finalOpts.dynamicModuleJsDir}/*` }) });
|
|
72
|
+
assets['app.json'] = new webpack_sources_1.RawSource(JSON.stringify(newAppJSONContent, null, 2));
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Compiler } from 'webpack';
|
|
2
|
+
export declare const PLUGIN_NAME = "MergeOutput";
|
|
3
|
+
interface MergeOutputOpt {
|
|
4
|
+
test: RegExp;
|
|
5
|
+
outputFile: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class MergeOutputPlugin {
|
|
8
|
+
private readonly opts;
|
|
9
|
+
constructor(opts: MergeOutputOpt);
|
|
10
|
+
apply(compiler: Compiler): void;
|
|
11
|
+
}
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MergeOutputPlugin = exports.PLUGIN_NAME = void 0;
|
|
4
|
+
exports.PLUGIN_NAME = 'MergeOutput';
|
|
5
|
+
class MergeOutputPlugin {
|
|
6
|
+
constructor(opts) {
|
|
7
|
+
this.opts = opts;
|
|
8
|
+
}
|
|
9
|
+
apply(compiler) {
|
|
10
|
+
compiler.hooks.compilation.tap(exports.PLUGIN_NAME, (compilation) => {
|
|
11
|
+
const stage = compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL; // 最早阶段,在优化前
|
|
12
|
+
compilation.hooks.processAssets.tap({ name: exports.PLUGIN_NAME, stage }, (assets) => {
|
|
13
|
+
const mergedResult = Object.keys(assets).reduce((result, item) => {
|
|
14
|
+
if (!this.opts.test.test(item))
|
|
15
|
+
return result;
|
|
16
|
+
const code = assets[item].source().toString();
|
|
17
|
+
delete assets[item];
|
|
18
|
+
return result + code + '\n';
|
|
19
|
+
}, '');
|
|
20
|
+
compilation.assets[this.opts.outputFile] = new compiler.webpack.sources.RawSource(mergedResult);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.MergeOutputPlugin = MergeOutputPlugin;
|
|
26
|
+
//# sourceMappingURL=merge-output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-output.js","sourceRoot":"","sources":["../src/merge-output.ts"],"names":[],"mappings":";;;AAEa,QAAA,WAAW,GAAG,aAAa,CAAA;AAOxC,MAAa,iBAAiB;IAG5B,YAAa,IAAoB;QAC/B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAED,KAAK,CAAE,QAAkB;QACvB,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,mBAAW,EAAE,CAAC,WAAwB,EAAE,EAAE;YACvE,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,+BAA+B,CAAA,CAAC,YAAY;YAEvF,WAAW,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,mBAAW,EAAE,KAAK,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE;gBAC3E,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE;oBAC/D,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;wBAAE,OAAO,MAAM,CAAA;oBAC7C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAA;oBAC7C,OAAO,MAAM,CAAC,IAAI,CAAC,CAAA;oBACnB,OAAO,MAAM,GAAG,IAAI,GAAG,IAAI,CAAA;gBAC7B,CAAC,EAAE,EAAE,CAAC,CAAA;gBAEN,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAW,CAAC,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,CAAA;YAClG,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC;CACF;AAvBD,8CAuBC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transformAppStylesheet = void 0;
|
|
4
|
+
const transformAppStylesheet = (code, opts) => {
|
|
5
|
+
const { dynamicModuleStyleFile, assets } = opts;
|
|
6
|
+
const isDynamicModuleStyleFileExist = Object.keys(assets).some(assetName => {
|
|
7
|
+
return new RegExp(`${dynamicModuleStyleFile}\\.wxss`).test(assetName);
|
|
8
|
+
});
|
|
9
|
+
if (!isDynamicModuleStyleFileExist)
|
|
10
|
+
return code;
|
|
11
|
+
return code.concat(`@import './${dynamicModuleStyleFile}.wxss';`);
|
|
12
|
+
};
|
|
13
|
+
exports.transformAppStylesheet = transformAppStylesheet;
|
|
14
|
+
//# sourceMappingURL=transform-app-stylesheet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform-app-stylesheet.js","sourceRoot":"","sources":["../src/transform-app-stylesheet.ts"],"names":[],"mappings":";;;AAMO,MAAM,sBAAsB,GAAG,CAAC,IAAY,EAAE,IAAU,EAAE,EAAE;IACjE,MAAM,EAAE,sBAAsB,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;IAE/C,MAAM,6BAA6B,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;QACzE,OAAO,IAAI,MAAM,CAAC,GAAG,sBAAsB,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACvE,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,6BAA6B;QAAE,OAAO,IAAI,CAAA;IAE/C,OAAO,IAAI,CAAC,MAAM,CAAC,cAAc,sBAAsB,SAAS,CAAC,CAAA;AACnE,CAAC,CAAA;AAVY,QAAA,sBAAsB,0BAUlC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import webpack from 'webpack';
|
|
2
|
+
import { CompilationAssets } from './types';
|
|
3
|
+
export interface TransformOpt {
|
|
4
|
+
assetName: string;
|
|
5
|
+
source: string | Buffer;
|
|
6
|
+
assets: CompilationAssets;
|
|
7
|
+
}
|
|
8
|
+
export interface PluginOpt {
|
|
9
|
+
test?: RegExp;
|
|
10
|
+
transform: (opt: TransformOpt) => string;
|
|
11
|
+
}
|
|
12
|
+
export declare const PLUGIN_NAME = "TransformBeforeCompression";
|
|
13
|
+
export declare class TransformBeforeCompressionPlugin {
|
|
14
|
+
private readonly opt;
|
|
15
|
+
constructor(opt: PluginOpt);
|
|
16
|
+
apply(compiler: webpack.Compiler): void;
|
|
17
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.TransformBeforeCompressionPlugin = exports.PLUGIN_NAME = void 0;
|
|
7
|
+
const webpack_1 = __importDefault(require("webpack"));
|
|
8
|
+
exports.PLUGIN_NAME = 'TransformBeforeCompression';
|
|
9
|
+
class TransformBeforeCompressionPlugin {
|
|
10
|
+
constructor(opt) {
|
|
11
|
+
this.opt = opt;
|
|
12
|
+
}
|
|
13
|
+
apply(compiler) {
|
|
14
|
+
compiler.hooks.compilation.tap(exports.PLUGIN_NAME, (compilation) => {
|
|
15
|
+
const stage = webpack_1.default.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE; // 压缩前
|
|
16
|
+
compilation.hooks.processAssets.tap({ name: exports.PLUGIN_NAME, stage }, (assets) => {
|
|
17
|
+
const { test, transform } = this.opt;
|
|
18
|
+
const assetNames = Object.keys(assets);
|
|
19
|
+
assetNames.forEach((assetName) => {
|
|
20
|
+
if (!test || !test.test(assetName))
|
|
21
|
+
return;
|
|
22
|
+
const source = assets[assetName].source();
|
|
23
|
+
const transformResult = transform({ assetName, source, assets });
|
|
24
|
+
compilation.updateAsset(assetName, new webpack_1.default.sources.RawSource(transformResult));
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.TransformBeforeCompressionPlugin = TransformBeforeCompressionPlugin;
|
|
31
|
+
//# sourceMappingURL=transform-before-compression-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform-before-compression-plugin.js","sourceRoot":"","sources":["../src/transform-before-compression-plugin.ts"],"names":[],"mappings":";;;;;;AAAA,sDAA6B;AAchB,QAAA,WAAW,GAAG,4BAA4B,CAAA;AAEvD,MAAa,gCAAgC;IAG3C,YAAa,GAAc;QACzB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;IAChB,CAAC;IAED,KAAK,CAAE,QAA0B;QAC/B,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,mBAAW,EAAE,CAAC,WAAgC,EAAE,EAAE;YAC/E,MAAM,KAAK,GAAG,iBAAO,CAAC,WAAW,CAAC,6BAA6B,CAAA,CAAC,MAAM;YAEtE,WAAW,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,mBAAW,EAAE,KAAK,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE;gBAC3E,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,GAAG,CAAA;gBAEpC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;gBAEtC,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;oBAC/B,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;wBAAE,OAAM;oBAE1C,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,CAAA;oBAEzC,MAAM,eAAe,GAAG,SAAS,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAkB,CAAC,CAAA;oBAEhF,WAAW,CAAC,WAAW,CAAC,SAAS,EAAE,IAAI,iBAAO,CAAC,OAAO,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAA;gBACpF,CAAC,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC;CACF;AA5BD,4EA4BC"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.transformWebpackRuntime = void 0;
|
|
40
|
+
const core_1 = require("@babel/core");
|
|
41
|
+
const generator_1 = __importDefault(require("@babel/generator"));
|
|
42
|
+
const parser = __importStar(require("@babel/parser"));
|
|
43
|
+
const traverse_1 = __importDefault(require("@babel/traverse"));
|
|
44
|
+
const types = __importStar(require("@babel/types"));
|
|
45
|
+
const webpackLoadDynamicModuleTemplateDep = `
|
|
46
|
+
var loadedDynamicModules = {};
|
|
47
|
+
var loadDynamicModule = function (dynamicModulePath) {
|
|
48
|
+
var loadDynamicModuleFn = loadDynamicModuleFnMap[dynamicModulePath];
|
|
49
|
+
return loadDynamicModuleFn ? loadDynamicModuleFn() : Promise.reject();
|
|
50
|
+
};
|
|
51
|
+
var promiseRetry = function (apply,retries = 6,delay = 500) {
|
|
52
|
+
return apply().catch(function (error) {
|
|
53
|
+
if (retries <= 0) return Promise.reject(error);
|
|
54
|
+
return new Promise(function (resolve) {
|
|
55
|
+
setTimeout(resolve, delay);
|
|
56
|
+
})
|
|
57
|
+
.then(function () {
|
|
58
|
+
return promiseRetry(apply, retries - 1, delay)
|
|
59
|
+
});
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
`;
|
|
63
|
+
const webpackLoadDynamicModuleTemplate = `
|
|
64
|
+
__webpack_require__.l = function (dynamicModulePath, done, key, chunkId) {
|
|
65
|
+
if (inProgress[dynamicModulePath]) {
|
|
66
|
+
inProgress[dynamicModulePath].push(done);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const target = { src: dynamicModulePath };
|
|
71
|
+
|
|
72
|
+
if (loadedDynamicModules[dynamicModulePath]) return done({ type: 'loaded', target });
|
|
73
|
+
|
|
74
|
+
promiseRetry(function () {
|
|
75
|
+
return loadDynamicModule(dynamicModulePath)
|
|
76
|
+
})
|
|
77
|
+
.then(function () {
|
|
78
|
+
return done({ type: 'loaded', target })
|
|
79
|
+
}).catch(function () {
|
|
80
|
+
return done({ type:'error', target })
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
`;
|
|
84
|
+
const replaceWebpackLoadScriptFn = (assignmentExpressionNodePath, opts) => {
|
|
85
|
+
const { left, right } = assignmentExpressionNodePath.node || {};
|
|
86
|
+
if (!types.isMemberExpression(left))
|
|
87
|
+
return;
|
|
88
|
+
if (!types.isFunctionExpression(right))
|
|
89
|
+
return;
|
|
90
|
+
if (!types.isIdentifier(left.object, { name: '__webpack_require__' }))
|
|
91
|
+
return;
|
|
92
|
+
if (!types.isIdentifier(left.property, { name: 'l' }))
|
|
93
|
+
return;
|
|
94
|
+
const isProcessed = right.params.some((item) => {
|
|
95
|
+
return types.isIdentifier(item, { name: 'dynamicModulePath' });
|
|
96
|
+
});
|
|
97
|
+
if (isProcessed)
|
|
98
|
+
return;
|
|
99
|
+
const { assets, dynamicModuleJsDir } = opts;
|
|
100
|
+
const dynamicAssets = Object.keys(assets).filter((assetName) => {
|
|
101
|
+
return new RegExp(`^${dynamicModuleJsDir}/.`).test(assetName);
|
|
102
|
+
});
|
|
103
|
+
const loadDynamicModuleFnMapCode = (() => {
|
|
104
|
+
const tempCode = dynamicAssets.map((dynamicAsset) => {
|
|
105
|
+
return `'/${dynamicAsset}':function (){ return require.async('${dynamicAsset}'); }`;
|
|
106
|
+
});
|
|
107
|
+
return `var loadDynamicModuleFnMap = {${tempCode.join(',')}}`;
|
|
108
|
+
})();
|
|
109
|
+
const templateCodeAst = core_1.template.ast(webpackLoadDynamicModuleTemplate);
|
|
110
|
+
const templateCodeDepAst = core_1.template.ast(webpackLoadDynamicModuleTemplateDep);
|
|
111
|
+
const loadDynamicModuleFnMapAst = core_1.template.ast(loadDynamicModuleFnMapCode);
|
|
112
|
+
assignmentExpressionNodePath.replaceWith(templateCodeAst);
|
|
113
|
+
assignmentExpressionNodePath.insertBefore(templateCodeDepAst);
|
|
114
|
+
assignmentExpressionNodePath.insertBefore(loadDynamicModuleFnMapAst);
|
|
115
|
+
};
|
|
116
|
+
const webpackLoadDynamicModuleStylesheetTemplate = `
|
|
117
|
+
loadStylesheet = function () {
|
|
118
|
+
return Promise.resolve()
|
|
119
|
+
}
|
|
120
|
+
`;
|
|
121
|
+
const replaceLoadStylesheetFn = (nodePath) => {
|
|
122
|
+
const { id, init } = nodePath.node || {};
|
|
123
|
+
if (!types.isIdentifier(id, { name: 'loadStylesheet' }))
|
|
124
|
+
return;
|
|
125
|
+
if (!types.isFunctionExpression(init))
|
|
126
|
+
return;
|
|
127
|
+
const isProcessed = !init.params.length;
|
|
128
|
+
if (isProcessed)
|
|
129
|
+
return;
|
|
130
|
+
const templateCodeAst = core_1.template.expression(webpackLoadDynamicModuleStylesheetTemplate)();
|
|
131
|
+
nodePath.replaceWith(templateCodeAst);
|
|
132
|
+
};
|
|
133
|
+
const removeCreateStylesheetFn = (nodePath) => {
|
|
134
|
+
const { id } = nodePath.node || {};
|
|
135
|
+
if (!types.isIdentifier(id, { name: 'createStylesheet' }))
|
|
136
|
+
return;
|
|
137
|
+
nodePath.remove();
|
|
138
|
+
};
|
|
139
|
+
const removeFindStylesheetFn = (nodePath) => {
|
|
140
|
+
const { id } = nodePath.node || {};
|
|
141
|
+
if (!types.isIdentifier(id, { name: 'findStylesheet' }))
|
|
142
|
+
return;
|
|
143
|
+
nodePath.remove();
|
|
144
|
+
};
|
|
145
|
+
const transformWebpackRuntime = (code, opts) => {
|
|
146
|
+
const ast = parser.parse(code); // 将代码解析为 AST
|
|
147
|
+
(0, traverse_1.default)(ast, {
|
|
148
|
+
AssignmentExpression: (nodePath) => {
|
|
149
|
+
replaceWebpackLoadScriptFn(nodePath, opts);
|
|
150
|
+
},
|
|
151
|
+
VariableDeclarator(nodePath) {
|
|
152
|
+
replaceLoadStylesheetFn(nodePath);
|
|
153
|
+
removeCreateStylesheetFn(nodePath);
|
|
154
|
+
removeFindStylesheetFn(nodePath);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
return (0, generator_1.default)(ast).code;
|
|
158
|
+
};
|
|
159
|
+
exports.transformWebpackRuntime = transformWebpackRuntime;
|
|
160
|
+
//# sourceMappingURL=transform-webpack-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform-webpack-runtime.js","sourceRoot":"","sources":["../src/transform-webpack-runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@taro-minify-pack/plugin-async-pack",
|
|
3
|
+
"version": "0.0.1-alpha.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"homepage": "https://github.com/panyu97py/taro-minify-pack",
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/panyu97py/taro-minify-pack.git"
|
|
14
|
+
},
|
|
15
|
+
"author": "yu.pan",
|
|
16
|
+
"license": "ISC",
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"@tarojs/service": "^3.0.0"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@babel/core": "^7.26.10",
|
|
22
|
+
"@babel/generator": "^7.26.10",
|
|
23
|
+
"@babel/parser": "^7.26.10",
|
|
24
|
+
"@babel/template": "^7.26.9",
|
|
25
|
+
"@babel/traverse": "^7.26.10",
|
|
26
|
+
"@babel/types": "^7.26.10",
|
|
27
|
+
"webpack": "^5.98.0",
|
|
28
|
+
"webpack-sources": "^3.2.3"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@tarojs/service": "^4.0.9",
|
|
32
|
+
"@types/babel__core": "^7.20.5",
|
|
33
|
+
"@types/babel__generator": "^7.6.8",
|
|
34
|
+
"@types/babel__template": "^7.4.4",
|
|
35
|
+
"@types/babel__traverse": "^7.20.6",
|
|
36
|
+
"@types/md5": "^2.3.5",
|
|
37
|
+
"@types/node": "^18.19.130",
|
|
38
|
+
"@types/webpack-sources": "^3.2.3",
|
|
39
|
+
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
|
40
|
+
"@typescript-eslint/parser": "^8.26.1",
|
|
41
|
+
"eslint": "^8.19.0",
|
|
42
|
+
"eslint-config-standard": "^17.0.0",
|
|
43
|
+
"eslint-plugin-import": "^2.26.0",
|
|
44
|
+
"eslint-plugin-n": "^15.2.3",
|
|
45
|
+
"eslint-plugin-promise": "^6.0.0",
|
|
46
|
+
"typescript": "^5.8.2"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc"
|
|
50
|
+
}
|
|
51
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { IPluginContext } from '@tarojs/service'
|
|
2
|
+
import { RawSource } from 'webpack-sources'
|
|
3
|
+
import { transformWebpackRuntime } from './transform-webpack-runtime'
|
|
4
|
+
import {
|
|
5
|
+
TransformOpt,
|
|
6
|
+
TransformBeforeCompressionPlugin,
|
|
7
|
+
PLUGIN_NAME as TransformBeforeCompressionPluginName
|
|
8
|
+
} from './transform-before-compression-plugin'
|
|
9
|
+
import { MergeOutputPlugin, PLUGIN_NAME as MergeOutputPluginName } from './merge-output'
|
|
10
|
+
import { AsyncPackOpts } from './types'
|
|
11
|
+
import { transformAppStylesheet } from './transform-app-stylesheet'
|
|
12
|
+
import fs from 'fs'
|
|
13
|
+
import path from 'path'
|
|
14
|
+
|
|
15
|
+
export { AsyncPackOpts } from './types'
|
|
16
|
+
|
|
17
|
+
const dynamicPackOptsDefaultOpt: AsyncPackOpts = {
|
|
18
|
+
dynamicModuleJsDir: 'dynamic-common',
|
|
19
|
+
dynamicModuleStyleFile: 'dynamic-common'
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default (ctx: IPluginContext, pluginOpts: AsyncPackOpts) => {
|
|
23
|
+
const finalOpts = { ...dynamicPackOptsDefaultOpt, ...pluginOpts }
|
|
24
|
+
|
|
25
|
+
if (process.env.TARO_ENV !== 'weapp') return
|
|
26
|
+
|
|
27
|
+
ctx.modifyWebpackChain(({ chain }) => {
|
|
28
|
+
// 动态获取现有的 splitChunks 配置
|
|
29
|
+
const existingSplitChunks = chain.optimization.get('splitChunks') || {}
|
|
30
|
+
|
|
31
|
+
const { common, vendors } = existingSplitChunks.cacheGroups
|
|
32
|
+
|
|
33
|
+
const newCommonChunks = common ? { ...common, chunks: 'initial' } : common
|
|
34
|
+
|
|
35
|
+
const newVendorsChunks = vendors ? { ...vendors, chunks: 'initial' } : vendors
|
|
36
|
+
|
|
37
|
+
chain.optimization.merge({
|
|
38
|
+
splitChunks: {
|
|
39
|
+
...existingSplitChunks,
|
|
40
|
+
cacheGroups: {
|
|
41
|
+
...existingSplitChunks.cacheGroups,
|
|
42
|
+
common: newCommonChunks,
|
|
43
|
+
vendors: newVendorsChunks
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
chain.merge({
|
|
49
|
+
output: {
|
|
50
|
+
chunkFilename: `${finalOpts.dynamicModuleJsDir}/[chunkhash].js`, // 异步模块输出路径
|
|
51
|
+
path: ctx.paths.outputPath,
|
|
52
|
+
clean: true
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
chain.plugin('miniCssExtractPlugin')
|
|
57
|
+
.tap((args) => {
|
|
58
|
+
const [options] = args
|
|
59
|
+
const finalOption = { ...options, chunkFilename: `${finalOpts.dynamicModuleStyleFile}/[chunkhash].wxss` }
|
|
60
|
+
return [finalOption]
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
chain.plugin(TransformBeforeCompressionPluginName).use(TransformBeforeCompressionPlugin, [{
|
|
64
|
+
test: /^(runtime\.js|app\.wxss)$/,
|
|
65
|
+
transform: (opt: TransformOpt) => {
|
|
66
|
+
const { source, assetName, assets } = opt
|
|
67
|
+
const transformOpts = { ...finalOpts, assets }
|
|
68
|
+
if (/^app\.wxss$/.test(assetName)) return transformAppStylesheet(source as string, transformOpts)
|
|
69
|
+
if (/^runtime\.js$/.test(assetName)) return transformWebpackRuntime(source as string, transformOpts)
|
|
70
|
+
return source as string
|
|
71
|
+
}
|
|
72
|
+
}])
|
|
73
|
+
|
|
74
|
+
chain.plugin(MergeOutputPluginName).use(MergeOutputPlugin, [{
|
|
75
|
+
test: new RegExp(`^${finalOpts.dynamicModuleStyleFile}\\/.*\\.wxss$`),
|
|
76
|
+
outputFile: `${finalOpts.dynamicModuleStyleFile}.wxss`
|
|
77
|
+
}])
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
ctx.modifyBuildAssets(({ assets }) => {
|
|
81
|
+
const curAppJSON = assets['app.json']
|
|
82
|
+
|
|
83
|
+
if (!curAppJSON) return
|
|
84
|
+
|
|
85
|
+
const curAppJSONContent = JSON.parse(curAppJSON.source())
|
|
86
|
+
|
|
87
|
+
const dynamicPackagesConfig = { root: finalOpts.dynamicModuleJsDir, pages: [] }
|
|
88
|
+
|
|
89
|
+
const hasDynamicModule = (() => {
|
|
90
|
+
const isDynamicModuleDirExist = fs.existsSync(path.join(ctx.paths.outputPath, finalOpts.dynamicModuleJsDir))
|
|
91
|
+
return isDynamicModuleDirExist && fs.readdirSync(path.join(ctx.paths.outputPath, finalOpts.dynamicModuleJsDir)).length > 0
|
|
92
|
+
})()
|
|
93
|
+
|
|
94
|
+
const { resolveAlias = {}, subpackages = [] } = curAppJSONContent
|
|
95
|
+
|
|
96
|
+
const newAppJSONContent = {
|
|
97
|
+
...curAppJSONContent,
|
|
98
|
+
subpackages: hasDynamicModule ? [...subpackages, dynamicPackagesConfig] : subpackages,
|
|
99
|
+
resolveAlias: {
|
|
100
|
+
...resolveAlias,
|
|
101
|
+
[`${finalOpts.dynamicModuleJsDir}/*`]: `/${finalOpts.dynamicModuleJsDir}/*`
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
assets['app.json'] = new RawSource(JSON.stringify(newAppJSONContent, null, 2))
|
|
106
|
+
})
|
|
107
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Compiler, Compilation } from 'webpack'
|
|
2
|
+
|
|
3
|
+
export const PLUGIN_NAME = 'MergeOutput'
|
|
4
|
+
|
|
5
|
+
interface MergeOutputOpt {
|
|
6
|
+
test: RegExp,
|
|
7
|
+
outputFile: string,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class MergeOutputPlugin {
|
|
11
|
+
private readonly opts: MergeOutputOpt
|
|
12
|
+
|
|
13
|
+
constructor (opts: MergeOutputOpt) {
|
|
14
|
+
this.opts = opts
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
apply (compiler: Compiler) {
|
|
18
|
+
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation: Compilation) => {
|
|
19
|
+
const stage = compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL // 最早阶段,在优化前
|
|
20
|
+
|
|
21
|
+
compilation.hooks.processAssets.tap({ name: PLUGIN_NAME, stage }, (assets) => {
|
|
22
|
+
const mergedResult = Object.keys(assets).reduce((result, item) => {
|
|
23
|
+
if (!this.opts.test.test(item)) return result
|
|
24
|
+
const code = assets[item].source().toString()
|
|
25
|
+
delete assets[item]
|
|
26
|
+
return result + code + '\n'
|
|
27
|
+
}, '')
|
|
28
|
+
|
|
29
|
+
compilation.assets[this.opts.outputFile!] = new compiler.webpack.sources.RawSource(mergedResult)
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CompilationAssets, AsyncPackOpts } from './types'
|
|
2
|
+
|
|
3
|
+
interface Opts extends AsyncPackOpts {
|
|
4
|
+
assets: CompilationAssets;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const transformAppStylesheet = (code: string, opts: Opts) => {
|
|
8
|
+
const { dynamicModuleStyleFile, assets } = opts
|
|
9
|
+
|
|
10
|
+
const isDynamicModuleStyleFileExist = Object.keys(assets).some(assetName => {
|
|
11
|
+
return new RegExp(`${dynamicModuleStyleFile}\\.wxss`).test(assetName)
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
if (!isDynamicModuleStyleFileExist) return code
|
|
15
|
+
|
|
16
|
+
return code.concat(`@import './${dynamicModuleStyleFile}.wxss';`)
|
|
17
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import webpack from 'webpack'
|
|
2
|
+
import { CompilationAssets } from './types'
|
|
3
|
+
|
|
4
|
+
export interface TransformOpt {
|
|
5
|
+
assetName: string
|
|
6
|
+
source: string | Buffer
|
|
7
|
+
assets: CompilationAssets
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface PluginOpt {
|
|
11
|
+
test?: RegExp;
|
|
12
|
+
transform: (opt: TransformOpt) => string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const PLUGIN_NAME = 'TransformBeforeCompression'
|
|
16
|
+
|
|
17
|
+
export class TransformBeforeCompressionPlugin {
|
|
18
|
+
private readonly opt: PluginOpt
|
|
19
|
+
|
|
20
|
+
constructor (opt: PluginOpt) {
|
|
21
|
+
this.opt = opt
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
apply (compiler: webpack.Compiler) {
|
|
25
|
+
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation: webpack.Compilation) => {
|
|
26
|
+
const stage = webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE // 压缩前
|
|
27
|
+
|
|
28
|
+
compilation.hooks.processAssets.tap({ name: PLUGIN_NAME, stage }, (assets) => {
|
|
29
|
+
const { test, transform } = this.opt
|
|
30
|
+
|
|
31
|
+
const assetNames = Object.keys(assets)
|
|
32
|
+
|
|
33
|
+
assetNames.forEach((assetName) => {
|
|
34
|
+
if (!test || !test.test(assetName)) return
|
|
35
|
+
|
|
36
|
+
const source = assets[assetName].source()
|
|
37
|
+
|
|
38
|
+
const transformResult = transform({ assetName, source, assets } as TransformOpt)
|
|
39
|
+
|
|
40
|
+
compilation.updateAsset(assetName, new webpack.sources.RawSource(transformResult))
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { NodePath, template } from '@babel/core'
|
|
2
|
+
import generator from '@babel/generator'
|
|
3
|
+
import * as parser from '@babel/parser'
|
|
4
|
+
import traverse, { Node } from '@babel/traverse'
|
|
5
|
+
import * as types from '@babel/types'
|
|
6
|
+
import type { AssignmentExpression, VariableDeclarator } from '@babel/types'
|
|
7
|
+
import type { CompilationAssets, AsyncPackOpts } from './types'
|
|
8
|
+
|
|
9
|
+
interface Opts extends AsyncPackOpts {
|
|
10
|
+
assets: CompilationAssets;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const webpackLoadDynamicModuleTemplateDep = `
|
|
14
|
+
var loadedDynamicModules = {};
|
|
15
|
+
var loadDynamicModule = function (dynamicModulePath) {
|
|
16
|
+
var loadDynamicModuleFn = loadDynamicModuleFnMap[dynamicModulePath];
|
|
17
|
+
return loadDynamicModuleFn ? loadDynamicModuleFn() : Promise.reject();
|
|
18
|
+
};
|
|
19
|
+
var promiseRetry = function (apply,retries = 6,delay = 500) {
|
|
20
|
+
return apply().catch(function (error) {
|
|
21
|
+
if (retries <= 0) return Promise.reject(error);
|
|
22
|
+
return new Promise(function (resolve) {
|
|
23
|
+
setTimeout(resolve, delay);
|
|
24
|
+
})
|
|
25
|
+
.then(function () {
|
|
26
|
+
return promiseRetry(apply, retries - 1, delay)
|
|
27
|
+
});
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
`
|
|
31
|
+
|
|
32
|
+
const webpackLoadDynamicModuleTemplate = `
|
|
33
|
+
__webpack_require__.l = function (dynamicModulePath, done, key, chunkId) {
|
|
34
|
+
if (inProgress[dynamicModulePath]) {
|
|
35
|
+
inProgress[dynamicModulePath].push(done);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const target = { src: dynamicModulePath };
|
|
40
|
+
|
|
41
|
+
if (loadedDynamicModules[dynamicModulePath]) return done({ type: 'loaded', target });
|
|
42
|
+
|
|
43
|
+
promiseRetry(function () {
|
|
44
|
+
return loadDynamicModule(dynamicModulePath)
|
|
45
|
+
})
|
|
46
|
+
.then(function () {
|
|
47
|
+
return done({ type: 'loaded', target })
|
|
48
|
+
}).catch(function () {
|
|
49
|
+
return done({ type:'error', target })
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
`
|
|
53
|
+
|
|
54
|
+
const replaceWebpackLoadScriptFn = (assignmentExpressionNodePath: NodePath<AssignmentExpression>, opts: Opts) => {
|
|
55
|
+
const { left, right } = assignmentExpressionNodePath.node || {}
|
|
56
|
+
|
|
57
|
+
if (!types.isMemberExpression(left)) return
|
|
58
|
+
|
|
59
|
+
if (!types.isFunctionExpression(right)) return
|
|
60
|
+
|
|
61
|
+
if (!types.isIdentifier(left.object, { name: '__webpack_require__' })) return
|
|
62
|
+
|
|
63
|
+
if (!types.isIdentifier(left.property, { name: 'l' })) return
|
|
64
|
+
|
|
65
|
+
const isProcessed = right.params.some((item) => {
|
|
66
|
+
return types.isIdentifier(item, { name: 'dynamicModulePath' })
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
if (isProcessed) return
|
|
70
|
+
|
|
71
|
+
const { assets, dynamicModuleJsDir } = opts
|
|
72
|
+
|
|
73
|
+
const dynamicAssets = Object.keys(assets).filter((assetName) => {
|
|
74
|
+
return new RegExp(`^${dynamicModuleJsDir}/.`).test(assetName)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
const loadDynamicModuleFnMapCode = (() => {
|
|
78
|
+
const tempCode = dynamicAssets.map((dynamicAsset) => {
|
|
79
|
+
return `'/${dynamicAsset}':function (){ return require.async('${dynamicAsset}'); }`
|
|
80
|
+
})
|
|
81
|
+
return `var loadDynamicModuleFnMap = {${tempCode.join(',')}}`
|
|
82
|
+
})()
|
|
83
|
+
|
|
84
|
+
const templateCodeAst = template.ast(webpackLoadDynamicModuleTemplate)
|
|
85
|
+
|
|
86
|
+
const templateCodeDepAst = template.ast(webpackLoadDynamicModuleTemplateDep)
|
|
87
|
+
|
|
88
|
+
const loadDynamicModuleFnMapAst = template.ast(loadDynamicModuleFnMapCode)
|
|
89
|
+
|
|
90
|
+
assignmentExpressionNodePath.replaceWith(templateCodeAst as Node)
|
|
91
|
+
|
|
92
|
+
assignmentExpressionNodePath.insertBefore(templateCodeDepAst)
|
|
93
|
+
|
|
94
|
+
assignmentExpressionNodePath.insertBefore(loadDynamicModuleFnMapAst)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const webpackLoadDynamicModuleStylesheetTemplate = `
|
|
98
|
+
loadStylesheet = function () {
|
|
99
|
+
return Promise.resolve()
|
|
100
|
+
}
|
|
101
|
+
`
|
|
102
|
+
|
|
103
|
+
const replaceLoadStylesheetFn = (nodePath: NodePath<VariableDeclarator>) => {
|
|
104
|
+
const { id, init } = nodePath.node || {}
|
|
105
|
+
if (!types.isIdentifier(id, { name: 'loadStylesheet' })) return
|
|
106
|
+
if (!types.isFunctionExpression(init)) return
|
|
107
|
+
const isProcessed = !init.params.length
|
|
108
|
+
if (isProcessed) return
|
|
109
|
+
const templateCodeAst = template.expression(webpackLoadDynamicModuleStylesheetTemplate)()
|
|
110
|
+
nodePath.replaceWith(templateCodeAst)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const removeCreateStylesheetFn = (nodePath: NodePath<VariableDeclarator>) => {
|
|
114
|
+
const { id } = nodePath.node || {}
|
|
115
|
+
if (!types.isIdentifier(id, { name: 'createStylesheet' })) return
|
|
116
|
+
nodePath.remove()
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const removeFindStylesheetFn = (nodePath: NodePath<VariableDeclarator>) => {
|
|
120
|
+
const { id } = nodePath.node || {}
|
|
121
|
+
if (!types.isIdentifier(id, { name: 'findStylesheet' })) return
|
|
122
|
+
nodePath.remove()
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export const transformWebpackRuntime = (code: string, opts: Opts) => {
|
|
126
|
+
const ast = parser.parse(code) // 将代码解析为 AST
|
|
127
|
+
traverse(ast, {
|
|
128
|
+
AssignmentExpression: (nodePath: NodePath<AssignmentExpression>) => {
|
|
129
|
+
replaceWebpackLoadScriptFn(nodePath, opts)
|
|
130
|
+
},
|
|
131
|
+
VariableDeclarator (nodePath: NodePath<VariableDeclarator>) {
|
|
132
|
+
replaceLoadStylesheetFn(nodePath)
|
|
133
|
+
removeCreateStylesheetFn(nodePath)
|
|
134
|
+
removeFindStylesheetFn(nodePath)
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
return generator(ast).code
|
|
138
|
+
}
|
package/src/types.ts
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2015",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"strict": true,
|
|
6
|
+
"sourceMap": true,
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"moduleResolution": "node",
|
|
10
|
+
// 声明文件生成到的文件目录
|
|
11
|
+
"outDir": "./dist/",
|
|
12
|
+
"skipLibCheck": true,
|
|
13
|
+
/* Skip type checking of declaration files. */
|
|
14
|
+
"forceConsistentCasingInFileNames": true,
|
|
15
|
+
"jsx": "react",
|
|
16
|
+
"lib": ["esnext", "dom"],
|
|
17
|
+
"types": ["@types/node"]
|
|
18
|
+
},
|
|
19
|
+
"include": ["src"]
|
|
20
|
+
}
|