@taro-hmr-compile/plugin-webpack 0.0.1-alpha.3

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.
Files changed (46) hide show
  1. package/dist/compile/compile-state.d.ts +3 -0
  2. package/dist/compile/compile-state.js +21 -0
  3. package/dist/compile/compile-state.js.map +1 -0
  4. package/dist/compile/hmr-compile-loader.d.ts +11 -0
  5. package/dist/compile/hmr-compile-loader.js +52 -0
  6. package/dist/compile/hmr-compile-loader.js.map +1 -0
  7. package/dist/compile/hmr-compiler-plugin.d.ts +38 -0
  8. package/dist/compile/hmr-compiler-plugin.js +158 -0
  9. package/dist/compile/hmr-compiler-plugin.js.map +1 -0
  10. package/dist/compile/inject-app-hmr-runtime.d.ts +1 -0
  11. package/dist/compile/inject-app-hmr-runtime.js +46 -0
  12. package/dist/compile/inject-app-hmr-runtime.js.map +1 -0
  13. package/dist/constants.d.ts +3 -0
  14. package/dist/constants.js +7 -0
  15. package/dist/constants.js.map +1 -0
  16. package/dist/index.d.ts +8 -0
  17. package/dist/index.js +49 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/patch/hmr-patch-manager.d.ts +30 -0
  20. package/dist/patch/hmr-patch-manager.js +75 -0
  21. package/dist/patch/hmr-patch-manager.js.map +1 -0
  22. package/dist/patch/hmr-patch-plugin.d.ts +16 -0
  23. package/dist/patch/hmr-patch-plugin.js +239 -0
  24. package/dist/patch/hmr-patch-plugin.js.map +1 -0
  25. package/dist/patch/hmr-patch-runtime-plugin.d.ts +4 -0
  26. package/dist/patch/hmr-patch-runtime-plugin.js +142 -0
  27. package/dist/patch/hmr-patch-runtime-plugin.js.map +1 -0
  28. package/dist/server/hmr-server-plugin.d.ts +13 -0
  29. package/dist/server/hmr-server-plugin.js +29 -0
  30. package/dist/server/hmr-server-plugin.js.map +1 -0
  31. package/dist/utils.d.ts +4 -0
  32. package/dist/utils.js +25 -0
  33. package/dist/utils.js.map +1 -0
  34. package/package.json +51 -0
  35. package/src/compile/compile-state.ts +15 -0
  36. package/src/compile/hmr-compile-loader.ts +72 -0
  37. package/src/compile/hmr-compiler-plugin.ts +191 -0
  38. package/src/compile/inject-app-hmr-runtime.ts +44 -0
  39. package/src/constants.ts +5 -0
  40. package/src/index.ts +67 -0
  41. package/src/patch/hmr-patch-manager.ts +102 -0
  42. package/src/patch/hmr-patch-plugin.ts +237 -0
  43. package/src/patch/hmr-patch-runtime-plugin.ts +150 -0
  44. package/src/server/hmr-server-plugin.ts +34 -0
  45. package/src/utils.ts +25 -0
  46. package/tsconfig.json +21 -0
