vite-plugin-taro 0.5.16 → 0.6.1
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 +1 -1
- package/README.md +1 -1
- package/dist/node/plugins/client/client-taro.d.ts +2 -2
- package/dist/node/plugins/conditional/conditional-directives.d.ts +2 -2
- package/dist/node/plugins/h5/plugins.d.ts +2 -2
- package/dist/node/plugins/h5/resolver/module-resolver.d.ts +2 -2
- package/dist/node/plugins/h5/transform-app.d.ts +2 -2
- package/dist/node/plugins/h5/transform-app.js +2 -2
- package/dist/node/plugins/wx/chunk-path.d.ts +8 -0
- package/dist/node/plugins/wx/chunk-path.js +18 -0
- package/dist/node/plugins/wx/dev/dev-host.d.ts +2 -2
- package/dist/node/plugins/wx/dev/plugins.d.ts +2 -2
- package/dist/node/plugins/wx/dev/wx-dev-options.d.ts +2 -2
- package/dist/node/plugins/wx/dev/wx-dev-options.js +21 -0
- package/dist/node/plugins/wx/native/create-native-component-output.d.ts +3 -1
- package/dist/node/plugins/wx/native/create-native-component-output.js +3 -5
- package/dist/node/plugins/wx/output/files.d.ts +5 -4
- package/dist/node/plugins/wx/output/files.js +2 -2
- package/dist/node/plugins/wx/output/json.d.ts +4 -4
- package/dist/node/plugins/wx/output/json.js +2 -2
- package/dist/node/plugins/wx/output/templates.d.ts +2 -2
- package/dist/node/plugins/wx/placer/placement.d.ts +50 -0
- package/dist/node/plugins/wx/placer/placement.js +245 -0
- package/dist/node/plugins/wx/placer/placer.d.ts +60 -0
- package/dist/node/plugins/wx/placer/placer.js +123 -0
- package/dist/node/plugins/wx/plugins.d.ts +2 -2
- package/dist/node/plugins/wx/plugins.js +16 -16
- package/dist/node/plugins/wx/render/capsule-wrapper.js +3 -3
- package/dist/node/plugins/wx/render/native.js +5 -5
- package/dist/node/plugins/wx/render/transport.d.ts +7 -3
- package/dist/node/plugins/wx/render/transport.js +18 -9
- package/dist/node/plugins/wx/resolve/resolver.d.ts +2 -2
- package/dist/node/plugins/wx/resolve/specialize-bootstrap.d.ts +2 -2
- package/dist/node/plugins/wx/resolve/specialize-bootstrap.js +1 -1
- package/dist/node/plugins/wx/resolve/specialize-page-capsule.d.ts +2 -2
- package/dist/node/plugins/wx/resolve/specialize-page-capsule.js +2 -2
- package/dist/node/utils/modules.d.ts +0 -2
- package/dist/node/utils/modules.js +0 -7
- package/dist/node/utils/project-config.d.ts +2 -2
- package/dist/node/vpt.d.ts +4 -0
- package/dist/node/{vite-plugin.js → vpt.js} +1 -1
- package/dist/options.d.ts +65 -13
- package/dist/runtime/h5/app.js +2 -2
- package/dist/runtime/wx/amphibious/bootstrap.js +1 -1
- package/dist/runtime/wx/amphibious/transport.js +1 -1
- package/dist/runtime/wx/capsule/page.js +1 -1
- package/dist/vite.d.ts +2 -2
- package/dist/vite.js +1 -1
- package/package.json +3 -3
- package/src/node/plugins/client/client-taro.ts +3 -3
- package/src/node/plugins/conditional/conditional-directives.ts +3 -3
- package/src/node/plugins/h5/plugins.ts +3 -3
- package/src/node/plugins/h5/resolver/module-resolver.ts +2 -2
- package/src/node/plugins/h5/transform-app.ts +5 -5
- package/src/node/plugins/wx/chunk-path.ts +22 -0
- package/src/node/plugins/wx/dev/dev-host.ts +2 -2
- package/src/node/plugins/wx/dev/plugins.ts +2 -5
- package/src/node/plugins/wx/dev/wx-dev-options.ts +23 -2
- package/src/node/plugins/wx/native/create-native-component-output.ts +6 -5
- package/src/node/plugins/wx/output/files.ts +7 -5
- package/src/node/plugins/wx/output/json.ts +9 -10
- package/src/node/plugins/wx/output/templates.ts +3 -3
- package/src/node/plugins/wx/placer/placement.ts +364 -0
- package/src/node/plugins/wx/placer/placer.ts +154 -0
- package/src/node/plugins/wx/plugins.ts +20 -20
- package/src/node/plugins/wx/render/capsule-wrapper.ts +3 -3
- package/src/node/plugins/wx/render/native.ts +5 -5
- package/src/node/plugins/wx/render/transport.ts +24 -8
- package/src/node/plugins/wx/resolve/resolver.ts +5 -5
- package/src/node/plugins/wx/resolve/specialize-bootstrap.ts +3 -3
- package/src/node/plugins/wx/resolve/specialize-page-capsule.ts +4 -4
- package/src/node/utils/modules.ts +0 -8
- package/src/node/utils/project-config.ts +2 -2
- package/src/node/{vite-plugin.ts → vpt.ts} +2 -2
- package/src/options.ts +71 -13
- package/src/runtime/h5/app.ts +4 -4
- package/src/runtime/wx/amphibious/bootstrap.ts +2 -2
- package/src/runtime/wx/amphibious/transport.ts +2 -4
- package/src/runtime/wx/capsule/page.ts +3 -8
- package/src/vite.ts +2 -2
- package/dist/node/plugins/wx/placement/placer.d.ts +0 -78
- package/dist/node/plugins/wx/placement/placer.js +0 -158
- package/dist/node/plugins/wx/placement/plan.d.ts +0 -46
- package/dist/node/plugins/wx/placement/plan.js +0 -210
- package/dist/node/vite-plugin.d.ts +0 -4
- package/src/node/plugins/wx/placement/placer.ts +0 -187
- package/src/node/plugins/wx/placement/plan.ts +0 -306
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { Plugin, Rolldown } from 'vite';
|
|
2
|
+
import { type GeneratedSubpackage, type PackageLocation } from './placement.ts';
|
|
3
|
+
export type { GeneratedSubpackage, Placement } from './placement.ts';
|
|
4
|
+
/** Placement services consumed by the later `vpt:wx` rendering and output hooks. */
|
|
5
|
+
export type WxPlacementPlugin = Plugin & Readonly<{
|
|
6
|
+
getPackageLocation(chunk: Rolldown.RenderedChunk | Rolldown.OutputChunk): PackageLocation;
|
|
7
|
+
getPhysicalChunkId(chunk: Rolldown.RenderedChunk): string;
|
|
8
|
+
getLoadMode(chunk: Rolldown.RenderedChunk): 'sync' | 'async';
|
|
9
|
+
getSubpackages(): readonly GeneratedSubpackage[];
|
|
10
|
+
}>;
|
|
11
|
+
/**
|
|
12
|
+
* Rolldown options owned by WX placement. Every field enforces a distinct output invariant. The plugin returns this object
|
|
13
|
+
* from its config hook, while direct Rolldown integration tests reuse the same value to exercise the identical lifecycle.
|
|
14
|
+
*/
|
|
15
|
+
export declare const placementRolldownOptions: {
|
|
16
|
+
/**
|
|
17
|
+
* Output-stage naming remains under Rolldown's ownership. These options establish physical candidates and hash
|
|
18
|
+
* participation only; LTHP mutates the resulting OutputChunk filenames later without replacing the chunks.
|
|
19
|
+
*/
|
|
20
|
+
output: {
|
|
21
|
+
/**
|
|
22
|
+
* Native App/Page/Component shells are files addressed directly by WeChat and must retain the exact names configured
|
|
23
|
+
* in `input`, such as `app.js` and `pages/home/index.js`. Transport is excluded even though it is CommonJS:
|
|
24
|
+
* application chunks import its content-hashed path, so it belongs with hashed runtime/capsule entries. `[hash]`
|
|
25
|
+
* remains a Rolldown placeholder here and is resolved only after renderChunk transforms finish.
|
|
26
|
+
*/
|
|
27
|
+
entryFileNames(chunk: Rolldown.PreRenderedChunk): string;
|
|
28
|
+
/**
|
|
29
|
+
* Leaves chunk identity and collision handling entirely to Rolldown. This package-neutral physical pattern deliberately
|
|
30
|
+
* contains no LTHP owner; generateBundle adds only the selected package root to the existing Rolldown filename.
|
|
31
|
+
*/
|
|
32
|
+
chunkFileNames: string;
|
|
33
|
+
/**
|
|
34
|
+
* Emits generic Rolldown assets under one collision-resistant hashed namespace. Native-component folders are not
|
|
35
|
+
* governed by this option: createNativeComponentOutput preserves their required relative filenames and relocates the
|
|
36
|
+
* complete folder beside its owning JavaScript chunk after LTHP finalization.
|
|
37
|
+
*/
|
|
38
|
+
assetFileNames: string;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Keeps every native entry's required exports while allowing Rolldown to add cross-chunk bindings created by natural code
|
|
42
|
+
* splitting. `strict` can reject those extensions; `exports-only` can merge away native boundaries; `allow-extension`
|
|
43
|
+
* preserves the shell/capsule contract without forcing source-module placement groups.
|
|
44
|
+
*/
|
|
45
|
+
preserveEntrySignatures: 'allow-extension';
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Creates the `vpt:wx-placer` lifecycle owner:
|
|
49
|
+
*
|
|
50
|
+
* 1. Its config hook installs package-neutral Rolldown names and entry-signature semantics.
|
|
51
|
+
* 2. `renderStart` atomically starts a generation in `awaiting-chunks`; no stale placement remains reachable.
|
|
52
|
+
* 3. Its first pre-order `renderChunk` creates one immutable LTHP placement from the complete tree-shaken graph.
|
|
53
|
+
* 4. `vpt:wx` asks this plugin only for package ownership, physical relocation, and native loading mode.
|
|
54
|
+
* 5. Its pre-order `generateBundle` assigns each OutputChunk its package-qualified filename and publishes app.json declarations.
|
|
55
|
+
*
|
|
56
|
+
* The discriminated state is the only generation-local mutation: `idle → awaiting-chunks → planned → finalized`. Each hook
|
|
57
|
+
* performs one whole-state transition, so stale graph state, duplicate planning, and partially reset generations are
|
|
58
|
+
* unrepresentable.
|
|
59
|
+
*/
|
|
60
|
+
export declare function createWxPlacementPlugin(): WxPlacementPlugin;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { getWxExecutionKind, isTransportModule } from '../module.js';
|
|
2
|
+
import { getNativeComponentAssetBytes } from '../native/native-component-assets.js';
|
|
3
|
+
import { createPlacement } from './placement.js';
|
|
4
|
+
/**
|
|
5
|
+
* Rolldown options owned by WX placement. Every field enforces a distinct output invariant. The plugin returns this object
|
|
6
|
+
* from its config hook, while direct Rolldown integration tests reuse the same value to exercise the identical lifecycle.
|
|
7
|
+
*/
|
|
8
|
+
export const placementRolldownOptions = {
|
|
9
|
+
/**
|
|
10
|
+
* Output-stage naming remains under Rolldown's ownership. These options establish physical candidates and hash
|
|
11
|
+
* participation only; LTHP mutates the resulting OutputChunk filenames later without replacing the chunks.
|
|
12
|
+
*/
|
|
13
|
+
output: {
|
|
14
|
+
/**
|
|
15
|
+
* Native App/Page/Component shells are files addressed directly by WeChat and must retain the exact names configured
|
|
16
|
+
* in `input`, such as `app.js` and `pages/home/index.js`. Transport is excluded even though it is CommonJS:
|
|
17
|
+
* application chunks import its content-hashed path, so it belongs with hashed runtime/capsule entries. `[hash]`
|
|
18
|
+
* remains a Rolldown placeholder here and is resolved only after renderChunk transforms finish.
|
|
19
|
+
*/
|
|
20
|
+
entryFileNames(chunk) {
|
|
21
|
+
return getWxExecutionKind(chunk) === 'native' && !isTransportModule(chunk)
|
|
22
|
+
? '[name]'
|
|
23
|
+
: 'assets/[name]-[hash].js';
|
|
24
|
+
},
|
|
25
|
+
/**
|
|
26
|
+
* Leaves chunk identity and collision handling entirely to Rolldown. This package-neutral physical pattern deliberately
|
|
27
|
+
* contains no LTHP owner; generateBundle adds only the selected package root to the existing Rolldown filename.
|
|
28
|
+
*/
|
|
29
|
+
chunkFileNames: 'assets/[name]-[hash].js',
|
|
30
|
+
/**
|
|
31
|
+
* Emits generic Rolldown assets under one collision-resistant hashed namespace. Native-component folders are not
|
|
32
|
+
* governed by this option: createNativeComponentOutput preserves their required relative filenames and relocates the
|
|
33
|
+
* complete folder beside its owning JavaScript chunk after LTHP finalization.
|
|
34
|
+
*/
|
|
35
|
+
assetFileNames: 'assets/[name]-[hash][extname]'
|
|
36
|
+
},
|
|
37
|
+
/**
|
|
38
|
+
* Keeps every native entry's required exports while allowing Rolldown to add cross-chunk bindings created by natural code
|
|
39
|
+
* splitting. `strict` can reject those extensions; `exports-only` can merge away native boundaries; `allow-extension`
|
|
40
|
+
* preserves the shell/capsule contract without forcing source-module placement groups.
|
|
41
|
+
*/
|
|
42
|
+
preserveEntrySignatures: 'allow-extension'
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Creates the `vpt:wx-placer` lifecycle owner:
|
|
46
|
+
*
|
|
47
|
+
* 1. Its config hook installs package-neutral Rolldown names and entry-signature semantics.
|
|
48
|
+
* 2. `renderStart` atomically starts a generation in `awaiting-chunks`; no stale placement remains reachable.
|
|
49
|
+
* 3. Its first pre-order `renderChunk` creates one immutable LTHP placement from the complete tree-shaken graph.
|
|
50
|
+
* 4. `vpt:wx` asks this plugin only for package ownership, physical relocation, and native loading mode.
|
|
51
|
+
* 5. Its pre-order `generateBundle` assigns each OutputChunk its package-qualified filename and publishes app.json declarations.
|
|
52
|
+
*
|
|
53
|
+
* The discriminated state is the only generation-local mutation: `idle → awaiting-chunks → planned → finalized`. Each hook
|
|
54
|
+
* performs one whole-state transition, so stale graph state, duplicate planning, and partially reset generations are
|
|
55
|
+
* unrepresentable.
|
|
56
|
+
*/
|
|
57
|
+
export function createWxPlacementPlugin() {
|
|
58
|
+
// This one mutable cell is the output-generation state machine described above; hooks replace it atomically by phase.
|
|
59
|
+
let state = { phase: 'idle' };
|
|
60
|
+
function requirePlacement() {
|
|
61
|
+
if (state.phase === 'idle' || state.phase === 'awaiting-chunks') {
|
|
62
|
+
throw new Error('wx placement is unavailable before Rolldown exposes the final chunk graph');
|
|
63
|
+
}
|
|
64
|
+
return state.placement;
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
name: 'vpt:wx-placer',
|
|
68
|
+
config() {
|
|
69
|
+
return {
|
|
70
|
+
build: {
|
|
71
|
+
rolldownOptions: placementRolldownOptions
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
},
|
|
75
|
+
renderStart() {
|
|
76
|
+
state = { phase: 'awaiting-chunks' };
|
|
77
|
+
},
|
|
78
|
+
renderChunk: {
|
|
79
|
+
order: 'pre',
|
|
80
|
+
handler(_code, _chunk, _outputOptions, meta) {
|
|
81
|
+
if (state.phase === 'planned') {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (state.phase !== 'awaiting-chunks') {
|
|
85
|
+
throw new Error(`wx placement received final chunks during the ${state.phase} phase`);
|
|
86
|
+
}
|
|
87
|
+
state = {
|
|
88
|
+
phase: 'planned',
|
|
89
|
+
placement: createPlacement({
|
|
90
|
+
chunks: meta.chunks,
|
|
91
|
+
getAdditionalModuleBytes: (moduleId) => getNativeComponentAssetBytes(this.getModuleInfo(moduleId)?.meta)
|
|
92
|
+
})
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
generateBundle: {
|
|
97
|
+
order: 'pre',
|
|
98
|
+
handler(_outputOptions, bundle) {
|
|
99
|
+
const placement = requirePlacement();
|
|
100
|
+
state = {
|
|
101
|
+
phase: 'finalized',
|
|
102
|
+
placement: placement,
|
|
103
|
+
subpackages: placement.finalize(bundle)
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
getPackageLocation(chunk) {
|
|
108
|
+
return requirePlacement().getPackageLocation(chunk);
|
|
109
|
+
},
|
|
110
|
+
getPhysicalChunkId(chunk) {
|
|
111
|
+
return requirePlacement().getPhysicalChunkId(chunk);
|
|
112
|
+
},
|
|
113
|
+
getLoadMode(chunk) {
|
|
114
|
+
return requirePlacement().getLoadMode(chunk);
|
|
115
|
+
},
|
|
116
|
+
getSubpackages() {
|
|
117
|
+
if (state.phase !== 'finalized') {
|
|
118
|
+
throw new Error('wx subpackages are unavailable before output finalization');
|
|
119
|
+
}
|
|
120
|
+
return state.subpackages;
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { PluginOption } from 'vite';
|
|
2
|
-
import type {
|
|
2
|
+
import type { VptOptions } from '../../../options.ts';
|
|
3
3
|
/** Creates the complete plugin set for the wx target. */
|
|
4
|
-
export declare function createWxTargetPlugins(options:
|
|
4
|
+
export declare function createWxTargetPlugins(options: VptOptions): PluginOption[];
|
|
@@ -4,9 +4,8 @@ import { clientTaroNativeId } from '../client/constant.js';
|
|
|
4
4
|
import { createWxDevelopmentPlugin } from './dev/plugins.js';
|
|
5
5
|
import { getWxExecutionKind, isTransportModule } from './module.js';
|
|
6
6
|
import { compileNativeComponentInterface } from './native/compile-native-component-interface.js';
|
|
7
|
-
import { getNativeComponentAssetBytes } from './native/native-component-assets.js';
|
|
8
7
|
import { createOutputFiles } from './output/files.js';
|
|
9
|
-
import {
|
|
8
|
+
import { createWxPlacementPlugin } from './placer/placer.js';
|
|
10
9
|
import { renderCapsule } from './render/capsule.js';
|
|
11
10
|
import { renderNative } from './render/native.js';
|
|
12
11
|
import { materializeTransport } from './render/transport.js';
|
|
@@ -17,15 +16,16 @@ export function createWxTargetPlugins(options) {
|
|
|
17
16
|
const resolver = createResolver(options);
|
|
18
17
|
// Reuse the resolver instance's ordered application subset. Rolldown's complete input also contains bootstrap, transport,
|
|
19
18
|
// shell, and component entries; entry membership alone cannot recover which roots define the App/Page CSS cascade.
|
|
19
|
+
const placement = createWxPlacementPlugin();
|
|
20
20
|
return [
|
|
21
|
+
placement,
|
|
21
22
|
createWxStylePlugins(),
|
|
22
|
-
createWxPlugin(options, resolver),
|
|
23
|
+
createWxPlugin(options, resolver, placement),
|
|
23
24
|
createWxDevelopmentPlugin(options, resolver.applicationEntryIds)
|
|
24
25
|
];
|
|
25
26
|
}
|
|
26
27
|
/** Configures the complete wx target build pipeline. */
|
|
27
|
-
function createWxPlugin(options, resolver) {
|
|
28
|
-
const placer = createPlacer();
|
|
28
|
+
function createWxPlugin(options, resolver, placement) {
|
|
29
29
|
return {
|
|
30
30
|
name: 'vpt:wx',
|
|
31
31
|
config(_config, _env) {
|
|
@@ -54,7 +54,8 @@ function createWxPlugin(options, resolver) {
|
|
|
54
54
|
assetsInlineLimit: 0,
|
|
55
55
|
target: esTarget,
|
|
56
56
|
rolldownOptions: {
|
|
57
|
-
|
|
57
|
+
// The dedicated vpt:wx-placer plugin owns output naming and entry-signature semantics. This plugin owns
|
|
58
|
+
// only the closed named input set of native shells, lifecycle capsules, bootstrap, and transport entries.
|
|
58
59
|
input: resolver.input
|
|
59
60
|
}
|
|
60
61
|
}
|
|
@@ -78,16 +79,10 @@ function createWxPlugin(options, resolver) {
|
|
|
78
79
|
return resolver.specialize(code, id, sourcemap);
|
|
79
80
|
}
|
|
80
81
|
},
|
|
81
|
-
renderStart() {
|
|
82
|
-
placer.analyze({
|
|
83
|
-
moduleIds: this.getModuleIds(),
|
|
84
|
-
getModuleInfo: (moduleId) => this.getModuleInfo(moduleId),
|
|
85
|
-
getAdditionalModuleBytes: (info) => getNativeComponentAssetBytes(info.meta)
|
|
86
|
-
});
|
|
87
|
-
},
|
|
88
82
|
renderChunk: {
|
|
89
83
|
order: 'post',
|
|
90
84
|
async handler(code, chunk, outputOptions, meta) {
|
|
85
|
+
// vpt:wx-placer runs first and has already created immutable placement from this complete chunk graph.
|
|
91
86
|
const executionKind = getWxExecutionKind(chunk);
|
|
92
87
|
const sourcemap = Boolean(outputOptions.sourcemap);
|
|
93
88
|
if (executionKind === 'capsule') {
|
|
@@ -101,7 +96,8 @@ function createWxPlugin(options, resolver) {
|
|
|
101
96
|
code: native.code,
|
|
102
97
|
transportChunk: chunk,
|
|
103
98
|
chunks: meta.chunks,
|
|
104
|
-
getLoadMode:
|
|
99
|
+
getLoadMode: placement.getLoadMode,
|
|
100
|
+
getPhysicalChunkId: placement.getPhysicalChunkId,
|
|
105
101
|
sourcemap
|
|
106
102
|
});
|
|
107
103
|
}
|
|
@@ -117,12 +113,16 @@ function createWxPlugin(options, resolver) {
|
|
|
117
113
|
*/
|
|
118
114
|
order: 'post',
|
|
119
115
|
async handler(_, bundle) {
|
|
120
|
-
|
|
116
|
+
// LTHP joins OutputChunks to their preliminary logical IDs and assigns Rolldown-owned physical filenames.
|
|
117
|
+
// createOutputFiles then observes those paths to relocate native component folders, emit placeholders, and
|
|
118
|
+
// declare only surviving package roots in app.json. No JavaScript chunk is manually emitted or copied.
|
|
119
|
+
const subpackages = placement.getSubpackages();
|
|
121
120
|
const outputFiles = await createOutputFiles({
|
|
122
121
|
bundle,
|
|
123
122
|
options,
|
|
124
123
|
subpackages,
|
|
125
|
-
getModuleInfo: (moduleId) => this.getModuleInfo(moduleId)
|
|
124
|
+
getModuleInfo: (moduleId) => this.getModuleInfo(moduleId),
|
|
125
|
+
getPackageLocation: placement.getPackageLocation
|
|
126
126
|
});
|
|
127
127
|
outputFiles.forEach((file) => {
|
|
128
128
|
this.emitFile(file);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { types } from '@babel/core';
|
|
2
|
-
import {
|
|
2
|
+
import { resolveLogicalChunkReference } from '../chunk-path.js';
|
|
3
3
|
/** Wraps System.register as an inert CommonJS capsule tuple with canonical final dependency IDs. */
|
|
4
4
|
export function wrapCapsulePlugin(fileName) {
|
|
5
5
|
return {
|
|
@@ -54,11 +54,11 @@ function canonicalizeStaticReference(reference, fileName) {
|
|
|
54
54
|
if (!types.isStringLiteral(reference)) {
|
|
55
55
|
throw new Error(`Expected a literal System.register dependency in ${fileName}`);
|
|
56
56
|
}
|
|
57
|
-
reference.value =
|
|
57
|
+
reference.value = resolveLogicalChunkReference(fileName, reference.value);
|
|
58
58
|
}
|
|
59
59
|
/** Resolves application literals while preserving runtime-computed IDs injected by the development runtime. */
|
|
60
60
|
function canonicalizeDynamicReference(reference, fileName) {
|
|
61
61
|
if (types.isStringLiteral(reference) && (reference.value.startsWith('./') || reference.value.startsWith('../'))) {
|
|
62
|
-
reference.value =
|
|
62
|
+
reference.value = resolveLogicalChunkReference(fileName, reference.value);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { types } from '@babel/core';
|
|
2
2
|
import transformModulesCommonjs from '@babel/plugin-transform-modules-commonjs';
|
|
3
|
-
import { resolveChunkReference } from '../../../utils/modules.js';
|
|
4
3
|
import { transformWithBabel } from '../../../utils/transform.js';
|
|
4
|
+
import { resolveLogicalChunkReference, resolvePhysicalChunkReference } from '../chunk-path.js';
|
|
5
5
|
import { getWxEntryRole } from '../module.js';
|
|
6
6
|
/** Renders a native module while activating its statically imported capsules through SystemJS. */
|
|
7
7
|
export function renderNative({ code, chunk, chunks, sourcemap }) {
|
|
@@ -17,8 +17,8 @@ function connectNativeCapsulesPlugin(fileName, chunks) {
|
|
|
17
17
|
if (!reference.startsWith('./') && !reference.startsWith('../')) {
|
|
18
18
|
return;
|
|
19
19
|
}
|
|
20
|
-
const
|
|
21
|
-
const importedChunk = chunks[
|
|
20
|
+
const physicalChunkId = resolvePhysicalChunkReference(fileName, reference);
|
|
21
|
+
const importedChunk = chunks[physicalChunkId];
|
|
22
22
|
if (!importedChunk || getWxEntryRole(importedChunk) !== 'capsule') {
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
@@ -26,12 +26,12 @@ function connectNativeCapsulesPlugin(fileName, chunks) {
|
|
|
26
26
|
if (importPath.node.specifiers.length !== 1 ||
|
|
27
27
|
!specifier ||
|
|
28
28
|
types.isImportNamespaceSpecifier(specifier)) {
|
|
29
|
-
throw new Error(`Expected one capsule value import from ${
|
|
29
|
+
throw new Error(`Expected one capsule value import from ${physicalChunkId} in ${fileName}`);
|
|
30
30
|
}
|
|
31
31
|
const imported = types.isImportDefaultSpecifier(specifier)
|
|
32
32
|
? types.identifier('default')
|
|
33
33
|
: specifier.imported;
|
|
34
|
-
const importedConfig = types.memberExpression(createSyncImport(
|
|
34
|
+
const importedConfig = types.memberExpression(createSyncImport(resolveLogicalChunkReference(fileName, reference)), types.cloneNode(imported), types.isStringLiteral(imported));
|
|
35
35
|
importPath.replaceWith(types.variableDeclaration('const', [
|
|
36
36
|
types.variableDeclarator(types.cloneNode(specifier.local), importedConfig)
|
|
37
37
|
]));
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import type { Rolldown } from 'vite';
|
|
2
2
|
import { type AstTransformResult } from '../../../utils/transform.ts';
|
|
3
3
|
/**
|
|
4
|
-
* Materializes transport while Rolldown's preliminary hash placeholders are still active
|
|
5
|
-
*
|
|
4
|
+
* Materializes transport while Rolldown's preliminary hash placeholders are still active. Each switch case deliberately has
|
|
5
|
+
* two IDs: the package-neutral preliminary filename without its `assets/` directory becomes the SystemJS registration
|
|
6
|
+
* identity, while the LTHP-selected assets/package-qualified filename becomes the literal native require path. Rolldown
|
|
7
|
+
* substitutes both hashes after this transform, so the
|
|
8
|
+
* generated transport code and its own content hash describe the exact files that `generateBundle` later materializes.
|
|
6
9
|
*
|
|
7
10
|
* This intentionally creates broad hash invalidation: changing one capsule can rename transport, then bootstrap, then
|
|
8
11
|
* chunks that import bootstrap. A Mini Program ships one application package rather than independently cached HTTP
|
|
9
12
|
* chunks, so honest content hashes and automatic graph linking are more valuable than minimizing that hash fan-out.
|
|
10
13
|
*/
|
|
11
|
-
export declare function materializeTransport({ code, transportChunk, chunks, getLoadMode, sourcemap }: {
|
|
14
|
+
export declare function materializeTransport({ code, transportChunk, chunks, getLoadMode, getPhysicalChunkId, sourcemap }: {
|
|
12
15
|
code: string;
|
|
13
16
|
transportChunk: Rolldown.RenderedChunk;
|
|
14
17
|
chunks: Readonly<Record<string, Rolldown.RenderedChunk>>;
|
|
15
18
|
getLoadMode(chunk: Rolldown.RenderedChunk): 'sync' | 'async';
|
|
19
|
+
getPhysicalChunkId?: (chunk: Rolldown.RenderedChunk) => string;
|
|
16
20
|
sourcemap?: boolean;
|
|
17
21
|
}): Promise<AstTransformResult>;
|
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { types } from '@babel/core';
|
|
3
3
|
import { replaceWithAst } from '../../../utils/transform.js';
|
|
4
|
+
import { toLogicalChunkId } from '../chunk-path.js';
|
|
4
5
|
import { getWxExecutionKind } from '../module.js';
|
|
5
|
-
const transportPlaceholder = '
|
|
6
|
+
const transportPlaceholder = '__VPT_TRANSPORT__';
|
|
6
7
|
const moduleIdParameter = 'moduleId';
|
|
7
8
|
const exportBindingParameter = 'exportBinding';
|
|
8
9
|
/**
|
|
9
|
-
* Materializes transport while Rolldown's preliminary hash placeholders are still active
|
|
10
|
-
*
|
|
10
|
+
* Materializes transport while Rolldown's preliminary hash placeholders are still active. Each switch case deliberately has
|
|
11
|
+
* two IDs: the package-neutral preliminary filename without its `assets/` directory becomes the SystemJS registration
|
|
12
|
+
* identity, while the LTHP-selected assets/package-qualified filename becomes the literal native require path. Rolldown
|
|
13
|
+
* substitutes both hashes after this transform, so the
|
|
14
|
+
* generated transport code and its own content hash describe the exact files that `generateBundle` later materializes.
|
|
11
15
|
*
|
|
12
16
|
* This intentionally creates broad hash invalidation: changing one capsule can rename transport, then bootstrap, then
|
|
13
17
|
* chunks that import bootstrap. A Mini Program ships one application package rather than independently cached HTTP
|
|
14
18
|
* chunks, so honest content hashes and automatic graph linking are more valuable than minimizing that hash fan-out.
|
|
15
19
|
*/
|
|
16
|
-
export async function materializeTransport({ code, transportChunk, chunks, getLoadMode, sourcemap = true }) {
|
|
20
|
+
export async function materializeTransport({ code, transportChunk, chunks, getLoadMode, getPhysicalChunkId = (chunk) => chunk.fileName, sourcemap = true }) {
|
|
21
|
+
const physicalTransportId = getPhysicalChunkId(transportChunk);
|
|
17
22
|
// Babel constructs and safely serializes an expression shaped like:
|
|
18
23
|
// (moduleId) => {
|
|
19
24
|
// switch (moduleId) {
|
|
@@ -28,12 +33,16 @@ export async function materializeTransport({ code, transportChunk, chunks, getLo
|
|
|
28
33
|
.sort((left, right) => left.chunk.fileName.localeCompare(right.chunk.fileName))
|
|
29
34
|
.map(({ chunk, kind }) => {
|
|
30
35
|
const loadMode = getLoadMode(chunk);
|
|
36
|
+
const logicalChunkId = toLogicalChunkId(chunk.fileName);
|
|
37
|
+
// Only native loading crosses the logical/physical boundary and receives the assets/package-qualified path.
|
|
38
|
+
const physicalChunkId = getPhysicalChunkId(chunk);
|
|
31
39
|
if (kind === 'amphibious' && loadMode !== 'sync') {
|
|
32
40
|
throw new Error(`Amphibious wx module must be in the main package: ${chunk.fileName}`);
|
|
33
41
|
}
|
|
34
42
|
return createTransportCase({
|
|
35
|
-
chunkId:
|
|
36
|
-
transportFileName:
|
|
43
|
+
chunkId: logicalChunkId,
|
|
44
|
+
transportFileName: physicalTransportId,
|
|
45
|
+
physicalChunkId: physicalChunkId,
|
|
37
46
|
loadMode,
|
|
38
47
|
kind
|
|
39
48
|
});
|
|
@@ -58,9 +67,9 @@ function getTransportedChunks(chunks) {
|
|
|
58
67
|
}
|
|
59
68
|
return transportedChunks;
|
|
60
69
|
}
|
|
61
|
-
/** Creates one
|
|
62
|
-
function createTransportCase({ chunkId, transportFileName, loadMode, kind }) {
|
|
63
|
-
const requirePath = toNativeRequirePath(transportFileName,
|
|
70
|
+
/** Creates one logical-ID switch case while keeping its physical native require argument literal. */
|
|
71
|
+
function createTransportCase({ chunkId, transportFileName, loadMode, kind, physicalChunkId }) {
|
|
72
|
+
const requirePath = toNativeRequirePath(transportFileName, physicalChunkId);
|
|
64
73
|
const requireCallee = loadMode === 'sync'
|
|
65
74
|
? types.identifier('require')
|
|
66
75
|
: types.memberExpression(types.identifier('require'), types.identifier('async'));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { VptOptions } from '../../../../options.ts';
|
|
2
2
|
/** Creates the resolver and source specializer for the wx module graph. */
|
|
3
|
-
export declare function createResolver(options:
|
|
3
|
+
export declare function createResolver(options: VptOptions): {
|
|
4
4
|
resolveId(id: string, importer: string | undefined, projectRoot: string): string | undefined;
|
|
5
5
|
specialize(code: string, id: string, sourcemap?: boolean): Promise<import("../../../utils/transform.ts").AstTransformResult> | undefined;
|
|
6
6
|
applicationEntryIds: string[];
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { VptJsonObject } from '../../../../options.ts';
|
|
2
2
|
import { type AstTransformResult } from '../../../utils/transform.ts';
|
|
3
3
|
/** Specializes the amphibious bootstrap with the shared App configuration. */
|
|
4
4
|
export declare function specializeBootstrap({ code, id, appConfig, sourcemap }: {
|
|
5
5
|
code: string;
|
|
6
6
|
id: string;
|
|
7
|
-
appConfig:
|
|
7
|
+
appConfig: VptJsonObject;
|
|
8
8
|
sourcemap?: boolean;
|
|
9
9
|
}): Promise<AstTransformResult>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { types } from '@babel/core';
|
|
2
2
|
import { replaceWithAst } from '../../../utils/transform.js';
|
|
3
|
-
const appConfigPlaceholder = '
|
|
3
|
+
const appConfigPlaceholder = '__VPT_APP_CONFIG__';
|
|
4
4
|
/** Specializes the amphibious bootstrap with the shared App configuration. */
|
|
5
5
|
export function specializeBootstrap({ code, id, appConfig, sourcemap = true }) {
|
|
6
6
|
return replaceWithAst(code, id, {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { VptPageOption } from '../../../../options.ts';
|
|
2
2
|
import { type AstTransformResult } from '../../../utils/transform.ts';
|
|
3
3
|
/** Specializes the Page capsule for one configured route. */
|
|
4
4
|
export declare function specializePageCapsule({ code, id, page, sourcemap }: {
|
|
5
5
|
code: string;
|
|
6
6
|
id: string;
|
|
7
|
-
page:
|
|
7
|
+
page: VptPageOption;
|
|
8
8
|
sourcemap?: boolean;
|
|
9
9
|
}): Promise<AstTransformResult>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { types } from '@babel/core';
|
|
2
2
|
import { replaceWithAst } from '../../../utils/transform.js';
|
|
3
|
-
const pagePathPlaceholder = '
|
|
4
|
-
const pageConfigPlaceholder = '
|
|
3
|
+
const pagePathPlaceholder = '__VPT_PAGE_PATH__';
|
|
4
|
+
const pageConfigPlaceholder = '__VPT_PAGE_CONFIG__';
|
|
5
5
|
/** Specializes the Page capsule for one configured route. */
|
|
6
6
|
export function specializePageCapsule({ code, id, page, sourcemap = true }) {
|
|
7
7
|
return replaceWithAst(code, id, {
|
|
@@ -6,8 +6,6 @@ type PageComponentPathOptions = {
|
|
|
6
6
|
pagePath: string;
|
|
7
7
|
projectRoot: string;
|
|
8
8
|
};
|
|
9
|
-
/** Resolves a final relative reference to the canonical output chunk ID used by the WX module registry. */
|
|
10
|
-
export declare function resolveChunkReference(importerChunkId: string, reference: string): string;
|
|
11
9
|
/** Resolves the source file for the configured App component. */
|
|
12
10
|
export declare function resolveAppComponentPath({ appPath, projectRoot }: AppComponentPathOptions): string;
|
|
13
11
|
/** Resolves the source file for one configured Page component. */
|
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { normalizePath } from 'vite';
|
|
3
|
-
/** Resolves a final relative reference to the canonical output chunk ID used by the WX module registry. */
|
|
4
|
-
export function resolveChunkReference(importerChunkId, reference) {
|
|
5
|
-
if (!reference.startsWith('./') && !reference.startsWith('../')) {
|
|
6
|
-
throw new Error(`Expected a relative chunk reference in ${importerChunkId}: ${reference}`);
|
|
7
|
-
}
|
|
8
|
-
return path.posix.join(path.posix.dirname(importerChunkId), reference);
|
|
9
|
-
}
|
|
10
3
|
/** Resolves the source file for the configured App component. */
|
|
11
4
|
export function resolveAppComponentPath({ appPath, projectRoot }) {
|
|
12
5
|
return path.resolve(projectRoot, appPath);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { VptJsonObject, VptOptions } from '../../options.ts';
|
|
2
2
|
/** Creates shared App configuration with configured Page order as the authoritative value. */
|
|
3
|
-
export declare function createAppConfig(options:
|
|
3
|
+
export declare function createAppConfig(options: VptOptions): VptJsonObject;
|
|
@@ -4,7 +4,7 @@ import { createConditionalDirectivePlugin } from './plugins/conditional/conditio
|
|
|
4
4
|
import { createH5TargetPlugins } from './plugins/h5/plugins.js';
|
|
5
5
|
import { createWxTargetPlugins } from './plugins/wx/plugins.js';
|
|
6
6
|
/** Creates the Vite plugins for one Taro target. */
|
|
7
|
-
export default function
|
|
7
|
+
export default function vpt(options) {
|
|
8
8
|
return [
|
|
9
9
|
createConditionalDirectivePlugin(options.target),
|
|
10
10
|
createClientTaroPlugin(options.target),
|
package/dist/options.d.ts
CHANGED
|
@@ -1,20 +1,72 @@
|
|
|
1
1
|
/** A JSON object used by generated target configs. */
|
|
2
|
-
export type
|
|
2
|
+
export type VptJsonObject = Record<string, unknown>;
|
|
3
3
|
/** Build target handled by this plugin. */
|
|
4
|
-
export type
|
|
4
|
+
export type VptTarget = 'wx' | 'h5';
|
|
5
5
|
/** Configures one Taro page. */
|
|
6
|
-
export type
|
|
7
|
-
/**
|
|
6
|
+
export type VptPageOption = {
|
|
7
|
+
/**
|
|
8
|
+
* Taro route and output path without a file extension.
|
|
9
|
+
*
|
|
10
|
+
* The plugin resolves the page component from `src/${path}.tsx`, relative to the Vite project root. For example,
|
|
11
|
+
* `pages/home/index` resolves to `src/pages/home/index.tsx` and is emitted under `pages/home/index` for `wx`.
|
|
12
|
+
*/
|
|
8
13
|
path: string;
|
|
9
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Target-independent Taro page configuration.
|
|
16
|
+
*
|
|
17
|
+
* For `wx`, these values form the generated `<path>.json`; the plugin augments `usingComponents` with its generated
|
|
18
|
+
* component registrations. For `h5`, the values are added to the corresponding Taro router entry.
|
|
19
|
+
*/
|
|
20
|
+
config: VptJsonObject;
|
|
10
21
|
};
|
|
11
|
-
/** Configures
|
|
12
|
-
export interface
|
|
13
|
-
|
|
22
|
+
/** Configures vpt for one build target. */
|
|
23
|
+
export interface VptOptions {
|
|
24
|
+
/**
|
|
25
|
+
* Platform produced by the current Vite invocation.
|
|
26
|
+
*
|
|
27
|
+
* Use `wx` to emit a WeChat Mini Program or `h5` to emit a browser application. The selected target controls Taro
|
|
28
|
+
* module resolution, conditional compilation, runtime bootstrapping, style processing, and output generation.
|
|
29
|
+
*/
|
|
30
|
+
target: VptTarget;
|
|
31
|
+
/**
|
|
32
|
+
* Source module that default-exports the root React application component.
|
|
33
|
+
*
|
|
34
|
+
* Relative paths are resolved from Vite's project root, for example `src/app.tsx`. The component wraps the active
|
|
35
|
+
* page through its `children` prop and is the appropriate place to import application-wide styles.
|
|
36
|
+
*/
|
|
14
37
|
app: string;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Complete ordered list of application pages.
|
|
40
|
+
*
|
|
41
|
+
* The declared order becomes the `pages` order in the generated `app.json`, the H5 route order, and the Page order
|
|
42
|
+
* in the application style cascade. Each Page source is resolved according to its `path`.
|
|
43
|
+
*/
|
|
44
|
+
pages: VptPageOption[];
|
|
45
|
+
/**
|
|
46
|
+
* Target-independent Taro application configuration.
|
|
47
|
+
*
|
|
48
|
+
* For `wx`, these values form the generated `app.json`. For `h5`, they configure the Taro application and router.
|
|
49
|
+
* The plugin always derives `pages` from {@link pages}; caller-provided `pages`, `subPackages`, and `subpackages`
|
|
50
|
+
* values are discarded because the build pipeline owns page order and generated package placement.
|
|
51
|
+
*/
|
|
52
|
+
appJson: VptJsonObject;
|
|
53
|
+
/**
|
|
54
|
+
* WeChat DevTools project configuration written to `project.config.json` without merging.
|
|
55
|
+
*
|
|
56
|
+
* This option is required so one configuration shape can be shared between targets, but it is only emitted for a
|
|
57
|
+
* `wx` build and is ignored for `h5`.
|
|
58
|
+
*/
|
|
59
|
+
projectConfigJson: VptJsonObject;
|
|
60
|
+
/**
|
|
61
|
+
* Local WeChat DevTools overrides written to `project.private.config.json` without merging.
|
|
62
|
+
*
|
|
63
|
+
* The file is emitted only when this value is provided for a `wx` build. It is ignored for `h5`.
|
|
64
|
+
*/
|
|
65
|
+
projectPrivateConfigJson?: VptJsonObject;
|
|
66
|
+
/**
|
|
67
|
+
* WeChat Mini Program indexing rules written to `sitemap.json` without merging.
|
|
68
|
+
*
|
|
69
|
+
* The file is emitted only when this value is provided for a `wx` build. It is ignored for `h5`.
|
|
70
|
+
*/
|
|
71
|
+
sitemapJson?: VptJsonObject;
|
|
20
72
|
}
|
package/dist/runtime/h5/app.js
CHANGED
|
@@ -5,9 +5,9 @@ import ReactDOM from 'react-dom/client';
|
|
|
5
5
|
// @ts-expect-error: The H5 build resolves this private App component.
|
|
6
6
|
import AppComponent from '\0vpt:app-component';
|
|
7
7
|
const browserWindow = window;
|
|
8
|
-
const config =
|
|
8
|
+
const config = __VPT_H5_APP_CONFIG__;
|
|
9
9
|
browserWindow.__taroAppConfig = config;
|
|
10
|
-
config.routes =
|
|
10
|
+
config.routes = __VPT_H5_ROUTES__;
|
|
11
11
|
const app = createReactApp(AppComponent, React, ReactDOM, config);
|
|
12
12
|
const history = createHashHistory({ window: browserWindow });
|
|
13
13
|
handleAppMount(config, history);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import '../systemjs/system-core.js';
|
|
3
3
|
import { transport } from './transport.js';
|
|
4
4
|
/** Shares one App configuration object between the specialized bootstrap and App capsule. */
|
|
5
|
-
export const appConfig =
|
|
5
|
+
export const appConfig = __VPT_APP_CONFIG__;
|
|
6
6
|
// WX has no modulepreload transport. Genuine application import() boundaries retain System.import() and may load
|
|
7
7
|
// asynchronous subpackage or top-level-await graphs through this identity wrapper.
|
|
8
8
|
export const __vitePreload = (load) => load();
|