@taro-hmr-compile/plugin-webpack 0.0.1-alpha.6 → 0.0.1-alpha.8
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/dist/compile/hmr-compiler-loader.d.ts +1 -1
- package/dist/compile/hmr-compiler-loader.js +48 -40
- package/dist/compile/hmr-compiler-loader.js.map +1 -1
- package/dist/compile/hmr-compiler-plugin.d.ts +4 -2
- package/dist/compile/hmr-compiler-plugin.js +11 -14
- package/dist/compile/hmr-compiler-plugin.js.map +1 -1
- package/dist/patch/hmr-patch-plugin.d.ts +6 -5
- package/dist/patch/hmr-patch-plugin.js +33 -179
- package/dist/patch/hmr-patch-plugin.js.map +1 -1
- package/dist/patch/hmr-patch-processor.d.ts +29 -0
- package/dist/patch/hmr-patch-processor.js +105 -0
- package/dist/patch/hmr-patch-processor.js.map +1 -0
- package/dist/patch/types.d.ts +15 -0
- package/dist/patch/types.js +3 -0
- package/dist/patch/types.js.map +1 -0
- package/dist/patch/utils.d.ts +26 -0
- package/dist/patch/utils.js +173 -0
- package/dist/patch/utils.js.map +1 -0
- package/package.json +2 -2
- package/src/compile/hmr-compiler-loader.ts +58 -40
- package/src/compile/hmr-compiler-plugin.ts +18 -16
- package/src/patch/hmr-patch-plugin.ts +42 -168
- package/src/patch/hmr-patch-processor.ts +149 -0
- package/src/patch/types.ts +19 -0
- package/src/patch/utils.ts +174 -0
- package/dist/patch/hmr-patch-manager.d.ts +0 -30
- package/dist/patch/hmr-patch-manager.js +0 -75
- package/dist/patch/hmr-patch-manager.js.map +0 -1
- package/src/patch/hmr-patch-manager.ts +0 -102
|
@@ -0,0 +1,105 @@
|
|
|
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.HmrPatchProcessor = void 0;
|
|
7
|
+
const generator_1 = __importDefault(require("@babel/generator"));
|
|
8
|
+
const utils_1 = require("./utils");
|
|
9
|
+
const crypto_1 = require("crypto");
|
|
10
|
+
const constants_1 = require("../constants");
|
|
11
|
+
class HmrPatchProcessor {
|
|
12
|
+
constructor(opts) {
|
|
13
|
+
this.bootstrapFactories = new Map();
|
|
14
|
+
this.bootstrapFactoriesByCompilation = new WeakMap();
|
|
15
|
+
this.moduleHashesByFullHash = new Map();
|
|
16
|
+
this.recentUpdatePatches = [];
|
|
17
|
+
this.opts = opts;
|
|
18
|
+
}
|
|
19
|
+
getChangedModuleIdsByFullHash(fromHash, toHash) {
|
|
20
|
+
const fromModuleHashes = this.moduleHashesByFullHash.get(fromHash);
|
|
21
|
+
const toModuleHashes = this.moduleHashesByFullHash.get(toHash);
|
|
22
|
+
// 任一编译缺少 Hash 基线时不做过滤,避免误丢有效的 hot-update 模块。
|
|
23
|
+
if (!fromModuleHashes || !toModuleHashes)
|
|
24
|
+
return;
|
|
25
|
+
// 同时检查前后两次编译的模块,确保新增、修改和删除都能被识别。
|
|
26
|
+
const moduleIds = new Set(fromModuleHashes.keys());
|
|
27
|
+
toModuleHashes.forEach((_, moduleId) => moduleIds.add(moduleId));
|
|
28
|
+
const changedModuleIds = new Set();
|
|
29
|
+
moduleIds.forEach(moduleId => {
|
|
30
|
+
var _a, _b;
|
|
31
|
+
const fromFactoryHash = (_a = fromModuleHashes.get(moduleId)) === null || _a === void 0 ? void 0 : _a.factoryHash;
|
|
32
|
+
const toFactoryHash = (_b = toModuleHashes.get(moduleId)) === null || _b === void 0 ? void 0 : _b.factoryHash;
|
|
33
|
+
if (fromFactoryHash !== toFactoryHash)
|
|
34
|
+
changedModuleIds.add(moduleId);
|
|
35
|
+
});
|
|
36
|
+
return changedModuleIds;
|
|
37
|
+
}
|
|
38
|
+
processUpdate(opt) {
|
|
39
|
+
var _a;
|
|
40
|
+
const { fromHash, toHash } = opt;
|
|
41
|
+
const tempPatchInfo = (0, utils_1.parseHotUpdateAssets)(opt);
|
|
42
|
+
const changedModuleIds = this.getChangedModuleIdsByFullHash(fromHash, toHash);
|
|
43
|
+
const moduleFactories = (() => {
|
|
44
|
+
if (!changedModuleIds)
|
|
45
|
+
return Array.from(tempPatchInfo.moduleFactories.values());
|
|
46
|
+
return Array.from(tempPatchInfo.moduleFactories.values()).filter(item => changedModuleIds.has(item.moduleId));
|
|
47
|
+
})();
|
|
48
|
+
const removedModules = (() => {
|
|
49
|
+
if (!changedModuleIds)
|
|
50
|
+
return Array.from(tempPatchInfo.removedModules.values());
|
|
51
|
+
return Array.from(tempPatchInfo.removedModules.values()).filter(item => changedModuleIds.has(item));
|
|
52
|
+
})();
|
|
53
|
+
this.recentUpdatePatches.push({ type: 'update', moduleFactories, fromHash, toHash, removedModules });
|
|
54
|
+
const patchHistoryLimit = Math.max(1, (_a = this.opts.patchHistoryLimit) !== null && _a !== void 0 ? _a : constants_1.DEFAULT_HMR_PATCH_HISTORY_LIMIT);
|
|
55
|
+
if (this.recentUpdatePatches.length <= patchHistoryLimit)
|
|
56
|
+
return;
|
|
57
|
+
const [oldestUpdatePatch, secondOldestUpdatePatch, ...rest] = this.recentUpdatePatches;
|
|
58
|
+
const mergedUpdatePatch = (0, utils_1.mergeUpdatePatches)(oldestUpdatePatch, secondOldestUpdatePatch);
|
|
59
|
+
this.recentUpdatePatches = [mergedUpdatePatch, ...rest];
|
|
60
|
+
this.moduleHashesByFullHash.delete(oldestUpdatePatch.toHash);
|
|
61
|
+
}
|
|
62
|
+
processChunkModules(opt) {
|
|
63
|
+
const { hash: fullHash } = opt.compilation;
|
|
64
|
+
const modules = (0, utils_1.parseChunkAsset)(opt.source);
|
|
65
|
+
modules.forEach(moduleFactory => {
|
|
66
|
+
var _a;
|
|
67
|
+
const { moduleId, factory } = moduleFactory;
|
|
68
|
+
if (opt.isBootstrapChunk) {
|
|
69
|
+
const compilationFactories = (_a = this.bootstrapFactoriesByCompilation.get(opt.compilation)) !== null && _a !== void 0 ? _a : new Map();
|
|
70
|
+
compilationFactories.set(moduleId, { moduleId, factory });
|
|
71
|
+
this.bootstrapFactoriesByCompilation.set(opt.compilation, compilationFactories);
|
|
72
|
+
}
|
|
73
|
+
if (!fullHash)
|
|
74
|
+
return;
|
|
75
|
+
const moduleHashes = (() => {
|
|
76
|
+
const hasCurFullHashModuleHashMap = this.moduleHashesByFullHash.has(fullHash);
|
|
77
|
+
if (!hasCurFullHashModuleHashMap)
|
|
78
|
+
this.moduleHashesByFullHash.set(fullHash, new Map());
|
|
79
|
+
return this.moduleHashesByFullHash.get(fullHash);
|
|
80
|
+
})();
|
|
81
|
+
const { code: source } = (0, generator_1.default)(factory, { compact: true, comments: false, minified: true, });
|
|
82
|
+
const factoryHash = (0, crypto_1.createHash)('sha256').update(source).digest('hex');
|
|
83
|
+
moduleHashes.set(moduleId, { moduleId, factoryHash });
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
commitBootstrapFactories(compilation) {
|
|
87
|
+
var _a;
|
|
88
|
+
this.bootstrapFactories.clear();
|
|
89
|
+
(_a = this.bootstrapFactoriesByCompilation.get(compilation)) === null || _a === void 0 ? void 0 : _a.forEach(moduleFactory => {
|
|
90
|
+
this.bootstrapFactories.set(moduleFactory.moduleId, moduleFactory);
|
|
91
|
+
});
|
|
92
|
+
this.bootstrapFactoriesByCompilation.delete(compilation);
|
|
93
|
+
}
|
|
94
|
+
generate() {
|
|
95
|
+
const { bootstrapFactories, recentUpdatePatches } = this;
|
|
96
|
+
return (0, utils_1.generatePatchAssetSource)({ bootstrapFactories, recentUpdatePatches });
|
|
97
|
+
}
|
|
98
|
+
reset() {
|
|
99
|
+
this.bootstrapFactories.clear();
|
|
100
|
+
this.moduleHashesByFullHash.clear();
|
|
101
|
+
this.recentUpdatePatches = [];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.HmrPatchProcessor = HmrPatchProcessor;
|
|
105
|
+
//# sourceMappingURL=hmr-patch-processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hmr-patch-processor.js","sourceRoot":"","sources":["../../src/patch/hmr-patch-processor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Expression } from "@babel/types";
|
|
2
|
+
export interface ModuleFactory {
|
|
3
|
+
factory: Expression;
|
|
4
|
+
moduleId: string;
|
|
5
|
+
}
|
|
6
|
+
export interface HotUpdateManifest {
|
|
7
|
+
m?: Array<string | number>;
|
|
8
|
+
}
|
|
9
|
+
export interface UpdatePatchSource {
|
|
10
|
+
type: 'update';
|
|
11
|
+
fromHash: string;
|
|
12
|
+
toHash: string;
|
|
13
|
+
moduleFactories: ModuleFactory[];
|
|
14
|
+
removedModules: string[];
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/patch/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Asset } from "webpack";
|
|
2
|
+
import { ModuleFactory } from "./types";
|
|
3
|
+
import { UpdatePatchSource } from "./types";
|
|
4
|
+
export interface ParseHotUpdateAssetsOptions {
|
|
5
|
+
manifests: Readonly<Asset>[];
|
|
6
|
+
scripts: Readonly<Asset>[];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* 解析热更新产物
|
|
10
|
+
* @param opt
|
|
11
|
+
*/
|
|
12
|
+
export declare const parseHotUpdateAssets: (opt: ParseHotUpdateAssetsOptions) => {
|
|
13
|
+
moduleFactories: Map<string, ModuleFactory>;
|
|
14
|
+
removedModules: Set<string>;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* 解析 chunk 产物
|
|
18
|
+
* @param source
|
|
19
|
+
*/
|
|
20
|
+
export declare const parseChunkAsset: (source: string) => Map<string, ModuleFactory>;
|
|
21
|
+
export declare const mergeUpdatePatches: (basePatch: UpdatePatchSource, nextPatch: UpdatePatchSource) => UpdatePatchSource;
|
|
22
|
+
export interface generatePatchAssetSourceOpts {
|
|
23
|
+
bootstrapFactories: Map<string, ModuleFactory>;
|
|
24
|
+
recentUpdatePatches: UpdatePatchSource[];
|
|
25
|
+
}
|
|
26
|
+
export declare const generatePatchAssetSource: (opt: generatePatchAssetSourceOpts) => string;
|
|
@@ -0,0 +1,173 @@
|
|
|
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.generatePatchAssetSource = exports.mergeUpdatePatches = exports.parseChunkAsset = exports.parseHotUpdateAssets = void 0;
|
|
40
|
+
const t = __importStar(require("@babel/types"));
|
|
41
|
+
const parser_1 = require("@babel/parser");
|
|
42
|
+
const traverse_1 = __importDefault(require("@babel/traverse"));
|
|
43
|
+
const template_1 = __importDefault(require("@babel/template"));
|
|
44
|
+
const generator_1 = __importDefault(require("@babel/generator"));
|
|
45
|
+
/**
|
|
46
|
+
* 解析模块 Factory
|
|
47
|
+
* @param expression
|
|
48
|
+
*/
|
|
49
|
+
const parseModuleFactories = (expression) => {
|
|
50
|
+
const moduleFactories = new Map();
|
|
51
|
+
if (!t.isObjectExpression(expression))
|
|
52
|
+
return moduleFactories.values();
|
|
53
|
+
expression.properties.forEach(property => {
|
|
54
|
+
if (!t.isObjectProperty(property) || !t.isExpression(property.value))
|
|
55
|
+
throw new Error('[taro-hmr-compile] HMR 模块对象包含无法识别的属性');
|
|
56
|
+
const { key, value: factory } = property;
|
|
57
|
+
const moduleId = (() => {
|
|
58
|
+
if (t.isStringLiteral(key) || t.isNumericLiteral(key))
|
|
59
|
+
return String(key.value);
|
|
60
|
+
if (t.isIdentifier(key) && !property.computed)
|
|
61
|
+
return key.name;
|
|
62
|
+
throw new Error('[taro-hmr-compile] Chunk 模块对象包含无法识别的模块 ID');
|
|
63
|
+
})();
|
|
64
|
+
moduleFactories.set(moduleId, { factory, moduleId });
|
|
65
|
+
});
|
|
66
|
+
return moduleFactories.values();
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* 解析热更新产物
|
|
70
|
+
* @param opt
|
|
71
|
+
*/
|
|
72
|
+
const parseHotUpdateAssets = (opt) => {
|
|
73
|
+
const { manifests, scripts } = opt;
|
|
74
|
+
const moduleFactories = new Map();
|
|
75
|
+
scripts.forEach(asset => {
|
|
76
|
+
const ast = (0, parser_1.parse)(asset.source.source().toString(), { sourceType: 'script' });
|
|
77
|
+
(0, traverse_1.default)(ast, {
|
|
78
|
+
CallExpression(nodePath) {
|
|
79
|
+
const { callee } = nodePath.node;
|
|
80
|
+
if (!t.isMemberExpression(callee) || !t.isIdentifier(callee.object, { name: 'wx' }))
|
|
81
|
+
return;
|
|
82
|
+
if (!t.isStringLiteral(callee.property) || !callee.property.value.startsWith('webpackHotUpdate'))
|
|
83
|
+
return;
|
|
84
|
+
const [_, modules] = nodePath.node.arguments;
|
|
85
|
+
if (!t.isObjectExpression(modules))
|
|
86
|
+
return;
|
|
87
|
+
parseModuleFactories(modules).forEach(module => moduleFactories.set(module.moduleId, module));
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
const removedModules = new Set();
|
|
92
|
+
manifests.forEach((module) => {
|
|
93
|
+
const manifest = JSON.parse(module.source.source().toString());
|
|
94
|
+
const { m: tempRemoveModules = [] } = manifest;
|
|
95
|
+
tempRemoveModules.forEach(removedModule => removedModules.add(String(removedModule)));
|
|
96
|
+
}, []);
|
|
97
|
+
return { moduleFactories, removedModules };
|
|
98
|
+
};
|
|
99
|
+
exports.parseHotUpdateAssets = parseHotUpdateAssets;
|
|
100
|
+
/**
|
|
101
|
+
* 解析 chunk 产物
|
|
102
|
+
* @param source
|
|
103
|
+
*/
|
|
104
|
+
const parseChunkAsset = (source) => {
|
|
105
|
+
const ast = (0, parser_1.parse)(`(${source})`, { sourceType: 'script' });
|
|
106
|
+
const [statement] = ast.program.body;
|
|
107
|
+
if (!t.isExpressionStatement(statement) || !t.isObjectExpression(statement.expression))
|
|
108
|
+
throw new Error('[taro-hmr-compile] Chunk 模块段不是对象表达式');
|
|
109
|
+
const moduleFactories = new Map();
|
|
110
|
+
parseModuleFactories(statement.expression).forEach(module => moduleFactories.set(module.moduleId, module));
|
|
111
|
+
return moduleFactories;
|
|
112
|
+
};
|
|
113
|
+
exports.parseChunkAsset = parseChunkAsset;
|
|
114
|
+
const mergeUpdatePatches = (basePatch, nextPatch) => {
|
|
115
|
+
if (basePatch.toHash !== nextPatch.fromHash)
|
|
116
|
+
throw new Error(`[taro-hmr-compile] 无法合并不连续的 HMR patch:${basePatch.toHash} !== ${nextPatch.fromHash}`);
|
|
117
|
+
const moduleFactories = new Map(basePatch.moduleFactories.map(moduleFactory => [moduleFactory.moduleId, moduleFactory]));
|
|
118
|
+
const removedModules = new Set(basePatch.removedModules);
|
|
119
|
+
nextPatch.moduleFactories.forEach(moduleFactory => {
|
|
120
|
+
const { moduleId } = moduleFactory;
|
|
121
|
+
moduleFactories.set(moduleId, moduleFactory);
|
|
122
|
+
removedModules.delete(moduleId);
|
|
123
|
+
});
|
|
124
|
+
nextPatch.removedModules.forEach(moduleId => {
|
|
125
|
+
moduleFactories.delete(moduleId);
|
|
126
|
+
removedModules.add(moduleId);
|
|
127
|
+
});
|
|
128
|
+
return {
|
|
129
|
+
type: 'update',
|
|
130
|
+
fromHash: basePatch.fromHash,
|
|
131
|
+
toHash: nextPatch.toHash,
|
|
132
|
+
moduleFactories: [...moduleFactories.values()],
|
|
133
|
+
removedModules: [...removedModules],
|
|
134
|
+
};
|
|
135
|
+
};
|
|
136
|
+
exports.mergeUpdatePatches = mergeUpdatePatches;
|
|
137
|
+
const generatePatchAssetSource = (opt) => {
|
|
138
|
+
const { bootstrapFactories, recentUpdatePatches } = opt;
|
|
139
|
+
const buildBootstrapPatch = template_1.default.expression(`({
|
|
140
|
+
type: 'bootstrap',
|
|
141
|
+
modules: MODULES
|
|
142
|
+
})`);
|
|
143
|
+
const buildUpdatePatch = template_1.default.expression(`({
|
|
144
|
+
type: 'update',
|
|
145
|
+
fromHash: "FROM_HASH",
|
|
146
|
+
toHash: "TO_HASH",
|
|
147
|
+
modules: MODULES,
|
|
148
|
+
removedModules: REMOVED_MODULES
|
|
149
|
+
})`);
|
|
150
|
+
const buildPatchAsset = template_1.default.program('module.exports = PATCHES;');
|
|
151
|
+
const bootstrapModules = Array.from(bootstrapFactories.values()).map((moduleFactory) => {
|
|
152
|
+
const { moduleId, factory } = moduleFactory;
|
|
153
|
+
return t.objectProperty(t.stringLiteral(moduleId), factory);
|
|
154
|
+
});
|
|
155
|
+
const patchNodes = [
|
|
156
|
+
buildBootstrapPatch({ MODULES: t.objectExpression(bootstrapModules) }),
|
|
157
|
+
...recentUpdatePatches.map(patch => {
|
|
158
|
+
const updateModules = patch.moduleFactories.map((moduleFactory) => {
|
|
159
|
+
const { moduleId, factory } = moduleFactory;
|
|
160
|
+
return t.objectProperty(t.stringLiteral(moduleId), factory);
|
|
161
|
+
});
|
|
162
|
+
return buildUpdatePatch({
|
|
163
|
+
FROM_HASH: patch.fromHash,
|
|
164
|
+
TO_HASH: patch.toHash,
|
|
165
|
+
MODULES: t.objectExpression(updateModules),
|
|
166
|
+
REMOVED_MODULES: t.arrayExpression(patch.removedModules.map(moduleId => t.stringLiteral(moduleId))),
|
|
167
|
+
});
|
|
168
|
+
}),
|
|
169
|
+
];
|
|
170
|
+
return (0, generator_1.default)(buildPatchAsset({ PATCHES: t.arrayExpression(patchNodes) })).code;
|
|
171
|
+
};
|
|
172
|
+
exports.generatePatchAssetSource = generatePatchAssetSource;
|
|
173
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/patch/utils.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taro-hmr-compile/plugin-webpack",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.8",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@babel/template": "^7.29.7",
|
|
45
45
|
"@babel/traverse": "^7.29.8",
|
|
46
46
|
"@babel/types": "^7.29.8",
|
|
47
|
-
"@taro-hmr-compile/core": "0.0.1-alpha.
|
|
47
|
+
"@taro-hmr-compile/core": "0.0.1-alpha.8",
|
|
48
48
|
"debug": "^4.4.3",
|
|
49
49
|
"tapable": "^2.3.3",
|
|
50
50
|
"webpack-sources": "^3.5.1"
|
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
import generator from '@babel/generator'
|
|
2
2
|
import * as parser from '@babel/parser'
|
|
3
3
|
import template from '@babel/template'
|
|
4
|
-
import traverse from '@babel/traverse'
|
|
4
|
+
import traverse, {NodePath} from '@babel/traverse'
|
|
5
5
|
import * as t from '@babel/types'
|
|
6
6
|
import type {LoaderDefinitionFunction} from 'webpack'
|
|
7
7
|
import webpack from 'webpack'
|
|
8
8
|
|
|
9
9
|
const CREATE_PAGE_CONFIG = 'createPageConfig'
|
|
10
|
+
|
|
10
11
|
const WITH_HMR_PAGE_CONFIG = 'withHmrPageConfig'
|
|
11
|
-
|
|
12
|
+
|
|
13
|
+
const TARO_RUNTIME_REQUEST = '@tarojs/runtime'
|
|
14
|
+
|
|
12
15
|
const LOG_REQUEST = require.resolve('../log')
|
|
13
16
|
|
|
17
|
+
const CORE_RUNTIME_REQUEST = require.resolve('@taro-hmr-compile/core/runtime')
|
|
18
|
+
|
|
14
19
|
export const injectAppHmrRuntime = (source: string, debugNamespaces = '') => {
|
|
20
|
+
|
|
21
|
+
|
|
15
22
|
const ast = parser.parse(source, {sourceType: 'module'})
|
|
16
23
|
|
|
17
24
|
const buildHmrCode = template.statements(`
|
|
@@ -40,7 +47,7 @@ export const injectAppHmrRuntime = (source: string, debugNamespaces = '') => {
|
|
|
40
47
|
traverse(ast, {
|
|
41
48
|
Program(path) {
|
|
42
49
|
const body = path.get('body')
|
|
43
|
-
const hasInjected = body.some(item => item.isImportDeclaration() && item.node.source
|
|
50
|
+
const hasInjected = body.some(item => item.isImportDeclaration() && t.isStringLiteral(item.node.source, {value: CORE_RUNTIME_REQUEST}))
|
|
44
51
|
if (hasInjected) return
|
|
45
52
|
|
|
46
53
|
const nodes = buildHmrCode()
|
|
@@ -55,54 +62,67 @@ export const injectAppHmrRuntime = (source: string, debugNamespaces = '') => {
|
|
|
55
62
|
}
|
|
56
63
|
|
|
57
64
|
export const transformPageConfig = (source: string, sourceFileName?: string) => {
|
|
65
|
+
|
|
58
66
|
const ast = parser.parse(source, {sourceType: 'module', plugins: ['typescript', 'jsx']})
|
|
59
|
-
|
|
67
|
+
|
|
68
|
+
const hasImportWithHmrPageConfig = (programPath: NodePath<t.Program>) => {
|
|
69
|
+
return programPath.node.body.some(node => {
|
|
70
|
+
if (!t.isImportDeclaration(node)) return false
|
|
71
|
+
if (!t.isStringLiteral(node.source, {value: CORE_RUNTIME_REQUEST})) return false
|
|
72
|
+
return node.specifiers.some(specifier => {
|
|
73
|
+
return t.isImportSpecifier(specifier) && t.isIdentifier(specifier.imported, {name: WITH_HMR_PAGE_CONFIG})
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
}
|
|
60
77
|
|
|
61
78
|
traverse(ast, {
|
|
62
79
|
Program(programPath) {
|
|
80
|
+
|
|
81
|
+
// 判断是否存在 createPageConfig 引用
|
|
63
82
|
const createPageConfigBinding = programPath.scope.getBinding(CREATE_PAGE_CONFIG)
|
|
64
83
|
if (!createPageConfigBinding || !createPageConfigBinding.path.isImportSpecifier()) return
|
|
65
|
-
const importDeclaration = createPageConfigBinding.path.parentPath
|
|
66
|
-
if (!importDeclaration.isImportDeclaration() || importDeclaration.node.source.value !== '@tarojs/runtime') return
|
|
67
84
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
85
|
+
// 判断 createPageConfig 引用是否来自 @tarojs/runtime
|
|
86
|
+
const {parentPath: createPageConfigImportDeclaration} = createPageConfigBinding.path
|
|
87
|
+
if (!t.isImportDeclaration(createPageConfigImportDeclaration.node)) return
|
|
88
|
+
if (!t.isStringLiteral(createPageConfigImportDeclaration.node.source, {value: TARO_RUNTIME_REQUEST})) return
|
|
71
89
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
transformed = true
|
|
81
|
-
variablePath.stop()
|
|
82
|
-
},
|
|
83
|
-
})
|
|
90
|
+
// 判断是否已经注入了 withHmrPageConfig
|
|
91
|
+
if (hasImportWithHmrPageConfig(programPath)) return
|
|
92
|
+
|
|
93
|
+
// 判断是否存在 withHmrPageConfig 引用
|
|
94
|
+
const hasWithHmrPageConfigBinding = programPath.scope.hasBinding(WITH_HMR_PAGE_CONFIG)
|
|
95
|
+
|
|
96
|
+
// 生成 withHmrPageConfig 的别名
|
|
97
|
+
const wrapperIdentifier = hasWithHmrPageConfigBinding ? programPath.scope.generateUidIdentifier(WITH_HMR_PAGE_CONFIG) : t.identifier(WITH_HMR_PAGE_CONFIG)
|
|
84
98
|
|
|
85
|
-
|
|
99
|
+
// 生成 runtime import
|
|
100
|
+
const runtimeImport = (() => {
|
|
101
|
+
if (!hasWithHmrPageConfigBinding) return template.statement(`import { ${WITH_HMR_PAGE_CONFIG} } from ${JSON.stringify(CORE_RUNTIME_REQUEST)};`)()
|
|
102
|
+
return template.statement(`import { ${WITH_HMR_PAGE_CONFIG} as %%WRAPPER%% } from ${JSON.stringify(CORE_RUNTIME_REQUEST)};`)({WRAPPER: wrapperIdentifier})
|
|
103
|
+
})()
|
|
86
104
|
|
|
87
|
-
|
|
88
|
-
|
|
105
|
+
programPath.traverse({
|
|
106
|
+
CallExpression(CallExpressionPath) {
|
|
107
|
+
const {node: CallExpressionNode} = CallExpressionPath
|
|
108
|
+
if (!t.isIdentifier(CallExpressionNode.callee, {name: CREATE_PAGE_CONFIG})) return
|
|
109
|
+
const [_, pageName] = CallExpressionNode.arguments
|
|
110
|
+
const wrappedPageConfig = template.expression(`%%WRAPPER%%(%%PAGE_CONFIG%%, %%PAGE_NAME%%)`)({
|
|
111
|
+
WRAPPER: wrapperIdentifier,
|
|
112
|
+
PAGE_CONFIG: CallExpressionNode,
|
|
113
|
+
PAGE_NAME: pageName,
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
if (!hasImportWithHmrPageConfig(programPath)) programPath.unshiftContainer('body', runtimeImport)
|
|
117
|
+
|
|
118
|
+
CallExpressionPath.replaceWith(wrappedPageConfig)
|
|
119
|
+
CallExpressionPath.skip()
|
|
120
|
+
}
|
|
89
121
|
})
|
|
90
|
-
|
|
91
|
-
? template.statement(`import { withHmrPageConfig } from ${JSON.stringify(CORE_RUNTIME_REQUEST)}`)()
|
|
92
|
-
: template.statement(`import { withHmrPageConfig as %%WRAPPER%% } from ${JSON.stringify(CORE_RUNTIME_REQUEST)}`)({WRAPPER: wrapperIdentifier})
|
|
93
|
-
if (!t.isImportDeclaration(runtimeImport)) throw new TypeError('Expected runtime import template to create an import declaration')
|
|
94
|
-
const hasNamespaceSpecifier = existingImport?.isImportDeclaration() && existingImport.node.specifiers.some(specifier => t.isImportNamespaceSpecifier(specifier))
|
|
95
|
-
|
|
96
|
-
if (existingImport?.isImportDeclaration() && !hasNamespaceSpecifier) {
|
|
97
|
-
existingImport.pushContainer('specifiers', runtimeImport.specifiers[0])
|
|
98
|
-
} else {
|
|
99
|
-
programPath.unshiftContainer('body', runtimeImport)
|
|
100
|
-
}
|
|
122
|
+
|
|
101
123
|
},
|
|
102
124
|
})
|
|
103
125
|
|
|
104
|
-
if (!transformed) return
|
|
105
|
-
|
|
106
126
|
return generator(ast, {sourceMaps: true, sourceFileName}, source).code
|
|
107
127
|
}
|
|
108
128
|
|
|
@@ -113,11 +133,9 @@ interface LoaderOptions {
|
|
|
113
133
|
|
|
114
134
|
const hmrCompilerLoader: LoaderDefinitionFunction<LoaderOptions> = function (source) {
|
|
115
135
|
const {miniType, debugNamespaces} = this.getOptions()
|
|
116
|
-
|
|
117
136
|
if (miniType === 'ENTRY') return injectAppHmrRuntime(source, debugNamespaces)
|
|
118
137
|
if (miniType === 'PAGE') return transformPageConfig(source, this.resourcePath) ?? source
|
|
119
|
-
|
|
120
|
-
throw new Error(`unsupported HMR entry miniType: ${miniType}`)
|
|
138
|
+
return source
|
|
121
139
|
}
|
|
122
140
|
|
|
123
141
|
export default hmrCompilerLoader
|
|
@@ -29,12 +29,16 @@ export interface HmrCompilerPluginOptions {
|
|
|
29
29
|
debugNamespaces?: string
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
type CompileRequested = SyncHook<[page: string]>
|
|
33
|
+
|
|
34
|
+
type ChunkModulesRendered = SyncHook<[source: string, isPageChunk: boolean]>
|
|
35
|
+
|
|
32
36
|
export interface HmrCompilerHooks {
|
|
33
|
-
compileRequested:
|
|
37
|
+
compileRequested: CompileRequested
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
export interface HmrCompilationHooks {
|
|
37
|
-
|
|
41
|
+
chunkModulesRendered: ChunkModulesRendered
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
export const applyPatchBeforeStartup = (source: Source, request: string) => {
|
|
@@ -67,21 +71,19 @@ export class HmrCompilerPlugin {
|
|
|
67
71
|
}
|
|
68
72
|
|
|
69
73
|
static getCompilerHooks(compiler: Compiler): HmrCompilerHooks {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
HmrCompilerPlugin.compilerHooksMap.set(compiler, hooks)
|
|
74
|
+
if (!HmrCompilerPlugin.compilerHooksMap.get(compiler)) {
|
|
75
|
+
const compileRequested: CompileRequested = new SyncHook(['page'])
|
|
76
|
+
HmrCompilerPlugin.compilerHooksMap.set(compiler, {compileRequested})
|
|
74
77
|
}
|
|
75
|
-
return
|
|
78
|
+
return HmrCompilerPlugin.compilerHooksMap.get(compiler)!
|
|
76
79
|
}
|
|
77
80
|
|
|
78
81
|
static getCompilationHooks(compilation: Compilation): HmrCompilationHooks {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
HmrCompilerPlugin.compilationHooksMap.set(compilation, hooks)
|
|
82
|
+
if (!HmrCompilerPlugin.compilationHooksMap.get(compilation)) {
|
|
83
|
+
const chunkModulesRendered: ChunkModulesRendered = new SyncHook(['source', 'isBootstrapChunk'])
|
|
84
|
+
HmrCompilerPlugin.compilationHooksMap.set(compilation, {chunkModulesRendered})
|
|
83
85
|
}
|
|
84
|
-
return
|
|
86
|
+
return HmrCompilerPlugin.compilationHooksMap.get(compilation)!
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
apply(compiler: Compiler) {
|
|
@@ -124,16 +126,16 @@ export class HmrCompilerPlugin {
|
|
|
124
126
|
|
|
125
127
|
const loaderOptions = {miniType: normalModule.miniType, debugNamespaces: this.options.debugNamespaces}
|
|
126
128
|
// Loader 从右向左执行;插到 taro-loader 左侧才能处理它生成的入口注册代码。
|
|
127
|
-
normalModule.loaders.splice(taroLoaderIndex, 0, {
|
|
129
|
+
normalModule.loaders.splice(taroLoaderIndex, 0, {loader: HMR_COMPILER_LOADER, options: loaderOptions})
|
|
128
130
|
},
|
|
129
131
|
)
|
|
130
132
|
|
|
131
133
|
// 只修改 Page Chunk 的 JS transport。Webpack 的 ModuleGraph / ChunkGraph 保持不变,
|
|
132
134
|
// 因而 hash、HMR diff 和 hot-update 仍以完整模块图为准。
|
|
133
135
|
javascriptHooks.renderChunk.tap({name: PLUGIN_NAME, stage: -10_000}, (source, {chunk}) => {
|
|
134
|
-
|
|
135
|
-
hmrHooks.
|
|
136
|
-
return new RawSource('{}')
|
|
136
|
+
const isBootstrapChunk = isPageChunk(chunk)
|
|
137
|
+
hmrHooks.chunkModulesRendered.call(source.source().toString(), isBootstrapChunk)
|
|
138
|
+
return isBootstrapChunk ? new RawSource('{}') : source
|
|
137
139
|
})
|
|
138
140
|
|
|
139
141
|
javascriptHooks.renderStartup.tap(PLUGIN_NAME, (source, _module, {chunk}) => {
|