vite-plugin-taro 0.5.12 → 0.5.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/node/plugins/client/client-taro.d.ts +1 -1
- package/dist/node/plugins/client/client-taro.js +2 -1
- package/dist/node/plugins/h5/create-stencil-client-adapter.d.ts +1 -1
- package/dist/node/plugins/h5/create-stencil-client-adapter.js +2 -1
- package/dist/node/plugins/h5/plugins.js +22 -1
- package/dist/node/plugins/h5/resolver/module-resolver.js +2 -1
- package/dist/node/plugins/tailwind/tailwind-css.d.ts +1 -0
- package/dist/node/plugins/tailwind/tailwind-css.js +3 -0
- package/dist/node/plugins/wx/dev/create-hmr-results-stream.d.ts +23 -0
- package/dist/node/plugins/wx/dev/create-hmr-results-stream.js +57 -0
- package/dist/node/plugins/wx/dev/create-style-capture.d.ts +42 -0
- package/dist/node/plugins/wx/dev/create-style-capture.js +125 -0
- package/dist/node/plugins/wx/dev/dev-host.d.ts +5 -1
- package/dist/node/plugins/wx/dev/dev-host.js +170 -47
- package/dist/node/plugins/wx/dev/hmr-files.d.ts +10 -0
- package/dist/node/plugins/wx/dev/hmr-files.js +12 -0
- package/dist/node/plugins/wx/dev/host-actions.d.ts +16 -0
- package/dist/node/plugins/wx/dev/host-actions.js +58 -0
- package/dist/node/plugins/wx/dev/patch-publisher.d.ts +2 -2
- package/dist/node/plugins/wx/dev/patch-publisher.js +17 -1
- package/dist/node/plugins/wx/dev/plugins.d.ts +25 -2
- package/dist/node/plugins/wx/dev/plugins.js +61 -9
- package/dist/node/plugins/wx/dev/react-refresh.js +6 -2
- package/dist/node/plugins/wx/dev/runtime-reports.d.ts +27 -0
- package/dist/node/plugins/wx/dev/runtime-reports.js +45 -0
- package/dist/node/plugins/wx/dev/wx-dev-options.d.ts +10 -5
- package/dist/node/plugins/wx/dev/wx-dev-options.js +47 -24
- package/dist/node/plugins/wx/module.d.ts +1 -1
- package/dist/node/plugins/wx/module.js +2 -1
- package/dist/node/plugins/wx/native/compile-native-component-interface.js +2 -1
- package/dist/node/plugins/wx/native/create-native-component-output.js +2 -0
- package/dist/node/plugins/wx/native/native-component-assets.d.ts +1 -1
- package/dist/node/plugins/wx/native/native-component-assets.js +3 -3
- package/dist/node/plugins/wx/native/native-component-interface.js +2 -1
- package/dist/node/plugins/wx/output/files.d.ts +1 -1
- package/dist/node/plugins/wx/output/files.js +6 -1
- package/dist/node/plugins/wx/plugins.js +13 -6
- package/dist/node/plugins/wx/resolve/resolver.d.ts +2 -1
- package/dist/node/plugins/wx/resolve/resolver.js +34 -19
- package/dist/node/plugins/wx/styles/plugins.d.ts +3 -0
- package/dist/node/plugins/wx/styles/plugins.js +111 -0
- package/dist/node/plugins/wx/styles/transform-wx-style.d.ts +8 -0
- package/dist/node/plugins/wx/styles/transform-wx-style.js +9 -0
- package/dist/node/plugins/wx/styles/utils.d.ts +39 -0
- package/dist/node/plugins/wx/styles/utils.js +95 -0
- package/dist/node/utils/modules.d.ts +1 -1
- package/dist/node/utils/modules.js +4 -3
- package/dist/node/utils/packages.js +2 -2
- package/dist/node/utils/vite.d.ts +17 -0
- package/dist/node/utils/vite.js +43 -0
- package/dist/node/vite-plugin.js +0 -2
- package/package.json +4 -3
- package/src/node/plugins/client/client-taro.ts +2 -2
- package/src/node/plugins/h5/create-stencil-client-adapter.ts +2 -2
- package/src/node/plugins/h5/plugins.ts +22 -1
- package/src/node/plugins/h5/resolver/module-resolver.ts +2 -1
- package/src/node/plugins/tailwind/tailwind-css.ts +4 -0
- package/src/node/plugins/wx/dev/create-hmr-results-stream.ts +71 -0
- package/src/node/plugins/wx/dev/create-style-capture.ts +179 -0
- package/src/node/plugins/wx/dev/dev-host.ts +198 -63
- package/src/node/plugins/wx/dev/hmr-files.ts +13 -0
- package/src/node/plugins/wx/dev/host-actions.ts +88 -0
- package/src/node/plugins/wx/dev/patch-publisher.ts +19 -2
- package/src/node/plugins/wx/dev/plugins.ts +67 -10
- package/src/node/plugins/wx/dev/react-refresh.ts +6 -2
- package/src/node/plugins/wx/dev/runtime-reports.ts +70 -0
- package/src/node/plugins/wx/dev/wx-dev-options.ts +53 -32
- package/src/node/plugins/wx/module.ts +2 -4
- package/src/node/plugins/wx/native/compile-native-component-interface.ts +2 -1
- package/src/node/plugins/wx/native/create-native-component-output.ts +2 -0
- package/src/node/plugins/wx/native/native-component-assets.ts +3 -4
- package/src/node/plugins/wx/native/native-component-interface.ts +2 -1
- package/src/node/plugins/wx/output/files.ts +6 -1
- package/src/node/plugins/wx/plugins.ts +16 -6
- package/src/node/plugins/wx/resolve/resolver.ts +36 -19
- package/src/node/plugins/wx/styles/plugins.ts +125 -0
- package/src/node/plugins/wx/styles/transform-wx-style.ts +11 -0
- package/src/node/plugins/wx/styles/utils.ts +119 -0
- package/src/node/utils/modules.ts +4 -3
- package/src/node/utils/packages.ts +2 -2
- package/src/node/utils/vite.ts +67 -0
- package/src/node/vite-plugin.ts +0 -2
- package/dist/node/plugins/css/plugins.d.ts +0 -4
- package/dist/node/plugins/css/plugins.js +0 -119
- package/dist/node/plugins/wx/dev/create-wx-dev-mode.d.ts +0 -6
- package/dist/node/plugins/wx/dev/create-wx-dev-mode.js +0 -9
- package/dist/node/utils/serialized-task-queue.d.ts +0 -13
- package/dist/node/utils/serialized-task-queue.js +0 -25
- package/src/node/plugins/css/plugins.ts +0 -135
- package/src/node/plugins/wx/dev/create-wx-dev-mode.ts +0 -14
- package/src/node/utils/serialized-task-queue.ts +0 -32
|
@@ -1,25 +1,43 @@
|
|
|
1
|
-
import { transformWithOxc } from 'vite';
|
|
1
|
+
import { normalizePath, transformWithOxc } from 'vite';
|
|
2
2
|
import { esTarget } from '../../../utils/constant.js';
|
|
3
3
|
import { memoize } from '../../../utils/memoize.js';
|
|
4
4
|
import { normalizeModuleId } from '../../../utils/modules.js';
|
|
5
5
|
import { appCapsulePath, pageCapsulePath, rolldownRuntimeId, taroRuntimePath } from '../module.js';
|
|
6
6
|
import { createWxDevHost } from './dev-host.js';
|
|
7
|
+
import { developmentAppWxssFileName } from './hmr-files.js';
|
|
7
8
|
import { createWxReactRefreshTransforms } from './react-refresh.js';
|
|
8
9
|
const taroRuntimeId = '@tarojs/runtime';
|
|
10
|
+
/** Selects the sole Vite environment that owns the physical Mini Program development project. */
|
|
11
|
+
export function isWxClientEnvironment(environment) {
|
|
12
|
+
return environment.name === 'client';
|
|
13
|
+
}
|
|
9
14
|
/**
|
|
10
15
|
* Adds the serve-only bundled-development plugin set for the wx target: the dev adapter,
|
|
11
16
|
* Page HMR activation, and React Refresh adaptation transforms.
|
|
17
|
+
*
|
|
18
|
+
* The ordered application entries cross this configuration boundary unchanged so the host can compose global CSS without
|
|
19
|
+
* reconstructing the resolver's App/Page ownership policy from unrelated Rolldown shell and transport entries.
|
|
12
20
|
*/
|
|
13
|
-
export function createWxDevelopmentPlugin(options) {
|
|
21
|
+
export function createWxDevelopmentPlugin(options, applicationEntryIds) {
|
|
22
|
+
/*
|
|
23
|
+
* Vite creates this plugin descriptor before a server or DevEngine exists, then invokes configureServer and closeBundle on
|
|
24
|
+
* different lifecycle stacks. This mutable handle transfers the one client-owned host between those hooks: configureServer
|
|
25
|
+
* assigns it after asynchronous construction, and closeBundle reads it to drain the same engine. Environment scoping ensures
|
|
26
|
+
* only the client hook pair participates. Capturing a construction Promise would start too early, while recreating the host
|
|
27
|
+
* in closeBundle would lose every live action, patch, style, and client frontier owned by the running instance.
|
|
28
|
+
*/
|
|
14
29
|
let host = null;
|
|
15
30
|
// Portable hook filters stay broad; these exact identities exclude similarly named user modules.
|
|
16
|
-
const normalizedAppCapsulePath =
|
|
17
|
-
const normalizedPageCapsulePath =
|
|
18
|
-
const normalizedTaroRuntimePath =
|
|
31
|
+
const normalizedAppCapsulePath = normalizePath(appCapsulePath);
|
|
32
|
+
const normalizedPageCapsulePath = normalizePath(pageCapsulePath);
|
|
33
|
+
const normalizedTaroRuntimePath = normalizePath(taroRuntimePath);
|
|
19
34
|
return [
|
|
20
35
|
{
|
|
21
36
|
name: 'vpt:wx-dev',
|
|
22
37
|
apply: 'serve',
|
|
38
|
+
// The physical WX DevEngine is a client build. Native environment scoping gives its shared host exactly one
|
|
39
|
+
// generate/close lifecycle instead of admitting hooks from Vite's unrelated SSR environment.
|
|
40
|
+
applyToEnvironment: isWxClientEnvironment,
|
|
23
41
|
config() {
|
|
24
42
|
return {
|
|
25
43
|
build: {
|
|
@@ -47,7 +65,20 @@ export function createWxDevelopmentPlugin(options) {
|
|
|
47
65
|
// asks bundledDev to create its hard-coded skip-write DevEngine.
|
|
48
66
|
order: 'post',
|
|
49
67
|
async handler(server) {
|
|
50
|
-
host = await createWxDevHost({
|
|
68
|
+
host = await createWxDevHost({
|
|
69
|
+
server: server,
|
|
70
|
+
options: options,
|
|
71
|
+
applicationEntryIds: applicationEntryIds
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
generateBundle: {
|
|
76
|
+
order: 'post',
|
|
77
|
+
handler(_, bundle) {
|
|
78
|
+
// `vpt:wx` emits the production App wrapper during every complete build: initial startup and each
|
|
79
|
+
// recovery build, not just once when this plugin instance is created. Development transfers that file
|
|
80
|
+
// to the host so its only physical write happens after the matching build identity is durable.
|
|
81
|
+
removeDevelopmentAppWxss(bundle);
|
|
51
82
|
}
|
|
52
83
|
},
|
|
53
84
|
closeBundle() {
|
|
@@ -117,6 +148,24 @@ export function createWxDevelopmentPlugin(options) {
|
|
|
117
148
|
...createWxReactRefreshTransforms()
|
|
118
149
|
];
|
|
119
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Transfers development ownership of `app.wxss` from complete output to the dev host.
|
|
153
|
+
*
|
|
154
|
+
* The ordinary WX output hook emits the static production wrapper during every complete build. In development, the existing
|
|
155
|
+
* physical wrapper instead contains the previous build ID. If the static asset remained in this bundle, the DevEngine would:
|
|
156
|
+
*
|
|
157
|
+
* 1. replace the versioned wrapper with static production bytes while JavaScript and HMR metadata are still being finalized;
|
|
158
|
+
* 2. let DevTools observe that root-style change and reload the App against the previous build identity;
|
|
159
|
+
* 3. let the host replace the wrapper again with the new build ID, causing a second App reload.
|
|
160
|
+
*
|
|
161
|
+
* Deleting only the in-memory bundle entry avoids both premature writes. Development sets `emptyOutDir: false`, so the prior
|
|
162
|
+
* physical `app.wxss` remains available while the complete output is written. The host replaces it exactly once after
|
|
163
|
+
* `hmr/patches.js` and `hmr/info.js` are durable. Incremental HMR never enters this complete-output hook and continues changing
|
|
164
|
+
* only `assets/global.wxss`, which preserves the App heap. The serve-only plugin leaves production output unchanged.
|
|
165
|
+
*/
|
|
166
|
+
export function removeDevelopmentAppWxss(bundle) {
|
|
167
|
+
delete bundle[developmentAppWxssFileName];
|
|
168
|
+
}
|
|
120
169
|
/** Ensures the Refresh hook exists before React's renderer evaluates and injects itself. */
|
|
121
170
|
export function injectReactRefreshBootstrap(code) {
|
|
122
171
|
return {
|
|
@@ -153,9 +202,12 @@ function getPageRoute(id) {
|
|
|
153
202
|
throw new Error(`WX Page capsule is missing its route: ${id}`);
|
|
154
203
|
return route;
|
|
155
204
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
205
|
+
/*
|
|
206
|
+
* memoize owns a mutable one-entry-by-input cache. The assembled runtime source is byte-identical across complete generations
|
|
207
|
+
* because both the Rolldown base and injected implementation are immutable for the server lifetime. Reusing its lowered result
|
|
208
|
+
* avoids repeating the only large Oxc transform on every rebuild; keying by source still invalidates correctly if a future Vite
|
|
209
|
+
* generation changes the runtime, unlike a module-global cached string detached from its actual input.
|
|
210
|
+
*/
|
|
159
211
|
const fixRolldownRuntime = memoize((code) => {
|
|
160
212
|
return transformWithOxc(code, rolldownRuntimeId, {
|
|
161
213
|
lang: 'js',
|
|
@@ -193,7 +193,11 @@ export function removeRefreshPreambleGuard({ code, id }) {
|
|
|
193
193
|
createVisitor: createRefreshPreambleGuardVisitor
|
|
194
194
|
});
|
|
195
195
|
}
|
|
196
|
-
|
|
197
|
-
|
|
196
|
+
/*
|
|
197
|
+
* Each memoized transform owns a mutable cache keyed only by source bytes. The matching runtime/react-family modules are
|
|
198
|
+
* immutable between complete generations, so reparsing them would repeat O(source bytes) Oxc work without observing new state.
|
|
199
|
+
* Source keys still create a fresh result after a dependency upgrade or real module edit, unlike a once-only cache keyed by ID;
|
|
200
|
+
* keeping separate caches prevents identical text in different transform domains from sharing the wrong adaptation.
|
|
201
|
+
*/
|
|
198
202
|
const fixRefreshRuntime = memoize(transformRefreshRuntime, { getCacheKey: ({ code }) => code });
|
|
199
203
|
const fixReactDevtoolsHook = memoize(transformReactDevtoolsHook, { getCacheKey: ({ code }) => code });
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type SchedulerLike, Subject } from 'rxjs';
|
|
2
|
+
type AppliedReport = Readonly<{
|
|
3
|
+
kind: 'applied';
|
|
4
|
+
buildId: string;
|
|
5
|
+
seq: number;
|
|
6
|
+
}>;
|
|
7
|
+
/** The runtime hit an unrecoverable state and needs a complete build. */
|
|
8
|
+
type RebuildReport = Readonly<{
|
|
9
|
+
kind: 'rebuild';
|
|
10
|
+
buildId: string;
|
|
11
|
+
reason: string;
|
|
12
|
+
}>;
|
|
13
|
+
export type RuntimeReport = AppliedReport | RebuildReport;
|
|
14
|
+
/**
|
|
15
|
+
* Conflates runtime receipts without weakening their build identity or recovery semantics.
|
|
16
|
+
*
|
|
17
|
+
* Reports are metadata frontiers rather than executable deltas: for one build, the highest applied sequence subsumes lower and
|
|
18
|
+
* duplicate acknowledgements. A rebuild does not subsume reports from a different build, because delayed Pages may still POST
|
|
19
|
+
* after session rotation, but it dominates every acknowledgement for its own build. The host validates each retained build ID
|
|
20
|
+
* against the physical publisher only when its serialized task executes, preserving rotation order.
|
|
21
|
+
*
|
|
22
|
+
* Completing the Subject flushes the active window synchronously so shutdown can include its host task before closing Rolldown.
|
|
23
|
+
* Reduction is O(reports) time and O(distinct builds) retained space per quiet window.
|
|
24
|
+
*/
|
|
25
|
+
export declare function createRuntimeReportsStream(settleMilliseconds: number, scheduler: SchedulerLike, publish: (reports: readonly RuntimeReport[]) => void): Subject<RuntimeReport>;
|
|
26
|
+
export declare function reduceRuntimeReportWindow(window: readonly RuntimeReport[]): readonly RuntimeReport[];
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { buffer, debounceTime, filter, Subject } from 'rxjs';
|
|
2
|
+
/**
|
|
3
|
+
* Conflates runtime receipts without weakening their build identity or recovery semantics.
|
|
4
|
+
*
|
|
5
|
+
* Reports are metadata frontiers rather than executable deltas: for one build, the highest applied sequence subsumes lower and
|
|
6
|
+
* duplicate acknowledgements. A rebuild does not subsume reports from a different build, because delayed Pages may still POST
|
|
7
|
+
* after session rotation, but it dominates every acknowledgement for its own build. The host validates each retained build ID
|
|
8
|
+
* against the physical publisher only when its serialized task executes, preserving rotation order.
|
|
9
|
+
*
|
|
10
|
+
* Completing the Subject flushes the active window synchronously so shutdown can include its host task before closing Rolldown.
|
|
11
|
+
* Reduction is O(reports) time and O(distinct builds) retained space per quiet window.
|
|
12
|
+
*/
|
|
13
|
+
export function createRuntimeReportsStream(settleMilliseconds, scheduler, publish) {
|
|
14
|
+
/*
|
|
15
|
+
* This Subject is the sole mutable HTTP admission edge. Requests append reports synchronously and finish their responses;
|
|
16
|
+
* buffer then owns the short-lived window while debounceTime supplies only its quiet-edge signal. Reports are metadata rather
|
|
17
|
+
* than executable deltas, so the window may be reduced before entering hostActions. Directly mutating PatchPublisher from the
|
|
18
|
+
* request stack would race patch writes and build rotation; retaining every raw receipt beyond the window would grow with Page
|
|
19
|
+
* count and duplicate acknowledgements. Completion flushes the final window during phased shutdown.
|
|
20
|
+
*/
|
|
21
|
+
const reports = new Subject();
|
|
22
|
+
reports
|
|
23
|
+
.pipe(buffer(reports.pipe(debounceTime(settleMilliseconds, scheduler))), filter((window) => window.length > 0))
|
|
24
|
+
.subscribe((window) => publish(reduceRuntimeReportWindow(window)));
|
|
25
|
+
return reports;
|
|
26
|
+
}
|
|
27
|
+
export function reduceRuntimeReportWindow(window) {
|
|
28
|
+
/*
|
|
29
|
+
* This transaction-local mutable Map is bounded by distinct build IDs in one quiet window. Insertion order preserves causal
|
|
30
|
+
* build order, while replacing a value conflates only that build's monotonic acknowledgement frontier; rebuild becomes its
|
|
31
|
+
* terminal value. A single global latest report would let delayed Pages erase another build, and retaining the raw window
|
|
32
|
+
* would make downstream work proportional to duplicate report volume. The Map is discarded immediately after reduction.
|
|
33
|
+
*/
|
|
34
|
+
const reportsByBuild = new Map();
|
|
35
|
+
for (const report of window) {
|
|
36
|
+
const previous = reportsByBuild.get(report.buildId);
|
|
37
|
+
if (previous?.kind === 'rebuild') {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (report.kind === 'rebuild' || previous === undefined || report.seq > previous.seq) {
|
|
41
|
+
reportsByBuild.set(report.buildId, report);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return [...reportsByBuild.values()];
|
|
45
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { InputOptions, OutputOptions } from 'rolldown';
|
|
1
|
+
import type { InputOptions, OutputOptions, Plugin } from 'rolldown';
|
|
2
2
|
import { type DevEngine } from 'rolldown/experimental';
|
|
3
3
|
import type { ViteDevServer } from 'vite';
|
|
4
4
|
import type { VitePluginTaroOptions } from '../../../../options.ts';
|
|
5
|
-
|
|
5
|
+
type BundledDevRolldownOptions = InputOptions & {
|
|
6
6
|
experimental?: {
|
|
7
7
|
[key: string]: unknown;
|
|
8
8
|
devMode?: boolean | Record<string, unknown>;
|
|
@@ -15,11 +15,16 @@ export type BundledDev = {
|
|
|
15
15
|
listen(): Promise<void>;
|
|
16
16
|
triggerBundleRegenerationIfStale(): Promise<boolean>;
|
|
17
17
|
};
|
|
18
|
-
/**
|
|
19
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Installs physical WX output and runtime conventions over Vite's browser-oriented bundled-development options.
|
|
20
|
+
* Build completion deliberately remains outside this options adapter: DevEngine onOutput is the single lifecycle authority.
|
|
21
|
+
*/
|
|
22
|
+
export declare function installWxDevOptions({ bundledDev, server, options, hostPlugins }: {
|
|
20
23
|
bundledDev: BundledDev;
|
|
21
24
|
server: ViteDevServer;
|
|
22
25
|
options: VitePluginTaroOptions;
|
|
23
|
-
|
|
26
|
+
hostPlugins: Plugin[];
|
|
27
|
+
}): void;
|
|
24
28
|
/** Returns the configured output after rejecting states unsupported by the physical WX engine. */
|
|
25
29
|
export declare function requireSingleOutput(rolldownOptions: BundledDevRolldownOptions): OutputOptions;
|
|
30
|
+
export {};
|
|
@@ -4,20 +4,17 @@ import { viteReporterPlugin } from 'rolldown/experimental';
|
|
|
4
4
|
import { once } from '../../../utils/once.js';
|
|
5
5
|
import { resolvePackageFile } from '../../../utils/packages.js';
|
|
6
6
|
import { appShellFileName } from '../module.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
initialBuild.resolve();
|
|
19
|
-
}
|
|
20
|
-
});
|
|
7
|
+
/**
|
|
8
|
+
* Installs physical WX output and runtime conventions over Vite's browser-oriented bundled-development options.
|
|
9
|
+
* Build completion deliberately remains outside this options adapter: DevEngine onOutput is the single lifecycle authority.
|
|
10
|
+
*/
|
|
11
|
+
export function installWxDevOptions({ bundledDev, server, options, hostPlugins }) {
|
|
12
|
+
/*
|
|
13
|
+
* Vite owns this mutable adapter method and calls it later when constructing DevEngine. Replacing that one seam preserves
|
|
14
|
+
* Vite's resolved graph while applying WX physical-output conventions to every options generation. Capturing and mutating one
|
|
15
|
+
* options object here would be stale on later complete builds; creating a second engine would duplicate watchers and graphs.
|
|
16
|
+
* The bound original remains immutable and is invoked exactly once per delegated options request.
|
|
17
|
+
*/
|
|
21
18
|
const original = bundledDev.getRolldownOptions.bind(bundledDev);
|
|
22
19
|
bundledDev.getRolldownOptions = async () => {
|
|
23
20
|
const rolldownOptions = await original();
|
|
@@ -28,8 +25,15 @@ export function installWxDevOptions({ bundledDev, server, options }) {
|
|
|
28
25
|
}
|
|
29
26
|
const configured = configuredOutput ?? {};
|
|
30
27
|
// Every page entry must depend on hmr/patches.js: DevTools classifies a changed Page dependency as Page JavaScript
|
|
31
|
-
// hot reload and re-executes live Pages, which is the only physical patch trigger that preserves the App heap.
|
|
28
|
+
// hot reload and re-executes live Pages, which is the only physical patch trigger that preserves the App heap. Although
|
|
29
|
+
// Set provides O(1) membership, exposing it as ReadonlySet prevents mutation after this options generation is resolved.
|
|
32
30
|
const pageFiles = new Set(options.pages.map((page) => `${page.path}.js`));
|
|
31
|
+
/*
|
|
32
|
+
* Rolldown passes this mutable output object onward by identity, and nested Vite plugins may already retain it. Mutating
|
|
33
|
+
* that single object preserves their references while atomically replacing browser-oriented naming and format fields with
|
|
34
|
+
* stable physical WX conventions. Cloning only our fields would leave retained references on stale hashed filenames;
|
|
35
|
+
* mutating configuredOutput itself would leak development normalization back into the user's resolved Vite config.
|
|
36
|
+
*/
|
|
33
37
|
Object.assign(output, configured, {
|
|
34
38
|
assetFileNames: createStableFileNames(configured.assetFileNames, 'assets/[name][extname]'),
|
|
35
39
|
banner: createEntryBanner(pageFiles),
|
|
@@ -39,19 +43,27 @@ export function installWxDevOptions({ bundledDev, server, options }) {
|
|
|
39
43
|
minify: true,
|
|
40
44
|
sourcemap: false
|
|
41
45
|
});
|
|
46
|
+
/*
|
|
47
|
+
* experimental belongs to this transaction-local Rolldown options generation. Materialize it only when absent, then
|
|
48
|
+
* replace devMode with a new object so user fields survive without mutating a possibly shared configured sub-object.
|
|
49
|
+
*/
|
|
42
50
|
rolldownOptions.experimental ??= {};
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
const existingDevMode = rolldownOptions.experimental.devMode;
|
|
52
|
+
rolldownOptions.experimental.devMode = {
|
|
53
|
+
...(typeof existingDevMode === 'object' ? existingDevMode : {}),
|
|
54
|
+
implement: await bundleRuntimeSource(),
|
|
55
|
+
lazy: false,
|
|
56
|
+
skipCommonRuntimeInjection: false
|
|
47
57
|
};
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
58
|
+
/*
|
|
59
|
+
* The plugin list is mutable configuration consumed once by this engine generation. Replace the top-level reference with
|
|
60
|
+
* an ordered composite rather than pushing into Vite's potentially shared nested array: existing transforms run first,
|
|
61
|
+
* host capture observes their final values, and the reporter observes final output without mutating either input list.
|
|
62
|
+
*/
|
|
63
|
+
rolldownOptions.plugins = [rolldownOptions.plugins, hostPlugins, createViteReporter(server)];
|
|
51
64
|
disableViteOxcSourcemap(rolldownOptions.plugins);
|
|
52
65
|
return rolldownOptions;
|
|
53
66
|
};
|
|
54
|
-
return initialBuild.promise;
|
|
55
67
|
}
|
|
56
68
|
/** Returns the configured output after rejecting states unsupported by the physical WX engine. */
|
|
57
69
|
export function requireSingleOutput(rolldownOptions) {
|
|
@@ -65,6 +77,7 @@ function ensureSingleOutput(rolldownOptions) {
|
|
|
65
77
|
if (Array.isArray(rolldownOptions.output)) {
|
|
66
78
|
throw new Error('wx development requires one configured Rolldown output.');
|
|
67
79
|
}
|
|
80
|
+
// Rolldown needs the created object attached to input options by identity; returning a detached fallback would be ignored.
|
|
68
81
|
rolldownOptions.output ??= {};
|
|
69
82
|
return rolldownOptions.output;
|
|
70
83
|
}
|
|
@@ -107,6 +120,11 @@ function disableViteOxcSourcemap(pluginOption) {
|
|
|
107
120
|
return;
|
|
108
121
|
const plugin = pluginOption;
|
|
109
122
|
if (plugin.name === 'builtin:vite-transform' && plugin._options?.transformOptions) {
|
|
123
|
+
/*
|
|
124
|
+
* Vite's private builtin retains this mutable transform options object and does not expose a public replacement hook.
|
|
125
|
+
* Updating its one sourcemap flag prevents Oxc from allocating maps that final WX output always discards; cloning the
|
|
126
|
+
* descriptor would not update the builtin closure that reads the original object during transforms.
|
|
127
|
+
*/
|
|
110
128
|
plugin._options.transformOptions.sourcemap = false;
|
|
111
129
|
}
|
|
112
130
|
}
|
|
@@ -123,7 +141,12 @@ function createViteReporter(server) {
|
|
|
123
141
|
warnLargeChunks: false
|
|
124
142
|
});
|
|
125
143
|
}
|
|
126
|
-
|
|
144
|
+
/*
|
|
145
|
+
* once owns a mutable cached Promise, justified because getRolldownOptions may run for multiple complete generations while the
|
|
146
|
+
* runtime input and build options remain immutable for the process lifetime. Sharing the in-flight/result Promise prevents
|
|
147
|
+
* concurrent options requests from launching duplicate nested builds; caching source instead of a Rolldown output object avoids
|
|
148
|
+
* leaking mutable bundle metadata between engines.
|
|
149
|
+
*/
|
|
127
150
|
const bundleRuntimeSource = once(async function bundleRuntimeSource() {
|
|
128
151
|
// write: false keeps this nested helper build from creating a second dist directory in the application project.
|
|
129
152
|
const result = await build({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Rolldown } from 'vite';
|
|
2
2
|
/** Identifies Rolldown's generated helper module independently of its unstable output filename. */
|
|
3
3
|
export declare const rolldownRuntimeId = "\0rolldown/runtime.js";
|
|
4
4
|
/** Resolves the direct React Reconciler dependency without assuming pnpm's layout. */
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
+
import { normalizePath } from 'vite';
|
|
2
3
|
import { normalizeModuleId } from '../../utils/modules.js';
|
|
3
4
|
import { packageRequire, resolvePackageFile } from '../../utils/packages.js';
|
|
4
5
|
/** Identifies Rolldown's generated helper module independently of its unstable output filename. */
|
|
5
6
|
export const rolldownRuntimeId = '\0rolldown/runtime.js';
|
|
6
7
|
/** Resolves the direct React Reconciler dependency without assuming pnpm's layout. */
|
|
7
|
-
export const reactReconcilerRoot =
|
|
8
|
+
export const reactReconcilerRoot = normalizePath(path.dirname(packageRequire.resolve('react-reconciler/package.json')));
|
|
8
9
|
/** Identifies the amphibious bootstrap that initializes SystemJS and serves every native shell. */
|
|
9
10
|
export const bootstrapPath = resolvePackageFile('dist/runtime/wx/amphibious/bootstrap.js');
|
|
10
11
|
/** Identifies the native transport source materialized before Rolldown finalizes content hashes. */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
+
import { normalizePath } from 'vite';
|
|
2
3
|
import { normalizeModuleId } from '../../../utils/modules.js';
|
|
3
4
|
import { collectNativeComponentAssets, nativeComponentMetaKey } from './native-component-assets.js';
|
|
4
5
|
import { transformNativeComponentInterfaces } from './native-component-interface.js';
|
|
@@ -10,7 +11,7 @@ export async function compileNativeComponentInterface({ code, id, sourcemap, add
|
|
|
10
11
|
nativeComponents.forEach((source) => {
|
|
11
12
|
addWatchFile(source.folder);
|
|
12
13
|
source.assets.forEach((asset) => {
|
|
13
|
-
addWatchFile(
|
|
14
|
+
addWatchFile(normalizePath(path.join(source.folder, asset.relativePath)));
|
|
14
15
|
});
|
|
15
16
|
});
|
|
16
17
|
const assetBytes = nativeComponents.reduce((sourceTotal, source) => {
|
|
@@ -26,6 +26,8 @@ export async function createNativeComponentOutput({ bundle, getModuleInfo }) {
|
|
|
26
26
|
fields: source.fields
|
|
27
27
|
});
|
|
28
28
|
for (const asset of source.assets) {
|
|
29
|
+
// Native folders are intentionally opaque to Rolldown, so no bundle asset contains these bytes to reuse.
|
|
30
|
+
// Read each planned source once here to transfer it into the compiler-owned output bundle.
|
|
29
31
|
files.push({
|
|
30
32
|
type: 'asset',
|
|
31
33
|
fileName: path.posix.join(outputFolder, asset.relativePath),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readdir, stat } from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import { normalizePath } from 'vite';
|
|
4
4
|
export const nativeComponentMetaKey = 'vpt:native-components';
|
|
5
5
|
/** Reads the native contribution to a transformed module's package weight. */
|
|
6
6
|
export function getNativeComponentAssetBytes(meta) {
|
|
@@ -16,7 +16,7 @@ export async function collectNativeComponentAssets(definition, interfacePath) {
|
|
|
16
16
|
await requireNativeComponentEntry(definition);
|
|
17
17
|
// This mutable accumulator is local to one traversal and avoids repeatedly copying growing asset arrays.
|
|
18
18
|
const assets = [];
|
|
19
|
-
await collectDirectory(definition.folder, [], assets,
|
|
19
|
+
await collectDirectory(definition.folder, [], assets, normalizePath(interfacePath));
|
|
20
20
|
return { ...definition, assets };
|
|
21
21
|
}
|
|
22
22
|
/** Rejects a missing or non-directory source before Rolldown starts its recursive traversal. */
|
|
@@ -65,7 +65,7 @@ async function collectDirectory(folder, segments, assets, interfacePath) {
|
|
|
65
65
|
continue;
|
|
66
66
|
}
|
|
67
67
|
const sourcePath = path.join(folder, ...entrySegments);
|
|
68
|
-
if (
|
|
68
|
+
if (normalizePath(sourcePath) === interfacePath) {
|
|
69
69
|
continue;
|
|
70
70
|
}
|
|
71
71
|
assets.push({
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { RolldownMagicString } from 'rolldown';
|
|
3
3
|
import { parseAst } from 'rolldown/parseAst';
|
|
4
|
+
import { normalizePath } from 'vite';
|
|
4
5
|
import { normalizeModuleId } from '../../../utils/modules.js';
|
|
5
6
|
import { clientTaroNativeId } from '../../client/constant.js';
|
|
6
7
|
/** Replaces native component interface calls with source-folder names and returns their static metadata. */
|
|
@@ -96,7 +97,7 @@ function parseDefinition(call, moduleId, declaredInterfaces, buildError) {
|
|
|
96
97
|
if (!entryReference) {
|
|
97
98
|
throw buildError('Native component entry must use () => import(...) with a static relative .js path');
|
|
98
99
|
}
|
|
99
|
-
const entryPath =
|
|
100
|
+
const entryPath = normalizePath(path.resolve(path.dirname(moduleId), entryReference));
|
|
100
101
|
return {
|
|
101
102
|
folder: path.posix.dirname(entryPath),
|
|
102
103
|
entry: path.posix.basename(entryPath, '.js'),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Rolldown } from 'vite';
|
|
2
2
|
import type { VitePluginTaroOptions } from '../../../../options.ts';
|
|
3
3
|
import type { GeneratedSubpackage } from '../placement/placer.ts';
|
|
4
|
-
/** Creates every
|
|
4
|
+
/** Creates every compiler-owned WX file derived from the final Rolldown bundle. */
|
|
5
5
|
export declare function createOutputFiles({ bundle, options, subpackages, getModuleInfo }: {
|
|
6
6
|
bundle: Rolldown.OutputBundle;
|
|
7
7
|
options: VitePluginTaroOptions;
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { createNativeComponentOutput } from '../native/create-native-component-output.js';
|
|
2
2
|
import { createJsonAssets } from './json.js';
|
|
3
3
|
import { createTemplateAssets } from './templates.js';
|
|
4
|
-
/** Creates every
|
|
4
|
+
/** Creates every compiler-owned WX file derived from the final Rolldown bundle. */
|
|
5
5
|
export async function createOutputFiles({ bundle, options, subpackages, getModuleInfo }) {
|
|
6
6
|
const nativeOutput = await createNativeComponentOutput({ bundle, getModuleInfo });
|
|
7
7
|
return [
|
|
8
|
+
{
|
|
9
|
+
type: 'asset',
|
|
10
|
+
fileName: 'app.wxss',
|
|
11
|
+
source: '@import "./assets/global.wxss";\n'
|
|
12
|
+
},
|
|
8
13
|
...createJsonAssets({ options, subpackages, nativeComponents: nativeOutput.registrations }),
|
|
9
14
|
...createTemplateAssets(bundle, options, nativeOutput.registrations),
|
|
10
15
|
...nativeOutput.files
|
|
@@ -11,13 +11,20 @@ import { renderCapsule } from './render/capsule.js';
|
|
|
11
11
|
import { renderNative } from './render/native.js';
|
|
12
12
|
import { materializeTransport } from './render/transport.js';
|
|
13
13
|
import { createResolver } from './resolve/resolver.js';
|
|
14
|
+
import { createWxStylePlugins } from './styles/plugins.js';
|
|
14
15
|
/** Creates the complete plugin set for the wx target. */
|
|
15
16
|
export function createWxTargetPlugins(options) {
|
|
16
|
-
|
|
17
|
+
const resolver = createResolver(options);
|
|
18
|
+
// Reuse the resolver instance's ordered application subset. Rolldown's complete input also contains bootstrap, transport,
|
|
19
|
+
// shell, and component entries; entry membership alone cannot recover which roots define the App/Page CSS cascade.
|
|
20
|
+
return [
|
|
21
|
+
createWxStylePlugins(),
|
|
22
|
+
createWxPlugin(options, resolver),
|
|
23
|
+
createWxDevelopmentPlugin(options, resolver.applicationEntryIds)
|
|
24
|
+
];
|
|
17
25
|
}
|
|
18
26
|
/** Configures the complete wx target build pipeline. */
|
|
19
|
-
function createWxPlugin(options) {
|
|
20
|
-
const resolver = createResolver(options);
|
|
27
|
+
function createWxPlugin(options, resolver) {
|
|
21
28
|
const placer = createPlacer();
|
|
22
29
|
return {
|
|
23
30
|
name: 'vpt:wx',
|
|
@@ -103,10 +110,10 @@ function createWxPlugin(options) {
|
|
|
103
110
|
},
|
|
104
111
|
generateBundle: {
|
|
105
112
|
/*
|
|
106
|
-
* This hook is registered after
|
|
113
|
+
* This hook is registered after createWxStylePlugins() and shares hook-level `order: 'post'` with the adapted
|
|
107
114
|
* upstream hooks and VPT style finalizer. Registration order therefore guarantees that the imported global
|
|
108
|
-
* stylesheet is complete before native Page/component companions are emitted. Without this order, the finalizer
|
|
109
|
-
* incomplete Tailwind output or mistake native WXSS companions for additional compiler styles.
|
|
115
|
+
* stylesheet is complete before native Page/component companions are emitted. Without this order, the finalizer
|
|
116
|
+
* could consume incomplete Tailwind output or mistake native WXSS companions for additional compiler styles.
|
|
110
117
|
*/
|
|
111
118
|
order: 'post',
|
|
112
119
|
async handler(_, bundle) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { VitePluginTaroOptions } from '../../../../options.ts';
|
|
2
2
|
/** Creates the resolver and source specializer for the wx module graph. */
|
|
3
3
|
export declare function createResolver(options: VitePluginTaroOptions): {
|
|
4
|
-
input: Record<string, string>;
|
|
5
4
|
resolveId(id: string, importer: string | undefined, projectRoot: string): string | undefined;
|
|
6
5
|
specialize(code: string, id: string, sourcemap?: boolean): Promise<import("../../../utils/transform.ts").AstTransformResult> | undefined;
|
|
6
|
+
applicationEntryIds: string[];
|
|
7
|
+
input: any;
|
|
7
8
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizePath } from 'vite';
|
|
1
2
|
import { normalizeModuleId, resolveAppComponentPath, resolvePageComponentPath } from '../../../utils/modules.js';
|
|
2
3
|
import { createAppConfig } from '../../../utils/project-config.js';
|
|
3
4
|
import { appComponentId } from '../../client/constant.js';
|
|
@@ -6,8 +7,10 @@ import { specializeBootstrap } from './specialize-bootstrap.js';
|
|
|
6
7
|
import { specializePageCapsule } from './specialize-page-capsule.js';
|
|
7
8
|
/** Creates the resolver and source specializer for the wx module graph. */
|
|
8
9
|
export function createResolver(options) {
|
|
9
|
-
const normalizedBootstrapPath =
|
|
10
|
-
const normalizedPageCapsulePath =
|
|
10
|
+
const normalizedBootstrapPath = normalizePath(bootstrapPath);
|
|
11
|
+
const normalizedPageCapsulePath = normalizePath(pageCapsulePath);
|
|
12
|
+
// Construct output input and application traversal roots together once so style order cannot drift from route order.
|
|
13
|
+
const entryGraph = createEntryGraph(options.pages);
|
|
11
14
|
// Provide constant-time route validation and access to each configured Page JSON object.
|
|
12
15
|
const pageByPath = new Map(options.pages.map((page) => [page.path, page]));
|
|
13
16
|
const privateIdResolvers = new Map([
|
|
@@ -32,7 +35,7 @@ export function createResolver(options) {
|
|
|
32
35
|
]
|
|
33
36
|
]);
|
|
34
37
|
return {
|
|
35
|
-
|
|
38
|
+
...entryGraph,
|
|
36
39
|
resolveId(id, importer, projectRoot) {
|
|
37
40
|
// Unknown IDs fall through so Vite and other plugins retain normal resolution.
|
|
38
41
|
return privateIdResolvers.get(id)?.(importer, projectRoot);
|
|
@@ -53,22 +56,34 @@ export function createResolver(options) {
|
|
|
53
56
|
}
|
|
54
57
|
};
|
|
55
58
|
}
|
|
56
|
-
/** Declares
|
|
57
|
-
function
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
59
|
+
/** Declares output entries and the ordered application subset that can own user styles. */
|
|
60
|
+
function createEntryGraph(pages) {
|
|
61
|
+
const pageEntries = pages.map((page) => {
|
|
62
|
+
return {
|
|
63
|
+
capsuleId: createRouteModuleId({ moduleId: pageCapsulePath, pagePath: page.path }),
|
|
64
|
+
capsuleName: `${page.path}-capsule`,
|
|
65
|
+
shellId: createRouteModuleId({ moduleId: pageShellPath, pagePath: page.path }),
|
|
66
|
+
shellName: `${page.path}.js`
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
return {
|
|
70
|
+
// The App owns the first global cascade layer; configured Pages follow in their declared route order.
|
|
71
|
+
applicationEntryIds: [appCapsulePath, ...pageEntries.map((entry) => entry.capsuleId)],
|
|
72
|
+
input: Object.fromEntries([
|
|
73
|
+
['bootstrap', bootstrapPath],
|
|
74
|
+
['transport', transportPath],
|
|
75
|
+
[appShellFileName, appShellPath],
|
|
76
|
+
['app-capsule', appCapsulePath],
|
|
77
|
+
[componentShellFileName, componentShellPath],
|
|
78
|
+
['component-capsule', componentCapsulePath],
|
|
79
|
+
...pageEntries.flatMap((entry) => {
|
|
80
|
+
return [
|
|
81
|
+
[entry.shellName, entry.shellId],
|
|
82
|
+
[entry.capsuleName, entry.capsuleId]
|
|
83
|
+
];
|
|
84
|
+
})
|
|
85
|
+
])
|
|
86
|
+
};
|
|
72
87
|
}
|
|
73
88
|
/** Creates one route-qualified module ID. */
|
|
74
89
|
function createRouteModuleId({ moduleId, pagePath }) {
|