@@ -0,0 +1,150 @@
1
+ import {parse} from '@babel/parser'
2
+ import generate from '@babel/generator'
3
+ import webpack from 'webpack'
4
+
5
+ const PLUGIN_NAME = 'HmrPatchRuntimePlugin'
6
+
7
+ const hotRuntimeCode = `
8
+ var applyQueue = Promise.resolve();
9
+ var applySequence = 0;
10
+
11
+ ${webpack.RuntimeGlobals.require}.miniHmr = {
12
+ applyPatch: function(patch) {
13
+ if (!patch) return Promise.resolve();
14
+
15
+ var applyId = ++applySequence;
16
+ var enqueueHash = ${webpack.RuntimeGlobals.getFullHash}();
17
+ // 微信要求 Page() 在页面脚本求值期间同步注册。bootstrap 只补齐缺失工厂,
18
+ // 不会覆盖现有模块;必须在 Page Chunk startup 继续执行前同步完成。
19
+ if (patch.type === 'bootstrap') {
20
+ var installedModules = [];
21
+ Object.keys(patch.modules).forEach(function(moduleId) {
22
+ if (!Object.prototype.hasOwnProperty.call(${webpack.RuntimeGlobals.moduleFactories}, moduleId)) {
23
+ ${webpack.RuntimeGlobals.moduleFactories}[moduleId] = patch.modules[moduleId];
24
+ installedModules.push(moduleId);
25
+ }
26
+ });
27
+ console.log('[taro-hmr-compile] bootstrap patch installed', {
28
+ applyId: applyId,
29
+ installedModules: installedModules
30
+ });
31
+ return Promise.resolve(installedModules);
32
+ }
33
+
34
+ console.log('[taro-hmr-compile] patch enqueued', {
35
+ applyId: applyId,
36
+ type: patch.type,
37
+ runtimeHash: enqueueHash,
38
+ fromHash: patch.fromHash,
39
+ toHash: patch.toHash
40
+ });
41
+
42
+ var task = applyQueue.then(function() {
43
+ var runtimeHash = ${webpack.RuntimeGlobals.getFullHash}();
44
+ console.log('[taro-hmr-compile] patch dequeued', {
45
+ applyId: applyId,
46
+ runtimeHash: runtimeHash,
47
+ fromHash: patch.fromHash,
48
+ toHash: patch.toHash,
49
+ isStaleBaseline: runtimeHash !== patch.fromHash
50
+ });
51
+
52
+ if (runtimeHash === patch.toHash) {
53
+ console.log('[taro-hmr-compile] patch skipped at target hash', {
54
+ applyId: applyId,
55
+ runtimeHash: runtimeHash
56
+ });
57
+ return;
58
+ }
59
+
60
+ currentUpdateApplyHandlers = [];
61
+
62
+ ${webpack.RuntimeGlobals.require}.miniHmr.preparePatch(
63
+ patch,
64
+ currentUpdateApplyHandlers
65
+ );
66
+
67
+ return setStatus('ready')
68
+ .then(function() {
69
+ return hotApply();
70
+ })
71
+ .then(function(updatedModules) {
72
+ ${webpack.RuntimeGlobals.getFullHash} = function() {
73
+ return patch.toHash;
74
+ };
75
+
76
+ console.log('[taro-hmr-compile] patch applied', {
77
+ applyId: applyId,
78
+ fromHash: patch.fromHash,
79
+ toHash: patch.toHash,
80
+ updatedModules: updatedModules
81
+ });
82
+
83
+ return updatedModules;
84
+ });
85
+ });
86
+
87
+ // 单次失败不能阻塞后续 patch
88
+ applyQueue = task.catch(function() {});
89
+
90
+ return task;
91
+ }
92
+ };
93
+ `;
94
+
95
+ const chunkLoadingRuntimeCode = `
96
+ ${webpack.RuntimeGlobals.require}.miniHmr.preparePatch = function(patch, applyHandlers) {
97
+ currentUpdateChunks = {};
98
+ currentUpdate = Object.assign({}, patch.modules);
99
+ currentUpdateRemovedChunks = [];
100
+ currentUpdateRuntime = [];
101
+
102
+ if (patch.removedModules) {
103
+ patch.removedModules.forEach(function(moduleId) {
104
+ currentUpdate[moduleId] = false;
105
+ });
106
+ }
107
+
108
+ applyHandlers.push(applyHandler);
109
+ };
110
+ `
111
+
112
+ const injectRuntime = (source: string, injectedCode: string) => {
113
+ const runtime = parse(source, {sourceType: 'script'})
114
+ const injected = parse(injectedCode, {sourceType: 'script'})
115
+
116
+ runtime.program.body.push(...injected.program.body)
117
+
118
+ return generate(runtime).code
119
+ }
120
+
121
+ export class HmrPatchRuntimePlugin {
122
+ apply(compiler: webpack.Compiler) {
123
+ compiler.hooks.thisCompilation.tap(
124
+ PLUGIN_NAME,
125
+ compilation => {
126
+ compilation.hooks.runtimeModule.tap(
127
+ PLUGIN_NAME,
128
+ runtimeModule => {
129
+ const injectedCode = {
130
+ HotModuleReplacementRuntimeModule: hotRuntimeCode,
131
+ JsonpChunkLoadingRuntimeModule: chunkLoadingRuntimeCode,
132
+ }[runtimeModule.constructor.name]
133
+
134
+ if (!injectedCode) return
135
+
136
+ const generate = runtimeModule.generate.bind(runtimeModule)
137
+
138
+ runtimeModule.generate = () => {
139
+ const source = generate()
140
+
141
+ if (!source) return source
142
+
143
+ return injectRuntime(source, injectedCode)
144
+ }
145
+ },
146
+ )
147
+ },
148
+ )
149
+ }
150
+ }
@@ -0,0 +1,34 @@
1
+ import {HmrCompileServer} from '@taro-hmr-compile/core/compiler'
2
+ import type {Compiler} from 'webpack'
3
+ import {HmrCompilerPlugin} from '../compile/hmr-compiler-plugin'
4
+
5
+ const PLUGIN_NAME = 'HmrServerPlugin'
6
+
7
+ export interface HmrServerPluginOptions {
8
+ host?: string
9
+ port?: number
10
+ }
11
+
12
+ export class HmrServerPlugin extends HmrCompileServer {
13
+ private compiler?: Compiler
14
+
15
+ constructor(private readonly options: HmrServerPluginOptions) {
16
+ super()
17
+ }
18
+
19
+ apply(compiler: Compiler) {
20
+ this.compiler = compiler
21
+
22
+ compiler.hooks.afterEmit.tap(PLUGIN_NAME, compilation => {
23
+ const isSuccessful = compilation.errors.length === 0 && Boolean(compilation.hash)
24
+ if (isSuccessful && !this.isServerRunning) this.start(this.options.port ?? 8080, this.options.host)
25
+ })
26
+
27
+ compiler.hooks.watchClose.tap(PLUGIN_NAME, () => this.stop())
28
+ }
29
+
30
+ override compile(page: string) {
31
+ if (!this.compiler) throw new Error('[taro-hmr-compile] Compiler 尚未初始化')
32
+ HmrCompilerPlugin.getCompilerHooks(this.compiler).compileRequested.call(page)
33
+ }
34
+ }
package/src/utils.ts ADDED
@@ -0,0 +1,25 @@
1
+ import {readConfig, resolveMainFilePath} from '@tarojs/helper'
2
+ import type {IPluginContext} from '@tarojs/service'
3
+ import type {AppConfig} from '@tarojs/taro'
4
+ import path from 'path'
5
+
6
+ export const getAppConfig = (ctx: IPluginContext): AppConfig => {
7
+ const sourceRoot = ctx.initialConfig.sourceRoot || 'src'
8
+
9
+ const appConfigPath = resolveMainFilePath(path.resolve(ctx.paths.appPath, sourceRoot, 'app.config'))
10
+
11
+ return readConfig(appConfigPath, ctx.initialConfig)
12
+ }
13
+
14
+ export const getAllPages = (appConfig: AppConfig): string[] => {
15
+ const subPackages = [
16
+ ...(appConfig.subPackages ?? []),
17
+ ...(appConfig.subpackages ?? []),
18
+ ]
19
+
20
+ const subPackagePages = subPackages.flatMap(({root, pages}) =>
21
+ pages.map(page => `${root.replace(/\/+$/, '')}/${page.replace(/^\/+/, '')}`)
22
+ )
23
+
24
+ return [...(appConfig.pages ?? []), ...subPackagePages]
25
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,21 @@
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
+
21
+ }