@taro-hmr-compile/plugin-webpack 0.0.1-alpha.10
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/compile-state.d.ts +3 -0
- package/dist/compile/compile-state.js +21 -0
- package/dist/compile/compile-state.js.map +1 -0
- package/dist/compile/hmr-compiler-loader.d.ts +9 -0
- package/dist/compile/hmr-compiler-loader.js +199 -0
- package/dist/compile/hmr-compiler-loader.js.map +1 -0
- package/dist/compile/hmr-compiler-plugin.d.ts +46 -0
- package/dist/compile/hmr-compiler-plugin.js +173 -0
- package/dist/compile/hmr-compiler-plugin.js.map +1 -0
- package/dist/compile/lazy-compiler-loader.d.ts +18 -0
- package/dist/compile/lazy-compiler-loader.js +38 -0
- package/dist/compile/lazy-compiler-loader.js.map +1 -0
- package/dist/constants.d.ts +4 -0
- package/dist/constants.js +8 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +68 -0
- package/dist/index.js.map +1 -0
- package/dist/log.d.ts +3 -0
- package/dist/log.js +11 -0
- package/dist/log.js.map +1 -0
- package/dist/patch/hmr-patch-plugin.d.ts +17 -0
- package/dist/patch/hmr-patch-plugin.js +93 -0
- package/dist/patch/hmr-patch-plugin.js.map +1 -0
- package/dist/patch/hmr-patch-processor.d.ts +30 -0
- package/dist/patch/hmr-patch-processor.js +122 -0
- package/dist/patch/hmr-patch-processor.js.map +1 -0
- package/dist/patch/hmr-patch-runtime-plugin.d.ts +4 -0
- package/dist/patch/hmr-patch-runtime-plugin.js +113 -0
- package/dist/patch/hmr-patch-runtime-plugin.js.map +1 -0
- package/dist/patch/types.d.ts +16 -0
- package/dist/patch/types.js +3 -0
- package/dist/patch/types.js.map +1 -0
- package/dist/patch/utils.d.ts +28 -0
- package/dist/patch/utils.js +179 -0
- package/dist/patch/utils.js.map +1 -0
- package/dist/server/hmr-server-plugin.d.ts +13 -0
- package/dist/server/hmr-server-plugin.js +42 -0
- package/dist/server/hmr-server-plugin.js.map +1 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +25 -0
- package/dist/utils.js.map +1 -0
- package/package.json +58 -0
- package/src/compile/compile-state.ts +15 -0
- package/src/compile/hmr-compiler-loader.ts +177 -0
- package/src/compile/hmr-compiler-plugin.ts +233 -0
- package/src/compile/lazy-compiler-loader.ts +57 -0
- package/src/constants.ts +7 -0
- package/src/index.ts +81 -0
- package/src/log.ts +5 -0
- package/src/patch/hmr-patch-plugin.ts +111 -0
- package/src/patch/hmr-patch-processor.ts +169 -0
- package/src/patch/hmr-patch-runtime-plugin.ts +119 -0
- package/src/patch/types.ts +20 -0
- package/src/patch/utils.ts +179 -0
- package/src/server/hmr-server-plugin.ts +40 -0
- package/src/utils.ts +25 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,179 @@
|
|
|
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 Array.from(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 Array.from(moduleFactories.values());
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* 解析热更新产物
|
|
70
|
+
* @param opt
|
|
71
|
+
*/
|
|
72
|
+
const parseHotUpdateAssets = (opt) => {
|
|
73
|
+
const { manifests, scripts } = opt;
|
|
74
|
+
const moduleFactories = new Map();
|
|
75
|
+
const runtimeModules = [];
|
|
76
|
+
scripts.forEach(asset => {
|
|
77
|
+
const ast = (0, parser_1.parse)(asset.source.source().toString(), { sourceType: 'script' });
|
|
78
|
+
(0, traverse_1.default)(ast, {
|
|
79
|
+
CallExpression(nodePath) {
|
|
80
|
+
const { callee } = nodePath.node;
|
|
81
|
+
if (!t.isMemberExpression(callee) || !t.isIdentifier(callee.object, { name: 'wx' }))
|
|
82
|
+
return;
|
|
83
|
+
if (!t.isStringLiteral(callee.property) || !callee.property.value.startsWith('webpackHotUpdate'))
|
|
84
|
+
return;
|
|
85
|
+
const [, modules, runtime] = nodePath.node.arguments;
|
|
86
|
+
if (!t.isObjectExpression(modules))
|
|
87
|
+
return;
|
|
88
|
+
parseModuleFactories(modules).forEach(module => moduleFactories.set(module.moduleId, module));
|
|
89
|
+
if (t.isExpression(runtime))
|
|
90
|
+
runtimeModules.push(runtime);
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
const removedModules = new Set();
|
|
95
|
+
manifests.forEach((module) => {
|
|
96
|
+
const manifest = JSON.parse(module.source.source().toString());
|
|
97
|
+
const { m: tempRemoveModules = [] } = manifest;
|
|
98
|
+
tempRemoveModules.forEach(removedModule => removedModules.add(String(removedModule)));
|
|
99
|
+
}, []);
|
|
100
|
+
return { moduleFactories, runtimeModules, removedModules };
|
|
101
|
+
};
|
|
102
|
+
exports.parseHotUpdateAssets = parseHotUpdateAssets;
|
|
103
|
+
/**
|
|
104
|
+
* 解析 chunk 产物
|
|
105
|
+
* @param source
|
|
106
|
+
*/
|
|
107
|
+
const parseChunkAsset = (source) => {
|
|
108
|
+
const ast = (0, parser_1.parse)(`(${source})`, { sourceType: 'script' });
|
|
109
|
+
const [statement] = ast.program.body;
|
|
110
|
+
if (!t.isExpressionStatement(statement) || !t.isObjectExpression(statement.expression))
|
|
111
|
+
throw new Error('[taro-hmr-compile] Chunk 模块段不是对象表达式');
|
|
112
|
+
const moduleFactories = new Map();
|
|
113
|
+
parseModuleFactories(statement.expression).forEach(module => moduleFactories.set(module.moduleId, module));
|
|
114
|
+
return moduleFactories;
|
|
115
|
+
};
|
|
116
|
+
exports.parseChunkAsset = parseChunkAsset;
|
|
117
|
+
const mergeUpdatePatches = (basePatch, nextPatch) => {
|
|
118
|
+
if (basePatch.toHash !== nextPatch.fromHash)
|
|
119
|
+
throw new Error(`[taro-hmr-compile] 无法合并不连续的 HMR patch:${basePatch.toHash} !== ${nextPatch.fromHash}`);
|
|
120
|
+
const moduleFactories = new Map(basePatch.moduleFactories.map(moduleFactory => [moduleFactory.moduleId, moduleFactory]));
|
|
121
|
+
const removedModules = new Set(basePatch.removedModules);
|
|
122
|
+
nextPatch.moduleFactories.forEach(moduleFactory => {
|
|
123
|
+
const { moduleId } = moduleFactory;
|
|
124
|
+
moduleFactories.set(moduleId, moduleFactory);
|
|
125
|
+
removedModules.delete(moduleId);
|
|
126
|
+
});
|
|
127
|
+
nextPatch.removedModules.forEach(moduleId => {
|
|
128
|
+
moduleFactories.delete(moduleId);
|
|
129
|
+
removedModules.add(moduleId);
|
|
130
|
+
});
|
|
131
|
+
return {
|
|
132
|
+
type: 'update',
|
|
133
|
+
fromHash: basePatch.fromHash,
|
|
134
|
+
toHash: nextPatch.toHash,
|
|
135
|
+
moduleFactories: Array.from(moduleFactories.values()),
|
|
136
|
+
runtimeModules: [...basePatch.runtimeModules, ...nextPatch.runtimeModules],
|
|
137
|
+
removedModules: [...removedModules],
|
|
138
|
+
};
|
|
139
|
+
};
|
|
140
|
+
exports.mergeUpdatePatches = mergeUpdatePatches;
|
|
141
|
+
const generatePatchAssetSource = (opt) => {
|
|
142
|
+
const { bootstrapFactories, recentUpdatePatches } = opt;
|
|
143
|
+
const buildBootstrapPatch = template_1.default.expression(`({
|
|
144
|
+
type: 'bootstrap',
|
|
145
|
+
modules: MODULES
|
|
146
|
+
})`);
|
|
147
|
+
const buildUpdatePatch = template_1.default.expression(`({
|
|
148
|
+
type: 'update',
|
|
149
|
+
fromHash: "FROM_HASH",
|
|
150
|
+
toHash: "TO_HASH",
|
|
151
|
+
modules: MODULES,
|
|
152
|
+
runtimeModules: RUNTIME_MODULES,
|
|
153
|
+
removedModules: REMOVED_MODULES
|
|
154
|
+
})`);
|
|
155
|
+
const buildPatchAsset = template_1.default.program('module.exports = PATCHES;');
|
|
156
|
+
const bootstrapModules = Array.from(bootstrapFactories.values()).map((moduleFactory) => {
|
|
157
|
+
const { moduleId, factory } = moduleFactory;
|
|
158
|
+
return t.objectProperty(t.stringLiteral(moduleId), factory);
|
|
159
|
+
});
|
|
160
|
+
const patchNodes = [
|
|
161
|
+
buildBootstrapPatch({ MODULES: t.objectExpression(bootstrapModules) }),
|
|
162
|
+
...recentUpdatePatches.map(patch => {
|
|
163
|
+
const updateModules = patch.moduleFactories.map((moduleFactory) => {
|
|
164
|
+
const { moduleId, factory } = moduleFactory;
|
|
165
|
+
return t.objectProperty(t.stringLiteral(moduleId), factory);
|
|
166
|
+
});
|
|
167
|
+
return buildUpdatePatch({
|
|
168
|
+
FROM_HASH: patch.fromHash,
|
|
169
|
+
TO_HASH: patch.toHash,
|
|
170
|
+
MODULES: t.objectExpression(updateModules),
|
|
171
|
+
RUNTIME_MODULES: t.arrayExpression(patch.runtimeModules),
|
|
172
|
+
REMOVED_MODULES: t.arrayExpression(patch.removedModules.map(moduleId => t.stringLiteral(moduleId))),
|
|
173
|
+
});
|
|
174
|
+
}),
|
|
175
|
+
];
|
|
176
|
+
return (0, generator_1.default)(buildPatchAsset({ PATCHES: t.arrayExpression(patchNodes) })).code;
|
|
177
|
+
};
|
|
178
|
+
exports.generatePatchAssetSource = generatePatchAssetSource;
|
|
179
|
+
//# 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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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { HmrCompileServer } from '@taro-hmr-compile/core/compiler';
|
|
2
|
+
import type { Compiler } from 'webpack';
|
|
3
|
+
export interface HmrServerPluginOptions {
|
|
4
|
+
host?: string;
|
|
5
|
+
port?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare class HmrServerPlugin extends HmrCompileServer {
|
|
8
|
+
private readonly options;
|
|
9
|
+
private compiler?;
|
|
10
|
+
constructor(options: HmrServerPluginOptions);
|
|
11
|
+
apply(compiler: Compiler): void;
|
|
12
|
+
compile(page: string): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
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
|
+
exports.HmrServerPlugin = void 0;
|
|
13
|
+
const compiler_1 = require("@taro-hmr-compile/core/compiler");
|
|
14
|
+
const hmr_compiler_plugin_1 = require("../compile/hmr-compiler-plugin");
|
|
15
|
+
const log_1 = require("../log");
|
|
16
|
+
const serverLog = log_1.log.extend('HmrServerPlugin');
|
|
17
|
+
const PLUGIN_NAME = 'HmrServerPlugin';
|
|
18
|
+
class HmrServerPlugin extends compiler_1.HmrCompileServer {
|
|
19
|
+
constructor(options) {
|
|
20
|
+
super();
|
|
21
|
+
this.options = options;
|
|
22
|
+
}
|
|
23
|
+
apply(compiler) {
|
|
24
|
+
this.compiler = compiler;
|
|
25
|
+
compiler.hooks.beforeCompile.tapPromise(PLUGIN_NAME, () => __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
if (this.isServerRunning)
|
|
27
|
+
return;
|
|
28
|
+
const { port = 8080, host } = this.options;
|
|
29
|
+
serverLog('start server %O', { port, host });
|
|
30
|
+
yield this.start(port, host);
|
|
31
|
+
}));
|
|
32
|
+
compiler.hooks.watchClose.tap(PLUGIN_NAME, () => this.stop());
|
|
33
|
+
}
|
|
34
|
+
compile(page) {
|
|
35
|
+
serverLog('receive compile %s', page);
|
|
36
|
+
if (!this.compiler)
|
|
37
|
+
throw new Error('[taro-hmr-compile] Compiler 尚未初始化');
|
|
38
|
+
hmr_compiler_plugin_1.HmrCompilerPlugin.getCompilerHooks(this.compiler).compileRequested.call(page);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.HmrServerPlugin = HmrServerPlugin;
|
|
42
|
+
//# sourceMappingURL=hmr-server-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hmr-server-plugin.js","sourceRoot":"","sources":["../../src/server/hmr-server-plugin.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8DAAgE;AAEhE,wEAAgE;AAChE,gCAA2B;AAE3B,MAAM,SAAS,GAAG,SAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAA;AAE/C,MAAM,WAAW,GAAG,iBAAiB,CAAA;AAOrC,MAAa,eAAgB,SAAQ,2BAAgB;IAGjD,YAA6B,OAA+B;QACxD,KAAK,EAAE,CAAA;QADkB,YAAO,GAAP,OAAO,CAAwB;IAE5D,CAAC;IAED,KAAK,CAAC,QAAkB;QACpB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QAExB,QAAQ,CAAC,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,WAAW,EAAE,GAAS,EAAE;YAC5D,IAAI,IAAI,CAAC,eAAe;gBAAE,OAAM;YAChC,MAAM,EAAC,IAAI,GAAG,IAAI,EAAE,IAAI,EAAC,GAAG,IAAI,CAAC,OAAO,CAAA;YACxC,SAAS,CAAC,iBAAiB,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAA;YAC1C,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;QAChC,CAAC,CAAA,CAAC,CAAA;QAEF,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;IACjE,CAAC;IAEQ,OAAO,CAAC,IAAY;QACzB,SAAS,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAA;QACrC,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAA;QACxE,uCAAiB,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACjF,CAAC;CACJ;AAzBD,0CAyBC"}
|
package/dist/utils.d.ts
ADDED
package/dist/utils.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
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.getAllPages = exports.getAppConfig = void 0;
|
|
7
|
+
const helper_1 = require("@tarojs/helper");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const getAppConfig = (ctx) => {
|
|
10
|
+
const sourceRoot = ctx.initialConfig.sourceRoot || 'src';
|
|
11
|
+
const appConfigPath = (0, helper_1.resolveMainFilePath)(path_1.default.resolve(ctx.paths.appPath, sourceRoot, 'app.config'));
|
|
12
|
+
return (0, helper_1.readConfig)(appConfigPath, ctx.initialConfig);
|
|
13
|
+
};
|
|
14
|
+
exports.getAppConfig = getAppConfig;
|
|
15
|
+
const getAllPages = (appConfig) => {
|
|
16
|
+
var _a, _b, _c;
|
|
17
|
+
const subPackages = [
|
|
18
|
+
...((_a = appConfig.subPackages) !== null && _a !== void 0 ? _a : []),
|
|
19
|
+
...((_b = appConfig.subpackages) !== null && _b !== void 0 ? _b : []),
|
|
20
|
+
];
|
|
21
|
+
const subPackagePages = subPackages.flatMap(({ root, pages }) => pages.map(page => `${root.replace(/\/+$/, '')}/${page.replace(/^\/+/, '')}`));
|
|
22
|
+
return [...((_c = appConfig.pages) !== null && _c !== void 0 ? _c : []), ...subPackagePages];
|
|
23
|
+
};
|
|
24
|
+
exports.getAllPages = getAllPages;
|
|
25
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;;;;AAAA,2CAA8D;AAG9D,gDAAuB;AAEhB,MAAM,YAAY,GAAG,CAAC,GAAmB,EAAa,EAAE;IAC3D,MAAM,UAAU,GAAG,GAAG,CAAC,aAAa,CAAC,UAAU,IAAI,KAAK,CAAA;IAExD,MAAM,aAAa,GAAG,IAAA,4BAAmB,EAAC,cAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,CAAA;IAEpG,OAAO,IAAA,mBAAU,EAAC,aAAa,EAAE,GAAG,CAAC,aAAa,CAAC,CAAA;AACvD,CAAC,CAAA;AANY,QAAA,YAAY,gBAMxB;AAEM,MAAM,WAAW,GAAG,CAAC,SAAoB,EAAY,EAAE;;IAC1D,MAAM,WAAW,GAAG;QAChB,GAAG,CAAC,MAAA,SAAS,CAAC,WAAW,mCAAI,EAAE,CAAC;QAChC,GAAG,CAAC,MAAA,SAAS,CAAC,WAAW,mCAAI,EAAE,CAAC;KACnC,CAAA;IAED,MAAM,eAAe,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,EAAC,IAAI,EAAE,KAAK,EAAC,EAAE,EAAE,CAC1D,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,CAC/E,CAAA;IAED,OAAO,CAAC,GAAG,CAAC,MAAA,SAAS,CAAC,KAAK,mCAAI,EAAE,CAAC,EAAE,GAAG,eAAe,CAAC,CAAA;AAC3D,CAAC,CAAA;AAXY,QAAA,WAAW,eAWvB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@taro-hmr-compile/plugin-webpack",
|
|
3
|
+
"version": "0.0.1-alpha.10",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"keywords": [],
|
|
8
|
+
"author": "yu.pan",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"devEngines": {
|
|
14
|
+
"packageManager": {
|
|
15
|
+
"name": "pnpm",
|
|
16
|
+
"version": "11.24.0",
|
|
17
|
+
"onFail": "download"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"type": "commonjs",
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"@tarojs/components": ">=3.0.0",
|
|
23
|
+
"@tarojs/helper": ">=3.0.0",
|
|
24
|
+
"@tarojs/service": ">=3.0.0",
|
|
25
|
+
"@tarojs/taro": ">=3.0.0",
|
|
26
|
+
"webpack": "^5.0.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@tarojs/helper": "4.0.8",
|
|
30
|
+
"@tarojs/service": "^4.0.8",
|
|
31
|
+
"@tarojs/taro": "^4.0.8",
|
|
32
|
+
"@types/babel__core": "^7.20.5",
|
|
33
|
+
"@types/babel__generator": "^7.27.0",
|
|
34
|
+
"@types/babel__template": "^7.4.4",
|
|
35
|
+
"@types/babel__traverse": "^7.28.0",
|
|
36
|
+
"@types/debug": "^4.1.13",
|
|
37
|
+
"@types/lodash": "^4.17.26",
|
|
38
|
+
"@types/node": "^22.20.1",
|
|
39
|
+
"typescript": "^5.8.2",
|
|
40
|
+
"webpack": "^5.110.3"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@babel/generator": "^7.29.8",
|
|
44
|
+
"@babel/parser": "^7.29.8",
|
|
45
|
+
"@babel/template": "^7.29.7",
|
|
46
|
+
"@babel/traverse": "^7.29.8",
|
|
47
|
+
"@babel/types": "^7.29.8",
|
|
48
|
+
"@taro-hmr-compile/core": "0.0.1-alpha.10",
|
|
49
|
+
"debug": "^4.4.3",
|
|
50
|
+
"lodash": "^4.18.1",
|
|
51
|
+
"tapable": "^2.3.3",
|
|
52
|
+
"webpack-sources": "^3.5.1"
|
|
53
|
+
},
|
|
54
|
+
"scripts": {
|
|
55
|
+
"build": "tsc",
|
|
56
|
+
"test": "pnpm run build && node --test test/*.test.cjs"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const compiledPagesByApp = new Map<string, Set<string>>()
|
|
2
|
+
|
|
3
|
+
export const markPageCompiled = (appPath: string, page: string) => {
|
|
4
|
+
const compiledPages = compiledPagesByApp.get(appPath) ?? new Set<string>()
|
|
5
|
+
compiledPages.add(page)
|
|
6
|
+
compiledPagesByApp.set(appPath, compiledPages)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const isPageCompiled = (appPath: string, page: string) => {
|
|
10
|
+
return compiledPagesByApp.get(appPath)?.has(page) ?? false
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const clearCompiledPages = (appPath: string) => {
|
|
14
|
+
compiledPagesByApp.delete(appPath)
|
|
15
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import generator from '@babel/generator'
|
|
2
|
+
import * as parser from '@babel/parser'
|
|
3
|
+
import template from '@babel/template'
|
|
4
|
+
import traverse, {NodePath} from '@babel/traverse'
|
|
5
|
+
import * as t from '@babel/types'
|
|
6
|
+
import type {LoaderDefinitionFunction} from 'webpack'
|
|
7
|
+
import webpack from 'webpack'
|
|
8
|
+
|
|
9
|
+
const CREATE_PAGE_CONFIG = 'createPageConfig'
|
|
10
|
+
|
|
11
|
+
const WITH_HMR_PAGE_CONFIG = 'withHmrPageConfig'
|
|
12
|
+
|
|
13
|
+
const TARO_RUNTIME_REQUEST = '@tarojs/runtime'
|
|
14
|
+
|
|
15
|
+
const LOG_REQUEST = require.resolve('../log')
|
|
16
|
+
|
|
17
|
+
const CORE_RUNTIME_REQUEST = require.resolve('@taro-hmr-compile/core/runtime')
|
|
18
|
+
|
|
19
|
+
export const injectAppHmrRuntime = (source: string, debugNamespaces = '') => {
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
const ast = parser.parse(source, {sourceType: 'module'})
|
|
23
|
+
|
|
24
|
+
const buildHmrCode = template.statements(`
|
|
25
|
+
import { updatePatchContext, mergePatches, enableLog as enableHmrCoreLog } from ${JSON.stringify(CORE_RUNTIME_REQUEST)}
|
|
26
|
+
import { log, enableLog as enableHmrWebpackLog } from ${JSON.stringify(LOG_REQUEST)}
|
|
27
|
+
enableHmrCoreLog(${JSON.stringify(debugNamespaces)})
|
|
28
|
+
enableHmrWebpackLog(${JSON.stringify(debugNamespaces)})
|
|
29
|
+
globalThis.log = log.extend('runtime')
|
|
30
|
+
updatePatchContext.initialize(${webpack.RuntimeGlobals.getFullHash}())
|
|
31
|
+
globalThis.miniHmrApplyPatch = async (patches)=>{
|
|
32
|
+
let transaction
|
|
33
|
+
try {
|
|
34
|
+
const { miniHmr } = __webpack_require__
|
|
35
|
+
const bootstrapPatch = patches.find(patch => patch.type === 'bootstrap')
|
|
36
|
+
const shouldApplyBootstrapPatch = miniHmr.shouldApplyBootstrapPatch(bootstrapPatch)
|
|
37
|
+
const currentHash = ${webpack.RuntimeGlobals.getFullHash}()
|
|
38
|
+
const updatePatch = mergePatches(currentHash, patches)
|
|
39
|
+
|
|
40
|
+
if (shouldApplyBootstrapPatch) miniHmr.applyBootstrapPatch(bootstrapPatch)
|
|
41
|
+
if (!updatePatch) return
|
|
42
|
+
|
|
43
|
+
transaction = updatePatchContext.beginTransaction({fromHash: currentHash,toHash: updatePatch.toHash})
|
|
44
|
+
await miniHmr.applyUpdatePatch(updatePatch)
|
|
45
|
+
updatePatchContext.completeTransaction(transaction.id)
|
|
46
|
+
} catch (error) {
|
|
47
|
+
if (transaction) updatePatchContext.abortTransaction(transaction.id)
|
|
48
|
+
console.error('[taro-hmr-compile] patch apply failed', error)
|
|
49
|
+
return Promise.resolve()
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
`, {placeholderPattern: false})
|
|
53
|
+
|
|
54
|
+
traverse(ast, {
|
|
55
|
+
Program(path) {
|
|
56
|
+
const body = path.get('body')
|
|
57
|
+
const hasInjected = body.some(item => item.isImportDeclaration() && t.isStringLiteral(item.node.source, {value: CORE_RUNTIME_REQUEST}))
|
|
58
|
+
if (hasInjected) return
|
|
59
|
+
|
|
60
|
+
const nodes = buildHmrCode()
|
|
61
|
+
const lastImport = [...body].reverse().find(item => item.isImportDeclaration())
|
|
62
|
+
|
|
63
|
+
if (lastImport) lastImport.insertAfter(nodes)
|
|
64
|
+
if (!lastImport) path.unshiftContainer('body', nodes)
|
|
65
|
+
},
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
return generator(ast).code
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const transformPageConfig = (source: string, sourceFileName?: string) => {
|
|
72
|
+
|
|
73
|
+
const ast = parser.parse(source, {sourceType: 'module', plugins: ['typescript', 'jsx']})
|
|
74
|
+
|
|
75
|
+
const hasImportWithHmrPageConfig = (programPath: NodePath<t.Program>) => {
|
|
76
|
+
return programPath.node.body.some(node => {
|
|
77
|
+
if (!t.isImportDeclaration(node)) return false
|
|
78
|
+
if (!t.isStringLiteral(node.source, {value: CORE_RUNTIME_REQUEST})) return false
|
|
79
|
+
return node.specifiers.some(specifier => {
|
|
80
|
+
return t.isImportSpecifier(specifier) && t.isIdentifier(specifier.imported, {name: WITH_HMR_PAGE_CONFIG})
|
|
81
|
+
})
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const isHotAcceptCall = (node: t.Node | null | undefined) => {
|
|
86
|
+
if (!t.isCallExpression(node)) return false
|
|
87
|
+
const {callee} = node
|
|
88
|
+
if (!t.isMemberExpression(callee) || !t.isIdentifier(callee.property, {name: 'accept'})) return false
|
|
89
|
+
const hot = callee.object
|
|
90
|
+
return t.isMemberExpression(hot) && t.isIdentifier(hot.object, {name: 'module'}) && t.isIdentifier(hot.property, {name: 'hot'})
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const hasHotAccept = (programPath: NodePath<t.Program>) => {
|
|
94
|
+
return programPath.node.body.some(statement => {
|
|
95
|
+
if (t.isExpressionStatement(statement)) return isHotAcceptCall(statement.expression)
|
|
96
|
+
if (!t.isIfStatement(statement)) return false
|
|
97
|
+
|
|
98
|
+
const {consequent} = statement
|
|
99
|
+
if (t.isExpressionStatement(consequent)) return isHotAcceptCall(consequent.expression)
|
|
100
|
+
if (!t.isBlockStatement(consequent)) return false
|
|
101
|
+
return consequent.body.some(node => t.isExpressionStatement(node) && isHotAcceptCall(node.expression))
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
traverse(ast, {
|
|
106
|
+
Program(programPath) {
|
|
107
|
+
|
|
108
|
+
// 判断是否存在 createPageConfig 引用
|
|
109
|
+
const createPageConfigBinding = programPath.scope.getBinding(CREATE_PAGE_CONFIG)
|
|
110
|
+
if (!createPageConfigBinding || !createPageConfigBinding.path.isImportSpecifier()) return
|
|
111
|
+
|
|
112
|
+
// 判断 createPageConfig 引用是否来自 @tarojs/runtime
|
|
113
|
+
const {parentPath: createPageConfigImportDeclaration} = createPageConfigBinding.path
|
|
114
|
+
if (!t.isImportDeclaration(createPageConfigImportDeclaration.node)) return
|
|
115
|
+
if (!t.isStringLiteral(createPageConfigImportDeclaration.node.source, {value: TARO_RUNTIME_REQUEST})) return
|
|
116
|
+
|
|
117
|
+
// 判断是否已经注入了 withHmrPageConfig
|
|
118
|
+
if (hasImportWithHmrPageConfig(programPath)) return
|
|
119
|
+
|
|
120
|
+
// 判断是否存在 withHmrPageConfig 引用
|
|
121
|
+
const hasWithHmrPageConfigBinding = programPath.scope.hasBinding(WITH_HMR_PAGE_CONFIG)
|
|
122
|
+
const shouldInjectHotAccept = !hasHotAccept(programPath)
|
|
123
|
+
|
|
124
|
+
// 生成 withHmrPageConfig 的别名
|
|
125
|
+
const wrapperIdentifier = hasWithHmrPageConfigBinding ? programPath.scope.generateUidIdentifier(WITH_HMR_PAGE_CONFIG) : t.identifier(WITH_HMR_PAGE_CONFIG)
|
|
126
|
+
|
|
127
|
+
// 生成 runtime import
|
|
128
|
+
const runtimeImport = (() => {
|
|
129
|
+
if (!hasWithHmrPageConfigBinding) return template.statement(`import { ${WITH_HMR_PAGE_CONFIG} } from ${JSON.stringify(CORE_RUNTIME_REQUEST)};`)()
|
|
130
|
+
return template.statement(`import { ${WITH_HMR_PAGE_CONFIG} as %%WRAPPER%% } from ${JSON.stringify(CORE_RUNTIME_REQUEST)};`)({WRAPPER: wrapperIdentifier})
|
|
131
|
+
})()
|
|
132
|
+
|
|
133
|
+
let transformedPageConfig = false
|
|
134
|
+
|
|
135
|
+
programPath.traverse({
|
|
136
|
+
CallExpression(CallExpressionPath) {
|
|
137
|
+
const {node: CallExpressionNode} = CallExpressionPath
|
|
138
|
+
if (!t.isIdentifier(CallExpressionNode.callee, {name: CREATE_PAGE_CONFIG})) return
|
|
139
|
+
const [_, pageName] = CallExpressionNode.arguments
|
|
140
|
+
const wrappedPageConfig = template.expression(`%%WRAPPER%%(%%PAGE_CONFIG%%, %%PAGE_NAME%%, typeof module !== 'undefined' ? module.hot : undefined)`)({
|
|
141
|
+
WRAPPER: wrapperIdentifier,
|
|
142
|
+
PAGE_CONFIG: CallExpressionNode,
|
|
143
|
+
PAGE_NAME: pageName,
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
CallExpressionPath.replaceWith(wrappedPageConfig)
|
|
147
|
+
CallExpressionPath.skip()
|
|
148
|
+
transformedPageConfig = true
|
|
149
|
+
}
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
if (!transformedPageConfig) return
|
|
153
|
+
|
|
154
|
+
programPath.unshiftContainer('body', runtimeImport)
|
|
155
|
+
if (shouldInjectHotAccept) {
|
|
156
|
+
programPath.pushContainer('body', template.statement(`if (typeof module !== 'undefined' && module.hot) module.hot.accept();`)())
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
},
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
return generator(ast, {sourceMaps: true, sourceFileName}, source).code
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
interface LoaderOptions {
|
|
166
|
+
miniType: 'PAGE' | 'ENTRY'
|
|
167
|
+
debugNamespaces?: string
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const hmrCompilerLoader: LoaderDefinitionFunction<LoaderOptions> = function (source) {
|
|
171
|
+
const {miniType, debugNamespaces} = this.getOptions()
|
|
172
|
+
if (miniType === 'ENTRY') return injectAppHmrRuntime(source, debugNamespaces)
|
|
173
|
+
if (miniType === 'PAGE') return transformPageConfig(source, this.resourcePath) ?? source
|
|
174
|
+
return source
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export default hmrCompilerLoader
|