vite-plugin-taro 0.3.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +44 -0
- package/README.md +22 -497
- package/client.d.ts +9 -0
- package/dist/node/plugins/client/client-taro.d.ts +4 -0
- package/dist/node/plugins/client/client-taro.js +19 -0
- package/dist/node/plugins/client/constant.d.ts +4 -0
- package/dist/node/plugins/client/constant.js +4 -0
- package/dist/node/plugins/conditional/conditional-directives.d.ts +4 -0
- package/dist/node/plugins/{conditional-directives.js → conditional/conditional-directives.js} +27 -11
- package/dist/node/plugins/css/plugins.d.ts +4 -0
- package/dist/node/plugins/css/plugins.js +84 -0
- package/dist/node/plugins/h5/constant.d.ts +2 -0
- package/dist/node/plugins/h5/constant.js +3 -0
- package/dist/node/plugins/h5/plugins.d.ts +4 -0
- package/dist/node/plugins/h5/plugins.js +161 -0
- package/dist/node/plugins/h5/resolver/module-resolver.d.ts +14 -0
- package/dist/node/plugins/h5/resolver/module-resolver.js +19 -0
- package/dist/node/plugins/h5/transform-app.d.ts +10 -0
- package/dist/node/plugins/h5/transform-app.js +48 -0
- package/dist/node/plugins/wx/dev/dev-host.d.ts +15 -0
- package/dist/node/plugins/wx/dev/dev-host.js +352 -0
- package/dist/node/plugins/wx/dev/hmr-files.d.ts +28 -0
- package/dist/node/plugins/wx/dev/hmr-files.js +34 -0
- package/dist/node/plugins/wx/dev/patch-publisher.d.ts +22 -0
- package/dist/node/plugins/wx/dev/patch-publisher.js +40 -0
- package/dist/node/plugins/wx/dev/plugin.d.ts +7 -0
- package/dist/node/plugins/wx/dev/plugin.js +73 -0
- package/dist/node/plugins/wx/dev/react-refresh.d.ts +20 -0
- package/dist/node/plugins/wx/dev/react-refresh.js +198 -0
- package/dist/node/plugins/wx/module.d.ts +45 -0
- package/dist/node/plugins/wx/module.js +66 -0
- package/dist/node/plugins/wx/native/compile-native-component-interface.d.ts +21 -0
- package/dist/node/plugins/wx/native/compile-native-component-interface.js +29 -0
- package/dist/node/plugins/wx/native/create-native-component-output.d.ts +15 -0
- package/dist/node/plugins/wx/native/create-native-component-output.js +39 -0
- package/dist/node/plugins/wx/native/native-component-assets.d.ts +26 -0
- package/dist/node/plugins/wx/native/native-component-assets.js +76 -0
- package/dist/node/plugins/wx/native/native-component-interface.d.ts +12 -0
- package/dist/node/plugins/wx/native/native-component-interface.js +201 -0
- package/dist/node/plugins/wx/output/files.d.ts +12 -0
- package/dist/node/plugins/wx/output/files.js +12 -0
- package/dist/node/plugins/wx/output/json.d.ts +14 -0
- package/dist/node/plugins/wx/output/json.js +52 -0
- package/dist/node/plugins/wx/output/relative-root.d.ts +2 -0
- package/dist/node/plugins/wx/output/relative-root.js +6 -0
- package/dist/node/plugins/wx/output/templates.d.ts +7 -0
- package/dist/node/plugins/wx/output/templates.js +100 -0
- package/dist/node/plugins/wx/placement/placer.d.ts +78 -0
- package/dist/node/plugins/wx/placement/placer.js +145 -0
- package/dist/node/plugins/wx/placement/plan.d.ts +46 -0
- package/dist/node/plugins/wx/placement/plan.js +210 -0
- package/dist/node/plugins/wx/plugins.d.ts +4 -0
- package/dist/node/plugins/wx/plugins.js +137 -0
- package/dist/node/plugins/wx/render/capsule-wrapper.d.ts +3 -0
- package/dist/node/plugins/wx/render/capsule-wrapper.js +64 -0
- package/dist/node/plugins/wx/render/capsule.d.ts +4 -0
- package/dist/node/plugins/wx/render/capsule.js +13 -0
- package/dist/node/plugins/wx/render/native.d.ts +9 -0
- package/dist/node/plugins/wx/render/native.js +45 -0
- package/dist/node/plugins/wx/render/transport.d.ts +17 -0
- package/dist/node/plugins/wx/render/transport.js +94 -0
- package/dist/node/plugins/wx/resolve/resolver.d.ts +7 -0
- package/dist/node/plugins/wx/resolve/resolver.js +86 -0
- package/dist/node/plugins/wx/resolve/specialize-bootstrap.d.ts +9 -0
- package/dist/node/plugins/wx/resolve/specialize-bootstrap.js +9 -0
- package/dist/node/plugins/wx/resolve/specialize-page-capsule.d.ts +9 -0
- package/dist/node/plugins/wx/resolve/specialize-page-capsule.js +11 -0
- package/dist/node/utils/constant.d.ts +1 -0
- package/dist/node/utils/constant.js +1 -0
- package/dist/node/utils/memoize.d.ts +122 -0
- package/dist/node/utils/memoize.js +86 -0
- package/dist/node/utils/modules.d.ts +20 -24
- package/dist/node/utils/modules.js +21 -34
- package/dist/node/utils/once.d.ts +10 -0
- package/dist/node/utils/once.js +20 -0
- package/dist/node/utils/packages.d.ts +1 -0
- package/dist/node/utils/packages.js +1 -1
- package/dist/node/utils/project-config.d.ts +3 -0
- package/dist/node/utils/project-config.js +8 -0
- package/dist/node/utils/serialized-task-queue.d.ts +9 -0
- package/dist/node/utils/serialized-task-queue.js +17 -0
- package/dist/node/utils/transform.d.ts +11 -0
- package/dist/node/utils/transform.js +58 -0
- package/dist/node/vite-plugin.d.ts +1 -1
- package/dist/node/vite-plugin.js +11 -27
- package/dist/options.d.ts +3 -4
- package/dist/runtime/{taro → client/taro}/api.d.ts +0 -1
- package/dist/runtime/client/taro/api.js +9 -0
- package/dist/runtime/client/taro/component.d.ts +1 -0
- package/dist/runtime/client/taro/component.js +1 -0
- package/dist/runtime/client/taro/define-native-component.d.ts +7 -0
- package/dist/runtime/client/taro/define-native-component.js +4 -0
- package/dist/runtime/h5/app.d.ts +2 -0
- package/dist/runtime/h5/app.js +15 -0
- package/dist/runtime/h5/taro-runtime.d.ts +1 -1
- package/dist/runtime/h5/taro-runtime.js +1 -4
- package/dist/runtime/wx/amphibious/bootstrap.d.ts +4 -0
- package/dist/runtime/wx/amphibious/bootstrap.js +16 -0
- package/dist/runtime/wx/amphibious/transport.d.ts +2 -0
- package/dist/runtime/wx/amphibious/transport.js +4 -0
- package/dist/runtime/wx/capsule/app.d.ts +2 -0
- package/dist/runtime/wx/capsule/app.js +7 -0
- package/dist/runtime/wx/capsule/component.d.ts +3 -0
- package/dist/runtime/wx/capsule/component.js +4 -0
- package/dist/runtime/wx/capsule/page.d.ts +3 -0
- package/dist/runtime/wx/capsule/page.js +68 -0
- package/dist/runtime/wx/capsule/taro-runtime.d.ts +6 -0
- package/dist/runtime/wx/capsule/taro-runtime.js +6 -0
- package/dist/runtime/wx/dev/dev-runtime.d.ts +1 -0
- package/dist/runtime/wx/dev/dev-runtime.js +246 -0
- package/dist/runtime/wx/native/app.d.ts +1 -0
- package/dist/runtime/wx/native/app.js +3 -0
- package/dist/runtime/wx/native/component.d.ts +1 -0
- package/dist/runtime/wx/native/component.js +3 -0
- package/dist/runtime/wx/native/page.d.ts +1 -0
- package/dist/runtime/wx/native/page.js +4 -0
- package/dist/runtime/wx/systemjs/system-core.d.ts +4 -0
- package/dist/runtime/wx/systemjs/system-core.js +331 -0
- package/package.json +21 -14
- package/src/node/plugins/client/client-taro.ts +23 -0
- package/src/node/plugins/client/constant.ts +5 -0
- package/src/node/plugins/{conditional-directives.ts → conditional/conditional-directives.ts} +33 -13
- package/src/node/plugins/css/plugins.ts +96 -0
- package/src/node/plugins/h5/constant.ts +4 -0
- package/src/node/plugins/h5/plugins.ts +197 -0
- package/src/node/plugins/h5/resolver/module-resolver.ts +32 -0
- package/src/node/plugins/h5/transform-app.ts +90 -0
- package/src/node/plugins/wx/dev/dev-host.ts +448 -0
- package/src/node/plugins/wx/dev/hmr-files.ts +55 -0
- package/src/node/plugins/wx/dev/patch-publisher.ts +49 -0
- package/src/node/plugins/wx/dev/plugin.ts +82 -0
- package/src/node/plugins/wx/dev/react-refresh.ts +227 -0
- package/src/node/plugins/wx/module.ts +97 -0
- package/src/node/plugins/wx/native/compile-native-component-interface.ts +47 -0
- package/src/node/plugins/wx/native/create-native-component-output.ts +57 -0
- package/src/node/plugins/wx/native/native-component-assets.ts +114 -0
- package/src/node/plugins/wx/native/native-component-interface.ts +265 -0
- package/src/node/plugins/wx/output/files.ts +27 -0
- package/src/node/plugins/wx/output/json.ts +79 -0
- package/src/node/plugins/wx/output/relative-root.ts +7 -0
- package/src/node/plugins/wx/output/templates.ts +141 -0
- package/src/node/plugins/wx/placement/placer.ts +172 -0
- package/src/node/plugins/wx/placement/plan.ts +306 -0
- package/src/node/plugins/wx/plugins.ts +165 -0
- package/src/node/plugins/wx/render/capsule-wrapper.ts +86 -0
- package/src/node/plugins/wx/render/capsule.ts +21 -0
- package/src/node/plugins/wx/render/native.ts +84 -0
- package/src/node/plugins/wx/render/transport.ts +157 -0
- package/src/node/plugins/wx/resolve/resolver.ts +125 -0
- package/src/node/plugins/wx/resolve/specialize-bootstrap.ts +27 -0
- package/src/node/plugins/wx/resolve/specialize-page-capsule.ts +29 -0
- package/src/node/utils/constant.ts +1 -0
- package/src/node/utils/memoize.ts +149 -0
- package/src/node/utils/modules.ts +36 -38
- package/src/node/utils/once.ts +21 -0
- package/src/node/utils/packages.ts +1 -1
- package/src/node/utils/project-config.ts +10 -0
- package/src/node/utils/serialized-task-queue.ts +20 -0
- package/src/node/utils/transform.ts +82 -0
- package/src/node/vite-plugin.ts +12 -32
- package/src/options.ts +3 -4
- package/src/runtime/client/taro/api.ts +11 -0
- package/src/runtime/client/taro/component.ts +1 -0
- package/src/runtime/client/taro/define-native-component.ts +15 -0
- package/src/runtime/h5/app.ts +25 -0
- package/src/runtime/h5/taro-runtime.ts +1 -4
- package/src/runtime/wx/amphibious/bootstrap.ts +22 -0
- package/src/runtime/wx/amphibious/transport.ts +10 -0
- package/src/runtime/wx/capsule/app.ts +9 -0
- package/src/runtime/wx/capsule/component.ts +6 -0
- package/src/runtime/wx/capsule/page.ts +96 -0
- package/src/runtime/wx/capsule/taro-runtime.ts +14 -0
- package/src/runtime/wx/dev/dev-runtime.ts +317 -0
- package/src/runtime/wx/native/app.ts +4 -0
- package/src/runtime/wx/native/component.ts +4 -0
- package/src/runtime/wx/native/page.ts +6 -0
- package/src/runtime/wx/systemjs/LICENSE +10 -0
- package/src/runtime/wx/systemjs/system-core.js +370 -0
- package/src/runtime/wx/systemjs/system.d.ts +55 -0
- package/src/runtime/wx/wechat.d.ts +52 -0
- package/README.zh.md +0 -521
- package/dist/node/build-context.d.ts +0 -25
- package/dist/node/build-context.js +0 -47
- package/dist/node/css/css-pipeline.d.ts +0 -35
- package/dist/node/css/css-pipeline.js +0 -154
- package/dist/node/plugins/conditional-directives.d.ts +0 -3
- package/dist/node/plugins/taro-runtime.d.ts +0 -5
- package/dist/node/plugins/taro-runtime.js +0 -18
- package/dist/node/targets/h5/plugin.d.ts +0 -6
- package/dist/node/targets/h5/plugin.js +0 -117
- package/dist/node/targets/h5/virtual-modules.d.ts +0 -5
- package/dist/node/targets/h5/virtual-modules.js +0 -60
- package/dist/node/targets/wx/companion-assets.d.ts +0 -19
- package/dist/node/targets/wx/companion-assets.js +0 -129
- package/dist/node/targets/wx/dev-server/development-session.d.ts +0 -32
- package/dist/node/targets/wx/dev-server/development-session.js +0 -215
- package/dist/node/targets/wx/dev-server/full-build-scheduler.d.ts +0 -14
- package/dist/node/targets/wx/dev-server/full-build-scheduler.js +0 -60
- package/dist/node/targets/wx/dev-server/js-utils.d.ts +0 -5
- package/dist/node/targets/wx/dev-server/js-utils.js +0 -28
- package/dist/node/targets/wx/dev-server/output.d.ts +0 -19
- package/dist/node/targets/wx/dev-server/output.js +0 -44
- package/dist/node/targets/wx/dev-server/rolldown-runtime-source.d.ts +0 -8
- package/dist/node/targets/wx/dev-server/rolldown-runtime-source.js +0 -95
- package/dist/node/targets/wx/dev-server/update-server-state.d.ts +0 -65
- package/dist/node/targets/wx/dev-server/update-server-state.js +0 -116
- package/dist/node/targets/wx/dev-server/update-transport.d.ts +0 -28
- package/dist/node/targets/wx/dev-server/update-transport.js +0 -212
- package/dist/node/targets/wx/dev-server/vite-bundled-dev-adapter.d.ts +0 -44
- package/dist/node/targets/wx/dev-server/vite-bundled-dev-adapter.js +0 -145
- package/dist/node/targets/wx/development-files.d.ts +0 -8
- package/dist/node/targets/wx/development-files.js +0 -8
- package/dist/node/targets/wx/plugin.d.ts +0 -6
- package/dist/node/targets/wx/plugin.js +0 -144
- package/dist/node/targets/wx/react-refresh.d.ts +0 -4
- package/dist/node/targets/wx/react-refresh.js +0 -38
- package/dist/node/targets/wx/virtual-modules.d.ts +0 -16
- package/dist/node/targets/wx/virtual-modules.js +0 -120
- package/dist/node/utils/async.d.ts +0 -8
- package/dist/node/utils/async.js +0 -16
- package/dist/node/utils/filesystem.d.ts +0 -13
- package/dist/node/utils/filesystem.js +0 -43
- package/dist/runtime/taro/api.js +0 -11
- package/dist/runtime/taro/components.d.ts +0 -2
- package/dist/runtime/taro/components.js +0 -2
- package/dist/runtime/wx/page-update.d.ts +0 -6
- package/dist/runtime/wx/page-update.js +0 -157
- package/dist/runtime/wx/taro-runtime.d.ts +0 -5
- package/dist/runtime/wx/taro-runtime.js +0 -6
- package/dist/runtime/wx/update-client-state.d.ts +0 -68
- package/dist/runtime/wx/update-client-state.js +0 -84
- package/dist/runtime/wx/update-client.d.ts +0 -1
- package/dist/runtime/wx/update-client.js +0 -171
- package/src/node/build-context.ts +0 -62
- package/src/node/css/css-pipeline.ts +0 -171
- package/src/node/plugins/taro-runtime.ts +0 -22
- package/src/node/targets/h5/plugin.ts +0 -135
- package/src/node/targets/h5/virtual-modules.ts +0 -71
- package/src/node/targets/wx/companion-assets.ts +0 -174
- package/src/node/targets/wx/dev-server/development-session.ts +0 -271
- package/src/node/targets/wx/dev-server/full-build-scheduler.ts +0 -62
- package/src/node/targets/wx/dev-server/js-utils.ts +0 -33
- package/src/node/targets/wx/dev-server/output.ts +0 -56
- package/src/node/targets/wx/dev-server/rolldown-runtime-source.ts +0 -95
- package/src/node/targets/wx/dev-server/update-server-state.ts +0 -183
- package/src/node/targets/wx/dev-server/update-transport.ts +0 -261
- package/src/node/targets/wx/dev-server/vite-bundled-dev-adapter.ts +0 -203
- package/src/node/targets/wx/development-files.ts +0 -11
- package/src/node/targets/wx/plugin.ts +0 -164
- package/src/node/targets/wx/react-refresh.ts +0 -51
- package/src/node/targets/wx/virtual-modules.ts +0 -152
- package/src/node/utils/async.ts +0 -19
- package/src/node/utils/filesystem.ts +0 -45
- package/src/runtime/taro/api.ts +0 -13
- package/src/runtime/taro/components.ts +0 -2
- package/src/runtime/wx/page-update.ts +0 -230
- package/src/runtime/wx/react-refresh.d.ts +0 -20
- package/src/runtime/wx/taro-runtime.ts +0 -7
- package/src/runtime/wx/update-client-state.ts +0 -138
- package/src/runtime/wx/update-client.ts +0 -223
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import colors from 'picocolors';
|
|
3
|
+
import { build } from 'rolldown';
|
|
4
|
+
import { dev, viteReporterPlugin } from 'rolldown/experimental';
|
|
5
|
+
import { once } from '../../../utils/once.js';
|
|
6
|
+
import { resolvePackageFile } from '../../../utils/packages.js';
|
|
7
|
+
import { appShellFileName } from '../module.js';
|
|
8
|
+
import { hmrControlPath, hmrInfoFileName, hmrPatchesFileName, renderHmrInfo, renderInitialHmrPatches, writeHmrFile } from './hmr-files.js';
|
|
9
|
+
import { PatchPublisher } from './patch-publisher.js';
|
|
10
|
+
/**
|
|
11
|
+
* Creates the wx dev host: the adapter that owns the physical Rolldown DevEngine (created
|
|
12
|
+
* with dev(...)) and the patch publisher, and replaces Vite's bundledDev.listen so the
|
|
13
|
+
* engine writes directly to the Mini Program output directory instead of serving browser
|
|
14
|
+
* HMR over HTTP.
|
|
15
|
+
*/
|
|
16
|
+
export async function createWxDevHost({ server, options }) {
|
|
17
|
+
const bundledDev = getBundledDev(server);
|
|
18
|
+
// DevEngine does not reject run() after an initial plugin failure, so settle startup from its first buildEnd result.
|
|
19
|
+
// Later build errors belong to the running server and continue through onOutput/onHmrUpdates.
|
|
20
|
+
const initialBuild = Promise.withResolvers();
|
|
21
|
+
const settleInitialBuild = once((error) => {
|
|
22
|
+
if (error) {
|
|
23
|
+
initialBuild.reject(error);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
initialBuild.resolve();
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
const publisher = new PatchPublisher((content) => writeHmrFile(server.config.build.outDir, hmrPatchesFileName, content));
|
|
30
|
+
// Must install rolldown options before create engine
|
|
31
|
+
installRolldownOptions();
|
|
32
|
+
const engine = await createEngine();
|
|
33
|
+
// The wx dev host owns the only DevEngine. Vite's default listen() would create a second
|
|
34
|
+
// skip-write engine that renders into memory for browser HMR; instead the physical
|
|
35
|
+
// engine's initial build must finish before the HTTP server becomes ready, because
|
|
36
|
+
// DevTools opens the output directory directly and the app requires its files on disk.
|
|
37
|
+
bundledDev._devEngine = engine;
|
|
38
|
+
bundledDev.triggerBundleRegenerationIfStale = async () => false;
|
|
39
|
+
bundledDev.listen = async () => {
|
|
40
|
+
await Promise.all([engine.run(), initialBuild.promise]);
|
|
41
|
+
await engine.ensureCurrentBuildFinish();
|
|
42
|
+
};
|
|
43
|
+
// Vite binds the port only after initServer (and therefore the initial build) completes, so
|
|
44
|
+
// the actual port is not observable while onOutput runs for the first build. The App metadata
|
|
45
|
+
// is written once the port is real; later full builds rewrite it from onOutput.
|
|
46
|
+
server.httpServer?.once('listening', startFreshBuild);
|
|
47
|
+
// The runtime's metadata-only reports land on the control path; the buildId in each report
|
|
48
|
+
// IS the Rolldown client ID.
|
|
49
|
+
server.middlewares.use(hmrControlPath, (req, res) => void handleReport(req, res));
|
|
50
|
+
// Append the DevTools project directory line after Vite's own startup banner: DevTools
|
|
51
|
+
// opens the output directory directly, so the printed path is the one to select.
|
|
52
|
+
const originalPrintUrls = server.printUrls.bind(server);
|
|
53
|
+
server.printUrls = () => {
|
|
54
|
+
originalPrintUrls();
|
|
55
|
+
server.config.logger.info(` ${colors.green('➜')} ${colors.bold('WeChat DevTools')}: ${colors.cyan(relativeToViteConfig(server.config.build.outDir, server.config.configFile, server.config.root))}`);
|
|
56
|
+
};
|
|
57
|
+
return {
|
|
58
|
+
close: async () => {
|
|
59
|
+
await engine.close();
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
/** Rotates the build identity and materializes the App metadata for it. */
|
|
63
|
+
async function startFreshBuild() {
|
|
64
|
+
const port = boundPort(server);
|
|
65
|
+
if (port === undefined) {
|
|
66
|
+
// The initial output finishes before Vite binds its port. The listening listener
|
|
67
|
+
// starts the first real client build, avoiding a phantom registered client.
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const { buildId, previousBuildId } = publisher.startBuild();
|
|
71
|
+
if (previousBuildId) {
|
|
72
|
+
await engine.removeClient(previousBuildId);
|
|
73
|
+
}
|
|
74
|
+
await engine.registerClient(buildId);
|
|
75
|
+
// Publish info last: a heap that observes the new identity is guaranteed to see the
|
|
76
|
+
// matching reset patch file.
|
|
77
|
+
await writeHmrFile(server.config.build.outDir, hmrPatchesFileName, renderInitialHmrPatches());
|
|
78
|
+
await writeHmrInfo(server, buildId, port);
|
|
79
|
+
}
|
|
80
|
+
async function handleReport(req, res) {
|
|
81
|
+
if (req.method !== 'POST') {
|
|
82
|
+
res.statusCode = 404;
|
|
83
|
+
res.end();
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
const report = JSON.parse(await readBody(req));
|
|
88
|
+
// Only the current build's reports can advance physical delivery;
|
|
89
|
+
// delayed reports from older builds are ignored so they can never influence the
|
|
90
|
+
// live build.
|
|
91
|
+
if (!publisher.isCurrentBuild(report.buildId)) {
|
|
92
|
+
res.end();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (report.kind === 'rebuild') {
|
|
96
|
+
engine.triggerFullBuild();
|
|
97
|
+
res.end();
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// Commit every newly acknowledged Rolldown payload to this client's ship map.
|
|
101
|
+
const deliveredFiles = publisher.acknowledge(report.seq);
|
|
102
|
+
await Promise.all(deliveredFiles.map((fileName) => engine.notifyPayloadDelivered(fileName)));
|
|
103
|
+
res.end();
|
|
104
|
+
}
|
|
105
|
+
catch (e) {
|
|
106
|
+
logWxError(server.config.logger, 'wx HMR report failed', e);
|
|
107
|
+
res.statusCode = 400;
|
|
108
|
+
res.end();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/** Creates the physical DevEngine with the wx dev host hooks. */
|
|
112
|
+
async function createEngine() {
|
|
113
|
+
const rolldownOptions = await bundledDev.getRolldownOptions();
|
|
114
|
+
if (!rolldownOptions.output || Array.isArray(rolldownOptions.output)) {
|
|
115
|
+
throw new Error('wx development requires exactly one Rolldown output.');
|
|
116
|
+
}
|
|
117
|
+
return dev(rolldownOptions, rolldownOptions.output, {
|
|
118
|
+
onHmrUpdates: async (result) => {
|
|
119
|
+
if (result instanceof Error) {
|
|
120
|
+
logWxError(server.config.logger, 'wx HMR update failed', result);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
// Collect the current client's batch first: one HMR event can carry several
|
|
124
|
+
// client envelopes, while only the active build may enter its patch history.
|
|
125
|
+
const batch = [];
|
|
126
|
+
for (const { clientId, update } of result.updates) {
|
|
127
|
+
// Removed and delayed client sessions can still appear in a completed
|
|
128
|
+
// engine batch; they must never enter the current build's patch history.
|
|
129
|
+
if (!publisher.isCurrentBuild(clientId) || update.type === 'Noop') {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
if (update.type === 'Patch') {
|
|
133
|
+
batch.push(update);
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
server.config.logger.info(`[vpt] wx full rebuild required${update.reason ? `: ${update.reason}` : ''}`);
|
|
137
|
+
engine.triggerFullBuild();
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (batch.length > 0) {
|
|
141
|
+
await publisher.produce(batch);
|
|
142
|
+
// server.config.logger.info('[vpt] wx patch produced')
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
onOutput: async (result) => {
|
|
146
|
+
if (result instanceof Error) {
|
|
147
|
+
logWxError(server.config.logger, 'wx dev build failed', result);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// A fresh build identity per complete physical build; the App runtime reads it
|
|
151
|
+
// from hmr/info.js before any module registers.
|
|
152
|
+
await startFreshBuild();
|
|
153
|
+
},
|
|
154
|
+
rebuildStrategy: 'never',
|
|
155
|
+
watch: { skipWrite: false }
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
/** Restores physical Mini Program output conventions after Vite applies browser bundled-dev defaults. */
|
|
159
|
+
function installRolldownOptions() {
|
|
160
|
+
const original = bundledDev.getRolldownOptions.bind(bundledDev);
|
|
161
|
+
bundledDev.getRolldownOptions = async () => {
|
|
162
|
+
const rolldownOptions = await original();
|
|
163
|
+
if (Array.isArray(rolldownOptions.output)) {
|
|
164
|
+
throw new Error('wx development requires one configured Rolldown output.');
|
|
165
|
+
}
|
|
166
|
+
rolldownOptions.output ??= {};
|
|
167
|
+
const output = rolldownOptions.output;
|
|
168
|
+
const configuredOutput = server.config.build.rolldownOptions.output;
|
|
169
|
+
if (Array.isArray(configuredOutput)) {
|
|
170
|
+
throw new Error('wx development supports one configured Rolldown output.');
|
|
171
|
+
}
|
|
172
|
+
// Every page entry must depend on hmr/patches.js: DevTools classifies a changed Page
|
|
173
|
+
// dependency as Page JavaScript hot reload and re-executes live Pages, which is the only
|
|
174
|
+
// trigger that delivers physical patches while keeping the App heap alive.
|
|
175
|
+
const pageFiles = new Set(options.pages.map((page) => `${page.path}.js`));
|
|
176
|
+
const configured = (configuredOutput ?? {});
|
|
177
|
+
Object.assign(output, configured, {
|
|
178
|
+
assetFileNames: createStableFileNames(configured.assetFileNames, 'assets/[name][extname]'),
|
|
179
|
+
banner: createEntryBanner(pageFiles),
|
|
180
|
+
chunkFileNames: createStableFileNames(configured.chunkFileNames, 'assets/[name].js'),
|
|
181
|
+
entryFileNames: createStableFileNames(configured.entryFileNames, '[name]'),
|
|
182
|
+
format: 'es',
|
|
183
|
+
minify: true,
|
|
184
|
+
sourcemap: false
|
|
185
|
+
});
|
|
186
|
+
rolldownOptions.experimental ??= {};
|
|
187
|
+
rolldownOptions.experimental.devMode = {
|
|
188
|
+
...(typeof rolldownOptions.experimental.devMode === 'object'
|
|
189
|
+
? rolldownOptions.experimental.devMode
|
|
190
|
+
: {}),
|
|
191
|
+
implement: await bundleRuntimeSource(),
|
|
192
|
+
lazy: false
|
|
193
|
+
};
|
|
194
|
+
const reportInitialBuildPlugin = {
|
|
195
|
+
name: 'vpt:wx-report-initial-build',
|
|
196
|
+
buildEnd: settleInitialBuild
|
|
197
|
+
};
|
|
198
|
+
rolldownOptions.plugins = [rolldownOptions.plugins, reportInitialBuildPlugin, createViteReporter(server)];
|
|
199
|
+
disableViteOxcSourcemap(rolldownOptions.plugins);
|
|
200
|
+
return rolldownOptions;
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/** The bound HTTP port, or undefined before Vite's server is listening. */
|
|
205
|
+
function boundPort(server) {
|
|
206
|
+
const httpServer = server.httpServer;
|
|
207
|
+
if (!httpServer) {
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
const address = httpServer.address();
|
|
211
|
+
if (!address || typeof address === 'string') {
|
|
212
|
+
return undefined;
|
|
213
|
+
}
|
|
214
|
+
return address.port;
|
|
215
|
+
}
|
|
216
|
+
/** Writes the immutable App metadata every full build starts from. */
|
|
217
|
+
async function writeHmrInfo(server, buildId, port) {
|
|
218
|
+
const info = {
|
|
219
|
+
buildId,
|
|
220
|
+
endpoint: `${server.config.server.https ? 'https' : 'http'}://${resolveEndpointHost(server)}:${port}${hmrControlPath}`
|
|
221
|
+
};
|
|
222
|
+
await writeHmrFile(server.config.build.outDir, hmrInfoFileName, renderHmrInfo(info));
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* The project directory shown in the DevTools banner, relative to the Vite config:
|
|
226
|
+
* `dist/wx` instead of the absolute output path, so it can be pasted into DevTools.
|
|
227
|
+
*/
|
|
228
|
+
function relativeToViteConfig(outDir, configFile, root) {
|
|
229
|
+
const configDirectory = configFile ? path.dirname(configFile) : root;
|
|
230
|
+
const relativePath = path.relative(configDirectory, outDir).replaceAll('\\', '/');
|
|
231
|
+
if (!relativePath)
|
|
232
|
+
return '.';
|
|
233
|
+
return relativePath.startsWith('.') ? relativePath : `./${relativePath}`;
|
|
234
|
+
}
|
|
235
|
+
/** Logs an error with the plugin prefix, distinguishing Error values from unknowns. */
|
|
236
|
+
function logWxError(logger, prefix, error) {
|
|
237
|
+
if (Error.isError(error)) {
|
|
238
|
+
logger.error(`[vpt] ${prefix}`, { error });
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
logger.error(`[vpt] ${prefix} with unknown error: ${error}`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
// The runtime source is immutable for the host's lifetime (it changes only when the
|
|
245
|
+
// plugin is rebuilt), so the nested bundle runs once and every build reuses it.
|
|
246
|
+
const bundleRuntimeSource = once(
|
|
247
|
+
/** Bundles the runtime host and state machine into one plain script for injection. */
|
|
248
|
+
async function bundleRuntimeSource() {
|
|
249
|
+
// write: false — only the code is consumed; without it rolldown drops the bundle into
|
|
250
|
+
// the default dist/ of the running project.
|
|
251
|
+
const result = await build({
|
|
252
|
+
input: resolvePackageFile('dist/runtime/wx/dev/dev-runtime.js'),
|
|
253
|
+
output: { format: 'iife', minify: true, sourcemap: false },
|
|
254
|
+
write: false
|
|
255
|
+
});
|
|
256
|
+
return result.output[0].code;
|
|
257
|
+
});
|
|
258
|
+
const maximumBodyBytes = 64 * 1024;
|
|
259
|
+
function readBody(req) {
|
|
260
|
+
return new Promise((resolve, reject) => {
|
|
261
|
+
let body = '';
|
|
262
|
+
req.on('data', (chunk) => {
|
|
263
|
+
body += chunk.toString('utf8');
|
|
264
|
+
if (body.length > maximumBodyBytes) {
|
|
265
|
+
reject(new Error('report body too large'));
|
|
266
|
+
req.destroy();
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
req.on('end', () => resolve(body));
|
|
270
|
+
req.on('error', reject);
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
/** The bound address host, or loopback for wildcard binds; IPv6 literals are bracketed. */
|
|
274
|
+
function resolveEndpointHost(server) {
|
|
275
|
+
const address = server.httpServer?.address();
|
|
276
|
+
if (!address || typeof address === 'string') {
|
|
277
|
+
return '127.0.0.1';
|
|
278
|
+
}
|
|
279
|
+
if (address.address === '0.0.0.0' || address.address === '::') {
|
|
280
|
+
// Wildcard binds accept loopback connections; 127.0.0.1 is the address DevTools can reach.
|
|
281
|
+
return '127.0.0.1';
|
|
282
|
+
}
|
|
283
|
+
return address.address.includes(':') ? `[${address.address}]` : address.address;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Prepends entry banners. Banners are plain text appended after Rolldown's analysis, so the
|
|
287
|
+
* requires never become chunk dependencies (a bare require inside the injected runtime source
|
|
288
|
+
* would stall the build), and the wx render pipeline keeps this text after the hoisted chunk
|
|
289
|
+
* requires — so the runtime chunk exists before these run:
|
|
290
|
+
* - the app entry loads hmr/info.js and initializes the runtime before any module registers;
|
|
291
|
+
* - every page requires hmr/patches.js, the changed dependency that makes DevTools re-execute
|
|
292
|
+
* live Pages and thereby load physical updates.
|
|
293
|
+
*/
|
|
294
|
+
function createEntryBanner(pageFiles) {
|
|
295
|
+
return (chunk) => {
|
|
296
|
+
if (chunk.name === appShellFileName) {
|
|
297
|
+
return "__rolldown_runtime__.initialize(require('./hmr/info.js'));\n";
|
|
298
|
+
}
|
|
299
|
+
if (pageFiles.has(chunk.name)) {
|
|
300
|
+
// Page files live at `pages/<route>/index.js`, so the dependency path must be
|
|
301
|
+
// computed relative to each page's own directory.
|
|
302
|
+
const patchesPath = path.posix.relative(path.posix.dirname(chunk.fileName), 'hmr/patches.js');
|
|
303
|
+
return `require('${patchesPath}');\n`;
|
|
304
|
+
}
|
|
305
|
+
return '';
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
function createStableFileNames(addon, fallback) {
|
|
309
|
+
if (typeof addon === 'function') {
|
|
310
|
+
return (value) => toStableFileName(String(addon(value)));
|
|
311
|
+
}
|
|
312
|
+
return toStableFileName(typeof addon === 'string' ? addon : fallback);
|
|
313
|
+
}
|
|
314
|
+
function toStableFileName(fileName) {
|
|
315
|
+
return fileName
|
|
316
|
+
.replace(/(^|\/)\[hash(?::\d+)?\](?=\.|$)/g, '$1[name]')
|
|
317
|
+
.replace(/[-_.]\[hash(?::\d+)?\]/g, '')
|
|
318
|
+
.replace(/\[hash(?::\d+)?\]/g, '[name]');
|
|
319
|
+
}
|
|
320
|
+
function disableViteOxcSourcemap(pluginOption) {
|
|
321
|
+
if (Array.isArray(pluginOption)) {
|
|
322
|
+
pluginOption.forEach(disableViteOxcSourcemap);
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
if (!pluginOption || typeof pluginOption !== 'object') {
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
const plugin = pluginOption;
|
|
329
|
+
if (plugin.name === 'builtin:vite-transform' && plugin._options?.transformOptions) {
|
|
330
|
+
plugin._options.transformOptions.sourcemap = false;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
function createViteReporter(server) {
|
|
334
|
+
const { build, logger, root } = server.config;
|
|
335
|
+
return viteReporterPlugin({
|
|
336
|
+
assetsDir: path.join(build.assetsDir, '/'),
|
|
337
|
+
chunkLimit: 2000,
|
|
338
|
+
isLib: Boolean(build.lib),
|
|
339
|
+
isTty: Boolean(process.stdout.isTTY && !process.env.CI),
|
|
340
|
+
logInfo: (message) => logger.info(message),
|
|
341
|
+
reportCompressedSize: false,
|
|
342
|
+
root,
|
|
343
|
+
warnLargeChunks: false
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
function getBundledDev(server) {
|
|
347
|
+
const bundledDev = server.environments.client.bundledDev;
|
|
348
|
+
if (!bundledDev) {
|
|
349
|
+
throw new Error('Vite did not create the wx bundled-development environment.');
|
|
350
|
+
}
|
|
351
|
+
return bundledDev;
|
|
352
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { BindingClientHmrUpdate } from 'rolldown/experimental';
|
|
2
|
+
export declare const hmrInfoFileName = "hmr/info.js";
|
|
3
|
+
export declare const hmrPatchesFileName = "hmr/patches.js";
|
|
4
|
+
/** Report endpoint path served by the wx dev control edge. */
|
|
5
|
+
export declare const hmrControlPath = "/__vpt_hmr__";
|
|
6
|
+
/** Immutable App metadata for the current complete physical build. */
|
|
7
|
+
export type HmrInfo = Readonly<{
|
|
8
|
+
buildId: string;
|
|
9
|
+
endpoint: string;
|
|
10
|
+
}>;
|
|
11
|
+
/** The Patch variant of Rolldown's per-client HMR update, admitted into the patch history. */
|
|
12
|
+
export type PatchUpdate = Extract<BindingClientHmrUpdate['update'], {
|
|
13
|
+
type: 'Patch';
|
|
14
|
+
}>;
|
|
15
|
+
/** Renders the synchronous CommonJS metadata module loaded by the runtime chunk. */
|
|
16
|
+
export declare function renderHmrInfo(info: HmrInfo): string;
|
|
17
|
+
/** Provides a valid dependency before the host has a patch range to publish. */
|
|
18
|
+
export declare function renderInitialHmrPatches(): string;
|
|
19
|
+
/**
|
|
20
|
+
* Renders the missing patch suffix as a passive physical delivery module.
|
|
21
|
+
*
|
|
22
|
+
* DevTools re-executes the Page because this file changed. The module only stores the literal
|
|
23
|
+
* Rolldown factories in the persistent App runtime; storePatches applies them synchronously,
|
|
24
|
+
* so the Page's imports below the require resolve against the freshly registered modules.
|
|
25
|
+
*/
|
|
26
|
+
export declare function renderHmrPatches(buildId: string, patches: readonly PatchUpdate[]): string;
|
|
27
|
+
/** Publishes one physical HMR file (direct write; atomic rename is reserved for later analysis). */
|
|
28
|
+
export declare function writeHmrFile(outDir: string, fileName: string, source: string): Promise<void>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export const hmrInfoFileName = 'hmr/info.js';
|
|
4
|
+
export const hmrPatchesFileName = 'hmr/patches.js';
|
|
5
|
+
/** Report endpoint path served by the wx dev control edge. */
|
|
6
|
+
export const hmrControlPath = '/__vpt_hmr__';
|
|
7
|
+
/** Renders the synchronous CommonJS metadata module loaded by the runtime chunk. */
|
|
8
|
+
export function renderHmrInfo(info) {
|
|
9
|
+
return `module.exports = Object.freeze(${JSON.stringify(info)});\n`;
|
|
10
|
+
}
|
|
11
|
+
/** Provides a valid dependency before the host has a patch range to publish. */
|
|
12
|
+
export function renderInitialHmrPatches() {
|
|
13
|
+
return 'module.exports = undefined;\n';
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Renders the missing patch suffix as a passive physical delivery module.
|
|
17
|
+
*
|
|
18
|
+
* DevTools re-executes the Page because this file changed. The module only stores the literal
|
|
19
|
+
* Rolldown factories in the persistent App runtime; storePatches applies them synchronously,
|
|
20
|
+
* so the Page's imports below the require resolve against the freshly registered modules.
|
|
21
|
+
*/
|
|
22
|
+
export function renderHmrPatches(buildId, patches) {
|
|
23
|
+
if (patches.length === 0) {
|
|
24
|
+
throw new Error('Cannot render an empty WX patch range.');
|
|
25
|
+
}
|
|
26
|
+
const rendered = patches.map((patch) => `{seq: ${patch.seq}, changedIds: ${JSON.stringify(patch.changedIds)}, factory: () => {\n${patch.code}\n}}`);
|
|
27
|
+
return `__rolldown_runtime__.storePatches({buildId: ${JSON.stringify(buildId)}, patches: [${rendered.join(',')}]});\n`;
|
|
28
|
+
}
|
|
29
|
+
/** Publishes one physical HMR file (direct write; atomic rename is reserved for later analysis). */
|
|
30
|
+
export async function writeHmrFile(outDir, fileName, source) {
|
|
31
|
+
const filePath = path.join(outDir, fileName);
|
|
32
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
33
|
+
await fs.writeFile(filePath, source);
|
|
34
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type PatchUpdate } from './hmr-files.ts';
|
|
2
|
+
/** Abstracts the physical patches write; the engine owns the file destination. */
|
|
3
|
+
export type WritePatches = (content: string) => Promise<void>;
|
|
4
|
+
/** Owns one build's unacknowledged patches and physical publish decision. */
|
|
5
|
+
export declare class PatchPublisher {
|
|
6
|
+
private readonly writePatches;
|
|
7
|
+
private buildId;
|
|
8
|
+
/** Executable updates retained only until the runtime acknowledges physical delivery. */
|
|
9
|
+
private readonly pendingPatches;
|
|
10
|
+
constructor(writePatches: WritePatches);
|
|
11
|
+
/** True when the buildId belongs to the current full build. */
|
|
12
|
+
isCurrentBuild(buildId: string): boolean;
|
|
13
|
+
/** Begins a fresh build and returns both sides of the client-session rotation. */
|
|
14
|
+
startBuild(): Readonly<{
|
|
15
|
+
buildId: string;
|
|
16
|
+
previousBuildId: string | undefined;
|
|
17
|
+
}>;
|
|
18
|
+
/** Appends a Rolldown batch and publishes every unacknowledged patch. */
|
|
19
|
+
produce(patches: readonly PatchUpdate[]): Promise<void>;
|
|
20
|
+
/** Removes the pending prefix covered by the runtime's Rolldown sequence receipt. */
|
|
21
|
+
acknowledge(seq: number): string[];
|
|
22
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { renderHmrPatches } from './hmr-files.js';
|
|
3
|
+
/** Owns one build's unacknowledged patches and physical publish decision. */
|
|
4
|
+
export class PatchPublisher {
|
|
5
|
+
writePatches;
|
|
6
|
+
buildId;
|
|
7
|
+
/** Executable updates retained only until the runtime acknowledges physical delivery. */
|
|
8
|
+
pendingPatches = [];
|
|
9
|
+
// Explicit field assignment: node --test strips types and does not support parameter properties.
|
|
10
|
+
constructor(writePatches) {
|
|
11
|
+
this.writePatches = writePatches;
|
|
12
|
+
}
|
|
13
|
+
/** True when the buildId belongs to the current full build. */
|
|
14
|
+
isCurrentBuild(buildId) {
|
|
15
|
+
return buildId === this.buildId;
|
|
16
|
+
}
|
|
17
|
+
/** Begins a fresh build and returns both sides of the client-session rotation. */
|
|
18
|
+
startBuild() {
|
|
19
|
+
const previousBuildId = this.buildId;
|
|
20
|
+
const buildId = randomUUID();
|
|
21
|
+
this.buildId = buildId;
|
|
22
|
+
this.pendingPatches.length = 0;
|
|
23
|
+
return { buildId, previousBuildId };
|
|
24
|
+
}
|
|
25
|
+
/** Appends a Rolldown batch and publishes every unacknowledged patch. */
|
|
26
|
+
async produce(patches) {
|
|
27
|
+
if (this.buildId === undefined || patches.length === 0)
|
|
28
|
+
return;
|
|
29
|
+
this.pendingPatches.push(...patches);
|
|
30
|
+
await this.writePatches(renderHmrPatches(this.buildId, this.pendingPatches));
|
|
31
|
+
}
|
|
32
|
+
/** Removes the pending prefix covered by the runtime's Rolldown sequence receipt. */
|
|
33
|
+
acknowledge(seq) {
|
|
34
|
+
let deliveredCount = 0;
|
|
35
|
+
while (deliveredCount < this.pendingPatches.length && this.pendingPatches[deliveredCount].seq <= seq) {
|
|
36
|
+
deliveredCount++;
|
|
37
|
+
}
|
|
38
|
+
return this.pendingPatches.splice(0, deliveredCount).map((patch) => patch.filename);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PluginOption } from 'vite';
|
|
2
|
+
import type { VitePluginTaroOptions } from '../../../../options.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Adds the serve-only bundled-development plugin set for the wx target: the dev adapter
|
|
5
|
+
* (config, runtime lowering, dev host) plus the React Refresh adaptation transforms.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createWxDevelopmentPlugin(options: VitePluginTaroOptions): PluginOption[];
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { transformWithOxc } from 'vite';
|
|
2
|
+
import { esTarget } from '../../../utils/constant.js';
|
|
3
|
+
import { rolldownRuntimeId } from '../module.js';
|
|
4
|
+
import { memoize } from '../../../utils/memoize.js';
|
|
5
|
+
import { createWxDevHost } from './dev-host.js';
|
|
6
|
+
import { createWxReactRefreshTransforms } from './react-refresh.js';
|
|
7
|
+
/**
|
|
8
|
+
* Adds the serve-only bundled-development plugin set for the wx target: the dev adapter
|
|
9
|
+
* (config, runtime lowering, dev host) plus the React Refresh adaptation transforms.
|
|
10
|
+
*/
|
|
11
|
+
export function createWxDevelopmentPlugin(options) {
|
|
12
|
+
let host = null;
|
|
13
|
+
return [
|
|
14
|
+
{
|
|
15
|
+
name: 'vpt:wx-dev',
|
|
16
|
+
apply: 'serve',
|
|
17
|
+
config() {
|
|
18
|
+
return {
|
|
19
|
+
build: {
|
|
20
|
+
// Disable maps in resolved environment config as well as final output so Oxc and Babel skip producing
|
|
21
|
+
// intermediate maps that Rolldown would discard.
|
|
22
|
+
sourcemap: false
|
|
23
|
+
},
|
|
24
|
+
experimental: {
|
|
25
|
+
// Ask Vite to resolve its bundled-development graph and expose the private adapter instance. The wx
|
|
26
|
+
// configureServer hook replaces only its startup method with the directly writing DevEngine.
|
|
27
|
+
bundledDev: true
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
transform: {
|
|
32
|
+
order: 'post',
|
|
33
|
+
// The dev-mode transform assembles the runtime chunk (Rolldown's base runtime
|
|
34
|
+
// plus our injected implement) as this module's transform output, which
|
|
35
|
+
// bypasses the build's es2018 lowering. Real-device engines and WeChat's
|
|
36
|
+
// upload parser predate class fields and nullish operators, so the assembled
|
|
37
|
+
// runtime is lowered here — the only module that needs it. The exact id
|
|
38
|
+
// filter needs no code scan; the id must stay in sync with rolldownRuntimeId
|
|
39
|
+
// in module.ts (kept as a regex for the Rolldown-side filter).
|
|
40
|
+
filter: { id: /^\0rolldown\/runtime\.js(?:\?|$)/ },
|
|
41
|
+
handler(code, id) {
|
|
42
|
+
// The `setPublicClassFields` assumption emits plain `this.x = ...`
|
|
43
|
+
// assignments instead of external helpers, whose references the later
|
|
44
|
+
// minifier would mangle.
|
|
45
|
+
return fixRolldownRuntime(code);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
configureServer: {
|
|
49
|
+
// Install after Vite and user plugins have finished configuring the environment, but before server.listen()
|
|
50
|
+
// asks bundledDev to create its hard-coded skip-write DevEngine.
|
|
51
|
+
order: 'post',
|
|
52
|
+
async handler(server) {
|
|
53
|
+
host = await createWxDevHost({ server, options });
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
closeBundle() {
|
|
57
|
+
return host?.close();
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
...createWxReactRefreshTransforms()
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
// The assembled runtime chunk is byte-identical on every build (the base runtime and the
|
|
64
|
+
// bundled implement are immutable for the server's lifetime), so the lowering runs once
|
|
65
|
+
// and every build reuses it.
|
|
66
|
+
const fixRolldownRuntime = memoize((code) => {
|
|
67
|
+
return transformWithOxc(code, rolldownRuntimeId, {
|
|
68
|
+
lang: 'js',
|
|
69
|
+
target: esTarget,
|
|
70
|
+
sourcemap: false,
|
|
71
|
+
assumptions: { setPublicClassFields: true }
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
2
|
+
/**
|
|
3
|
+
* Creates the serve-only React Refresh adaptation transforms for the wx target.
|
|
4
|
+
*
|
|
5
|
+
* @vitejs/plugin-react's generated refresh code assumes the web HTML preamble and a browser
|
|
6
|
+
* global scope; wx has neither. Each transform adapts one piece of that contract:
|
|
7
|
+
* - the refresh runtime module (id-filtered): the vendored runtime reads and assigns
|
|
8
|
+
* `window` protocol globals (rewritten to `global`) and must inject itself at evaluation
|
|
9
|
+
* — the preamble's `injectIntoGlobalHook` call has no HTML home in wx;
|
|
10
|
+
* - react-family modules (filtered on free references): the DevTools hook is read as a free
|
|
11
|
+
* variable, which the WeChat runtime scope never resolves against `global` — every free
|
|
12
|
+
* reference becomes an explicit member access;
|
|
13
|
+
* - boundary modules (filtered on the guard): the preamble's `$RefreshReg$` global is not
|
|
14
|
+
* needed because the transform generates local wrappers over the imported refresh
|
|
15
|
+
* runtime, so the guard that checks for the global is removed.
|
|
16
|
+
*
|
|
17
|
+
* Each transform's filter is its routing: the three domains are disjoint, so a module is
|
|
18
|
+
* transformed by at most one of them, and modules outside all three never reach a handler.
|
|
19
|
+
*/
|
|
20
|
+
export declare function createWxReactRefreshTransforms(): Plugin[];
|