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