vite-plugin-taro 0.6.18 → 0.6.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/client.d.ts +2 -3
  2. package/dist/index.js +213574 -0
  3. package/dist/node/plugins/wx/dev/react-refresh.d.ts +14 -13
  4. package/dist/node/utils/packages.d.ts +2 -0
  5. package/package.json +26 -26
  6. package/dist/node/plugins/client/client-taro.js +0 -59
  7. package/dist/node/plugins/client/constant.js +0 -4
  8. package/dist/node/plugins/client/inject-taro-framework-apis.js +0 -9
  9. package/dist/node/plugins/conditional/conditional-directives.js +0 -76
  10. package/dist/node/plugins/h5/constant.js +0 -3
  11. package/dist/node/plugins/h5/create-stencil-client-adapter.js +0 -94
  12. package/dist/node/plugins/h5/plugins.js +0 -179
  13. package/dist/node/plugins/h5/resolver/module-resolver.js +0 -20
  14. package/dist/node/plugins/h5/transform-app.js +0 -48
  15. package/dist/node/plugins/tailwind/tailwind-css.js +0 -3
  16. package/dist/node/plugins/wx/dev/create-hmr-results-stream.js +0 -57
  17. package/dist/node/plugins/wx/dev/dev-host.js +0 -361
  18. package/dist/node/plugins/wx/dev/hmr-files.js +0 -56
  19. package/dist/node/plugins/wx/dev/host-actions.js +0 -58
  20. package/dist/node/plugins/wx/dev/patch-publisher.js +0 -77
  21. package/dist/node/plugins/wx/dev/plugins.js +0 -164
  22. package/dist/node/plugins/wx/dev/react-refresh.js +0 -231
  23. package/dist/node/plugins/wx/dev/runtime-reports.js +0 -45
  24. package/dist/node/plugins/wx/dev/wx-dev-options.js +0 -178
  25. package/dist/node/plugins/wx/module/chunk-path.js +0 -18
  26. package/dist/node/plugins/wx/module/module.js +0 -79
  27. package/dist/node/plugins/wx/native/compile-native-component-interface.js +0 -30
  28. package/dist/node/plugins/wx/native/create-native-component-output.js +0 -39
  29. package/dist/node/plugins/wx/native/native-component-assets.js +0 -76
  30. package/dist/node/plugins/wx/native/native-component-interface.js +0 -203
  31. package/dist/node/plugins/wx/output/files.js +0 -21
  32. package/dist/node/plugins/wx/output/relative-root.js +0 -6
  33. package/dist/node/plugins/wx/output/templates.js +0 -358
  34. package/dist/node/plugins/wx/placer/placement.js +0 -245
  35. package/dist/node/plugins/wx/placer/placer.js +0 -147
  36. package/dist/node/plugins/wx/plugins.js +0 -152
  37. package/dist/node/plugins/wx/render/capsule.js +0 -54
  38. package/dist/node/plugins/wx/render/native.js +0 -543
  39. package/dist/node/plugins/wx/render/system-js/string-editor.js +0 -94
  40. package/dist/node/plugins/wx/render/system-js/system-js.js +0 -588
  41. package/dist/node/plugins/wx/render/transport.js +0 -103
  42. package/dist/node/plugins/wx/resolve/resolver.js +0 -102
  43. package/dist/node/plugins/wx/resolve/specialize-app-capsule.js +0 -9
  44. package/dist/node/plugins/wx/resolve/specialize-page-capsule.js +0 -11
  45. package/dist/node/plugins/wx/styles/plugins.js +0 -459
  46. package/dist/node/utils/constant.js +0 -1
  47. package/dist/node/utils/memoize.js +0 -86
  48. package/dist/node/utils/modules.js +0 -22
  49. package/dist/node/utils/once.js +0 -20
  50. package/dist/node/utils/oxc-transform.js +0 -57
  51. package/dist/node/utils/packages.js +0 -9
  52. package/dist/node/utils/project-config.js +0 -8
  53. package/dist/node/utils/transform.js +0 -32
  54. package/dist/node/utils/vite.js +0 -10
  55. package/dist/node/vpt.js +0 -15
  56. package/dist/options.js +0 -1
  57. package/dist/vite.js +0 -1
  58. package/src/node/plugins/client/client-taro.ts +0 -71
  59. package/src/node/plugins/client/constant.ts +0 -5
  60. package/src/node/plugins/client/inject-taro-framework-apis.ts +0 -11
  61. package/src/node/plugins/conditional/conditional-directives.ts +0 -94
  62. package/src/node/plugins/h5/constant.ts +0 -4
  63. package/src/node/plugins/h5/create-stencil-client-adapter.ts +0 -111
  64. package/src/node/plugins/h5/plugins.ts +0 -194
  65. package/src/node/plugins/h5/resolver/module-resolver.ts +0 -33
  66. package/src/node/plugins/h5/transform-app.ts +0 -90
  67. package/src/node/plugins/tailwind/tailwind-css.ts +0 -4
  68. package/src/node/plugins/wx/dev/create-hmr-results-stream.ts +0 -71
  69. package/src/node/plugins/wx/dev/dev-host.ts +0 -453
  70. package/src/node/plugins/wx/dev/hmr-files.ts +0 -80
  71. package/src/node/plugins/wx/dev/host-actions.ts +0 -88
  72. package/src/node/plugins/wx/dev/patch-publisher.ts +0 -92
  73. package/src/node/plugins/wx/dev/plugins.ts +0 -176
  74. package/src/node/plugins/wx/dev/react-refresh.ts +0 -253
  75. package/src/node/plugins/wx/dev/runtime-reports.ts +0 -70
  76. package/src/node/plugins/wx/dev/wx-dev-options.ts +0 -226
  77. package/src/node/plugins/wx/module/chunk-path.ts +0 -22
  78. package/src/node/plugins/wx/module/module.ts +0 -110
  79. package/src/node/plugins/wx/native/compile-native-component-interface.ts +0 -48
  80. package/src/node/plugins/wx/native/create-native-component-output.ts +0 -60
  81. package/src/node/plugins/wx/native/native-component-assets.ts +0 -113
  82. package/src/node/plugins/wx/native/native-component-interface.ts +0 -267
  83. package/src/node/plugins/wx/output/files.ts +0 -40
  84. package/src/node/plugins/wx/output/relative-root.ts +0 -7
  85. package/src/node/plugins/wx/output/templates.ts +0 -448
  86. package/src/node/plugins/wx/placer/placement.ts +0 -364
  87. package/src/node/plugins/wx/placer/placer.ts +0 -180
  88. package/src/node/plugins/wx/plugins.ts +0 -183
  89. package/src/node/plugins/wx/render/capsule.ts +0 -57
  90. package/src/node/plugins/wx/render/native.ts +0 -694
  91. package/src/node/plugins/wx/render/system-js/string-editor.ts +0 -116
  92. package/src/node/plugins/wx/render/system-js/system-js.ts +0 -821
  93. package/src/node/plugins/wx/render/transport.ts +0 -173
  94. package/src/node/plugins/wx/resolve/resolver.ts +0 -145
  95. package/src/node/plugins/wx/resolve/specialize-app-capsule.ts +0 -27
  96. package/src/node/plugins/wx/resolve/specialize-page-capsule.ts +0 -29
  97. package/src/node/plugins/wx/styles/plugins.ts +0 -595
  98. package/src/node/utils/constant.ts +0 -1
  99. package/src/node/utils/memoize.ts +0 -149
  100. package/src/node/utils/modules.ts +0 -37
  101. package/src/node/utils/once.ts +0 -21
  102. package/src/node/utils/oxc-transform.ts +0 -76
  103. package/src/node/utils/packages.ts +0 -11
  104. package/src/node/utils/project-config.ts +0 -10
  105. package/src/node/utils/transform.ts +0 -48
  106. package/src/node/utils/vite.ts +0 -22
  107. package/src/node/vpt.ts +0 -18
  108. package/src/options.ts +0 -82
  109. package/src/runtime/client/taro/api.ts +0 -11
  110. package/src/runtime/client/taro/component.ts +0 -1
  111. package/src/runtime/client/taro/define-native-component.ts +0 -15
  112. package/src/runtime/h5/app.ts +0 -25
  113. package/src/runtime/h5/taro-css.d.ts +0 -3
  114. package/src/runtime/h5/taro-runtime.ts +0 -7
  115. package/src/runtime/wx/amphibious/bootstrap.ts +0 -17
  116. package/src/runtime/wx/amphibious/transport.ts +0 -8
  117. package/src/runtime/wx/capsule/app.ts +0 -12
  118. package/src/runtime/wx/capsule/component.ts +0 -7
  119. package/src/runtime/wx/capsule/page.ts +0 -29
  120. package/src/runtime/wx/capsule/taro-runtime.ts +0 -8
  121. package/src/runtime/wx/dev/dev-runtime.ts +0 -464
  122. package/src/runtime/wx/native/app.ts +0 -4
  123. package/src/runtime/wx/native/component.ts +0 -4
  124. package/src/runtime/wx/native/custom-wrapper.ts +0 -4
  125. package/src/runtime/wx/native/page.ts +0 -6
  126. package/src/runtime/wx/systemjs/LICENSE +0 -10
  127. package/src/runtime/wx/systemjs/system-core.js +0 -370
  128. package/src/runtime/wx/systemjs/system.d.ts +0 -55
  129. package/src/runtime/wx/wechat.d.ts +0 -56
  130. package/src/vite.ts +0 -2
  131. /package/dist/{vite.d.ts → index.d.ts} +0 -0
  132. /package/dist/runtime/client/taro/{define-native-component.d.ts → native.d.ts} +0 -0
  133. /package/dist/runtime/client/taro/{define-native-component.js → native.js} +0 -0
@@ -1,358 +0,0 @@
1
- import { recursiveMerge } from '@tarojs/helper';
2
- import { Weapp as WxPlatform } from '@tarojs/plugin-platform-weapp';
3
- import { normalizeModuleId } from '../../../utils/modules.js';
4
- import { packageRequire } from '../../../utils/packages.js';
5
- import { createAppConfig } from '../../../utils/project-config.js';
6
- import { isGeneratedSubpackageFile } from '../placer/placement.js';
7
- import { toRootRelativePath } from './relative-root.js';
8
- const customWrapperName = 'custom-wrapper';
9
- const taroComponentsModulePath = packageRequire.resolve('@tarojs/plugin-platform-weapp/dist/components-react');
10
- /** Creates every JSON, WXML, WXS, and Page WXSS asset owned by Taro's native rendering boundary. */
11
- export function createTemplateAssets({ bundle, options, subpackages, nativeComponents, isProduction }) {
12
- const templateBuilder = createTemplateBuilder();
13
- const componentConfig = collectTemplateComponentConfig(bundle, nativeComponents);
14
- const nativeComponentConfig = createNativeComponentConfig(nativeComponents);
15
- const recursiveComponentJson = createRecursiveComponentJson(nativeComponentConfig);
16
- const jsonAsset = (fileName, value) => createJsonAsset(fileName, value, isProduction);
17
- return [
18
- jsonAsset('app.json', createAppJson({ options, subpackages })),
19
- createAsset('base.wxml', templateBuilder.buildBaseTemplate(componentConfig)),
20
- createAsset('utils.wxs', templateBuilder.buildXScript()),
21
- createAsset('comp.wxml', templateBuilder.buildBaseComponentTemplate('.wxml')),
22
- jsonAsset('comp.json', recursiveComponentJson),
23
- createAsset('custom-wrapper.wxml', templateBuilder.buildCustomComponentTemplate('.wxml')),
24
- jsonAsset('custom-wrapper.json', recursiveComponentJson),
25
- ...options.pages.flatMap((page) => [
26
- jsonAsset(`${page.path}.json`, createPageJson(page, nativeComponentConfig)),
27
- createAsset(`${page.path}.wxml`, templateBuilder.buildPageTemplate(toRootRelativePath(page.path, 'base.wxml'), {
28
- content: page.config,
29
- path: page.path
30
- })),
31
- createAsset(`${page.path}.wxss`, '')
32
- ]),
33
- jsonAsset('project.config.json', options.projectConfigJson),
34
- ...(options.projectPrivateConfigJson
35
- ? [jsonAsset('project.private.config.json', options.projectPrivateConfigJson)]
36
- : []),
37
- ...(options.sitemapJson ? [jsonAsset('sitemap.json', options.sitemapJson)] : [])
38
- ];
39
- }
40
- /**
41
- * Adapts Taro's stock template builder to the WXML half of WX App wrapping without changing its recursive renderer.
42
- *
43
- * End-to-end contract
44
- * -------------------
45
- * React and Taro retain one in-memory ownership tree:
46
- *
47
- * App React root
48
- * -> App host records
49
- * -> vpt_page_outlet host at App {children}
50
- * -> independently scheduled Taro Page roots
51
- *
52
- * The patched WX document makes the singleton App host a TaroRootElement. App host mutations therefore batch under app.*
53
- * and fan out to every mounted native Page. Each Page root remains its own TaroRootElement and emits only page.*. The React
54
- * host renderer marks the outlet and its App ancestors with an ordinary compact `vo` prop after each commit, while patched
55
- * hydrate() stops at vpt_page_outlet. Page roots remain attached for React Context, lifecycle, events, removal, refs, effects,
56
- * and HMR without entering app data.
57
- *
58
- * Build-time output
59
- * -----------------
60
- * createTemplateAssets asks one builder for shared base.wxml, utils.wxs, comp.wxml, custom-wrapper.wxml, and each Page WXML.
61
- * This adapter specializes the products that own the native join:
62
- *
63
- * - shared base.wxml receives branch-local slot forwarding at comp boundaries plus vpt_fragment and vpt_page_outlet
64
- * template definitions;
65
- * - each Page WXML replaces Taro's root:root entry with one generic comp bound to app and one caller-owned taro_tmpl bound
66
- * to page as that component's default slot.
67
- *
68
- * utils.wxs remains Taro's normal compact-node dispatcher. comp.wxml and custom-wrapper.wxml retain Taro's generic compact
69
- * rendering contracts; their JSON companions register recursive boundaries and native components, while runtime configs
70
- * retain standard event dispatch. CustomWrapper keeps Taro's Page-local ownership model and is not made slot-transparent
71
- * for App wrapping.
72
- * There is one shared template namespace, no Page-specific base file, no App/Page mode property, and no Page object threaded
73
- * through App template data.
74
- *
75
- * First native Page
76
- * -----------------
77
- * createPageConfig starts the native Page with:
78
- *
79
- * app = { nn: 'vpt_fragment', cn: [] }
80
- * page = { cn: [] }
81
- *
82
- * nn lets unchanged comp dispatch one input object even though App JSX may produce one or many root hosts. The record
83
- * is WXML-only rather than a Taro host, so it needs no sid. After React commits the Page root below the outlet, the framework
84
- * queues a lazy hydrate(AppRoot).cn value beside the Page root's already-pending page.* payloads. Taro drains both through the
85
- * native Page's existing first setData, making App wrapping and Page content appear atomically.
86
- *
87
- * Native WXML execution
88
- * ---------------------
89
- * Data/slot ownership and named-template ownership intentionally travel through different scopes:
90
- *
91
- * Page WXML (owns app, page, Page eh, and Page-content light DOM)
92
- * -> <comp i="{{app}}"> (crosses into a virtual custom-component scope)
93
- * -> comp.wxml (owns App eh, imports unchanged utils.wxs and shared base.wxml)
94
- * -> tmpl_0_vpt_fragment (iterates the real App compact roots in app.cn)
95
- * -> stock Taro templates (render App hosts and recurse through their cn arrays)
96
- * -> native recursion boundary <comp ...>
97
- * -> forwards <slot /> only when this compact subtree root has i.vo
98
- * -> tmpl_0_vpt_page_outlet at React's exact {children} position
99
- * -> <slot />
100
- * -> caller-owned <template is="taro_tmpl" data="{{root:page}}" />
101
- * -> stock Taro templates render this native Page's page.cn records
102
- *
103
- * The virtual comp and both private templates add no native layout node. `vo` is part of the existing compact node i, not a
104
- * component property or template context. App events execute through comp.eh; slotted Page events retain the native Page's
105
- * eh. Both resolve the original Taro sid through the same event source.
106
- *
107
- * Named-template scope
108
- * --------------------
109
- * Slots transfer caller-owned light DOM only. They do not transfer the caller's named-template table or WXS modules. App
110
- * dispatch runs inside comp.wxml, so vpt_fragment and vpt_page_outlet must live in base.wxml imported by that component.
111
- * Putting those definitions in buildPageTemplate produces Page WXML that compiles, but component runtime dispatch fails with
112
- * `Template tmpl_0_vpt_fragment not found`. Shared base.wxml makes the names visible in the root and every recursive
113
- * component scope and emits them once rather than once per Page.
114
- *
115
- * Projection-spine ownership
116
- * --------------------------
117
- * React's host renderer runs after the final commit tree exists and caches the outlet-to-root Taro host ancestor array. It
118
- * skips the unchanged root-side suffix, gives old leaf-side nodes the ordinary host prop vo=false, and gives new ones vo=true.
119
- * Taro's existing lazy structural hydration runs later and therefore serializes those props without projection-specific
120
- * scheduler or hydrate behavior. If React replaces the outlet host while moving it, the renderer finds the unique new marker
121
- * once and caches its new ancestor array. At each depth-reset comp boundary, i.vo makes forwarding an O(1) local decision;
122
- * WXML never searches descendants, and Page trees instantiate no unnamed slot.
123
- *
124
- * Steady-state updates and navigation
125
- * -----------------------------------
126
- * A page.* setData updates only the caller-owned Page template inside the slot. app is not passed through that template and
127
- * comp.i does not change, so Page updates cannot invalidate App recursion. Ordinary app.* payloads and outlet-spine marker
128
- * changes remain in Taro's granular batch before it fans out to every retained native Page. Adding or removing a React Page
129
- * root mutates the outlet only in memory, and the runtime suppresses that marker's native child update. A newly pushed Page
130
- * receives the latest complete App snapshot in its initial batch, while existing and hidden Pages require no navigation
131
- * synchronization.
132
- *
133
- * Method responsibilities
134
- * -----------------------
135
- * 1. buildBaseTemplate preserves stock host templates, makes each depth-reset comp boundary slot-transparent through i.vo,
136
- * and adds the two private definitions to the shared namespace.
137
- * 2. buildPageTemplate owns only the Page boundary: app binding, page binding, and the single Page-content slot.
138
- * 3. buildXScript delegates unchanged because routing metadata already travels inside compact node i.
139
- * 4. buildBaseComponentTemplate delegates unchanged so recursive comp remains generic and feature-independent.
140
- * 5. buildCustomComponentTemplate delegates unchanged so CustomWrapper renders compact children in its own native scope.
141
- *
142
- * H5 never calls this WX output builder. Its App continues to receive ordinary Fragment children and none of these native
143
- * data roots, templates, custom-component boundaries, or slot rules enter the browser build.
144
- */
145
- /** Replaces one pinned Taro fragment and rejects absent or duplicated upstream contracts. */
146
- export function replaceExactlyOnce(source, current, replacement, description) {
147
- const firstIndex = source.indexOf(current);
148
- const duplicateIndex = firstIndex === -1 ? -1 : source.indexOf(current, firstIndex + current.length);
149
- if (firstIndex === -1 || duplicateIndex !== -1) {
150
- throw new Error(`Expected one ${description}, found ${firstIndex === -1 ? 0 : 'multiple'}`);
151
- }
152
- return `${source.slice(0, firstIndex)}${replacement}${source.slice(firstIndex + current.length)}`;
153
- }
154
- function createTemplateBuilder() {
155
- const platform = new WxPlatform({
156
- helper: {
157
- recursiveMerge
158
- },
159
- // c8 cannot observe callbacks Taro accepts but intentionally never invokes.
160
- /* c8 ignore next */
161
- modifyWebpackChain() { },
162
- /* c8 ignore next */
163
- registerPlatform() { }
164
- }, {}, {});
165
- platform.modifyTemplate({});
166
- const taroTemplateBuilder = platform.template;
167
- return {
168
- buildBaseTemplate: (componentConfig) => {
169
- const source = taroTemplateBuilder.buildTemplate(componentConfig);
170
- /*
171
- * Taro inserts recursive comp only when template depth resets. App {children} may be below any number of those
172
- * boundaries, so each boundary reads the renderer-maintained vo marker on its compact subtree root before forwarding
173
- * the caller's default slot. No App/Page mode or Page data is threaded through template scopes: Page recursion
174
- * and unrelated App branches have no marker, while the outlet spine carries the one Page-owned slot.
175
- */
176
- const slotTransparentRecursion = replaceExactlyOnce(source, '<comp i="{{i}}" l="{{l}}" />', `<comp i="{{i}}" l="{{l}}"><slot wx:if="{{i.vo}}" /></comp>`, 'recursive comp call');
177
- /*
178
- * These definitions belong in shared base.wxml rather than buildPageTemplate. Although native data is Page-owned,
179
- * the dynamic calls that render App records execute after crossing into comp.wxml's component scope. WXML slots
180
- * transfer caller-owned light DOM, not the caller's named-template table or WXS modules. comp.wxml can therefore
181
- * resolve only its own definitions and those imported from base.wxml.
182
- *
183
- * Defining the two names in Page WXML is not merely redundant: WeChat accepts that Page file at compile time, then
184
- * comp.wxml's runtime dispatch fails with `Template tmpl_0_vpt_fragment not found` because component template
185
- * resolution never searches the caller Page. Shared base.wxml is already imported by comp.wxml, makes both names
186
- * visible at every depth-reset component scope, and emits them once instead of once per generated Page.
187
- *
188
- * Page WXML can give generic comp one i object, whereas App output is a root collection. vpt_fragment bridges
189
- * those contracts without becoming a native or Taro host: its nn is only a template discriminator and its
190
- * template emits each real cn record directly. Keeping the collection behind one comp is important because that
191
- * component owns exactly one Page slot regardless of whether App rendered zero, one, or many top-level hosts.
192
- * The synthetic record itself is not keyed or event-addressable, so it deliberately has no sid. Its cn items are
193
- * different: they are real hydrated Taro elements, text nodes, or the outlet, and every one has Taro's stable sid.
194
- * wx:key="sid" matches Taro's stock root.cn loop so insertion/reordering preserves native-component instances,
195
- * sibling identity, and event-source routing instead of reusing children only by array position.
196
- *
197
- * vpt_page_outlet is the matching terminal. The patched runtime retains Page roots below that marker in memory
198
- * and serializes no children into app data, while React's host renderer marks its compact ancestor spine with vo.
199
- * The slot inserts the parent Page's separate page data at the same visual position and adds no native layout
200
- * wrapper.
201
- */
202
- return `${slotTransparentRecursion}
203
- <template name="tmpl_0_vpt_fragment">
204
- <template
205
- is="{{xs.a(0, item.nn, '')}}"
206
- data="{{i:item,c:1,l:xs.f('',item.nn)}}"
207
- wx:for="{{i.cn}}"
208
- wx:key="sid"
209
- />
210
- </template>
211
- <template name="tmpl_0_vpt_page_outlet"><slot /></template>
212
- `;
213
- },
214
- buildXScript: () => {
215
- // Alias selection and compact paths are unchanged; both App and Page records use Taro's normal node vocabulary,
216
- // and projection ownership already travels on the current i object as vo.
217
- return taroTemplateBuilder.buildXScript();
218
- },
219
- buildBaseComponentTemplate: (ext) => {
220
- /*
221
- * Keep comp generic. i is the current compact node dispatched through i.nn. l is Taro's lineage of selected
222
- * special/native aliases: xs.f records bounded/nestable ancestors and xs.a uses that history when choosing a
223
- * generated template level on non-recursive WXML platforms. The current comp.wxml restarts its local lineage from
224
- * i.nn, but l remains part of Taro's intentional depth-reset component contract and platform variants may consume
225
- * it. Preserve that upstream binding; only the new Page-root comp starts with the property's empty default. Slot
226
- * forwarding lives at this base.wxml call site, and vo already belongs to i, so comp still needs no App/Page mode,
227
- * projection property, or Page data.
228
- */
229
- return taroTemplateBuilder.buildBaseComponentTemplate(ext);
230
- },
231
- buildCustomComponentTemplate: (ext) => {
232
- // CustomWrapper renders its compact children in its own native scope; imported base templates perform dispatch.
233
- return taroTemplateBuilder.buildCustomComponentTemplate(ext);
234
- },
235
- buildPageTemplate: (baseTempPath, page) => {
236
- const source = taroTemplateBuilder.buildPageTemplate(baseTempPath, page);
237
- /*
238
- * The native Page owns both data bindings. app is the transparent single-node adapter rendered by unchanged
239
- * comp; the caller-owned taro_tmpl still reads only page and becomes comp's one default slot. A page.* update
240
- * therefore cannot enter App template scopes or a component property, while App recursion can place the Page
241
- * exactly at {children} by consuming the slot at vpt_page_outlet. The root call omits l because this native comp
242
- * starts a fresh lineage scope and its generic property already defaults to the empty string. It also emits no id:
243
- * no runtime lookup, event dispatch, ref, or selector addresses this virtual boundary.
244
- */
245
- return replaceExactlyOnce(source, '<template is="taro_tmpl" data="{{root:root}}" />', `<comp i="{{app}}"><template is="taro_tmpl" data="{{root:page}}" /></comp>`, 'Page template entry');
246
- }
247
- };
248
- }
249
- /** Creates template metadata from reachable Taro hosts, the standard CustomWrapper boundary, and native JSX fields. */
250
- function collectTemplateComponentConfig(bundle, nativeComponents) {
251
- const components = findBundleModule(bundle, taroComponentsModulePath);
252
- const renderedComponentNames = (components?.renderedExports ?? []).map(toDashed);
253
- return {
254
- includes: new Set([
255
- 'view',
256
- 'catch-view',
257
- 'static-view',
258
- 'pure-view',
259
- 'click-view',
260
- 'scroll-view',
261
- 'image',
262
- 'static-image',
263
- 'text',
264
- 'static-text',
265
- ...renderedComponentNames.filter((name) => name !== customWrapperName)
266
- ]),
267
- exclude: new Set(),
268
- thirdPartyComponents: new Map([
269
- [customWrapperName, new Set()],
270
- ...nativeComponents.map((component) => [component.name, new Set(component.fields)])
271
- ]),
272
- includeAll: false
273
- };
274
- }
275
- /** Finds one module in the final chunk metadata. */
276
- function findBundleModule(bundle, resolvedId) {
277
- const normalizedResolvedId = normalizeModuleId(resolvedId);
278
- for (const output of Object.values(bundle)) {
279
- if (output.type !== 'chunk') {
280
- continue;
281
- }
282
- const found = Object.entries(output.modules).find(([id]) => normalizeModuleId(id) === normalizedResolvedId);
283
- if (found) {
284
- return found[1];
285
- }
286
- }
287
- }
288
- /** Converts a React component export to Taro's dashed host-component name. */
289
- function toDashed(value) {
290
- return value.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
291
- }
292
- /** Creates App JSON with generated subpackages. */
293
- function createAppJson({ options, subpackages }) {
294
- return {
295
- ...createAppConfig(options),
296
- ...(subpackages.length > 0 ? { subPackages: subpackages } : {})
297
- };
298
- }
299
- /** Creates native registrations for every WXML rendering scope that can instantiate their templates. */
300
- function createNativeComponentConfig(nativeComponents) {
301
- // Cross-package components require a placeholder while WeChat downloads their generated subpackage. Paths are
302
- // root-absolute, so remove the leading slash before testing the output-relative subpackage prefix.
303
- // https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages/async.html
304
- // https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/placeholder.html
305
- return {
306
- usingComponents: Object.fromEntries(nativeComponents.map(({ name, componentPath }) => [name, componentPath])),
307
- componentPlaceholder: Object.fromEntries(nativeComponents.flatMap(({ name, componentPath }) => isGeneratedSubpackageFile(componentPath.slice(1)) ? [[name, 'view']] : []))
308
- };
309
- }
310
- /** Preserves configured Page JSON and registers its recursive and native component entries. */
311
- function createPageJson(page, nativeComponentConfig) {
312
- const usingComponents = isJsonObject(page.config.usingComponents) ? page.config.usingComponents : {};
313
- const componentPlaceholder = isJsonObject(page.config.componentPlaceholder) ? page.config.componentPlaceholder : {};
314
- const hasNativeComponentPlaceholder = Object.keys(nativeComponentConfig.componentPlaceholder).length > 0;
315
- return {
316
- ...page.config,
317
- usingComponents: {
318
- ...usingComponents,
319
- ...nativeComponentConfig.usingComponents,
320
- comp: toRootRelativePath(page.path, 'comp'),
321
- [customWrapperName]: toRootRelativePath(page.path, customWrapperName)
322
- },
323
- ...(hasNativeComponentPlaceholder
324
- ? {
325
- componentPlaceholder: {
326
- ...componentPlaceholder,
327
- ...nativeComponentConfig.componentPlaceholder
328
- }
329
- }
330
- : {})
331
- };
332
- }
333
- /** Creates the shared recursive component configuration used by comp and CustomWrapper. */
334
- function createRecursiveComponentJson(nativeComponentConfig) {
335
- const hasNativeComponentPlaceholder = Object.keys(nativeComponentConfig.componentPlaceholder).length > 0;
336
- return {
337
- component: true,
338
- styleIsolation: 'apply-shared',
339
- usingComponents: {
340
- ...nativeComponentConfig.usingComponents,
341
- comp: './comp',
342
- [customWrapperName]: `./${customWrapperName}`
343
- },
344
- ...(hasNativeComponentPlaceholder ? { componentPlaceholder: nativeComponentConfig.componentPlaceholder } : {})
345
- };
346
- }
347
- /** Tests whether a configured JSON value can be merged as an object. */
348
- function isJsonObject(value) {
349
- return typeof value === 'object' && value !== null && !Array.isArray(value);
350
- }
351
- /** Creates compact production JSON and readable development JSON. */
352
- function createJsonAsset(fileName, value, isProduction) {
353
- return createAsset(fileName, isProduction ? JSON.stringify(value) : `${JSON.stringify(value, null, 4)}\n`);
354
- }
355
- /** Creates one emitted text asset. */
356
- function createAsset(fileName, source) {
357
- return { type: 'asset', fileName: fileName, source: source };
358
- }
@@ -1,245 +0,0 @@
1
- import { createHash } from 'node:crypto';
2
- // Leave headroom below WeChat's 2M subpackage limit for rendered wrappers and native assets.
3
- export const subpackagePlanningBudget = 1_900_000;
4
- const generatedSubpackageRootPrefix = 'sub/p_';
5
- /** Shared main-package value used for every synchronously reachable chunk. */
6
- const mainPackage = { kind: 'main' };
7
- /**
8
- * Applies Load-Transition Hypergraph Partitioning to Rolldown's final preliminary chunk graph:
9
- *
10
- * 1. Sort preliminary filenames to remove callback and object-enumeration order from every later decision.
11
- * 2. Reserve every explicit entry and its complete static closure in main because native startup must load it synchronously.
12
- * 3. Treat each dynamic-import edge as one load transition; the target's static closure is that transition's hyperedge.
13
- * Nested dynamic edges remain separate transitions rather than being folded into the parent closure.
14
- * 4. Index every lazy chunk by all transitions requiring it. Shared chunks therefore carry global demand rather than being
15
- * assigned according to the first source module or dynamic root that happens to visit them.
16
- * 5. Order chunks by transition demand, estimated emitted bytes, then preliminary filename. Place each chunk once into the
17
- * fitting bin with maximum transition overlap, using best-fit remaining capacity only as a tie-breaker.
18
- * 6. Hash each bin's sorted preliminary filenames into a deterministic physical package root and return unique ownership.
19
- *
20
- * Analysis costs the sum of transition static-closure traversals. Packing scans fitting bins and intersects sparse
21
- * transition sets; its worst case is O(CBT), while practical graphs have few bins and sparse transition membership.
22
- */
23
- export function createPlacement({ chunks, getAdditionalModuleBytes }) {
24
- const chunkById = new Map(Object.entries(chunks).sort(([left], [right]) => left.localeCompare(right)));
25
- const mainChunkIds = findMainChunkIds(chunkById);
26
- const transitionsByChunk = collectTransitionsByChunk({ chunks: chunkById, mainChunkIds: mainChunkIds });
27
- const placeableChunks = [...chunkById]
28
- .filter(([chunkId]) => !mainChunkIds.has(chunkId))
29
- .map(([chunkId, chunk]) => ({
30
- chunkId: chunkId,
31
- estimatedBytes: estimateChunkBytes(chunk) +
32
- chunk.moduleIds.reduce((bytes, moduleId) => bytes + getAdditionalModuleBytes(moduleId), 0),
33
- transitions: transitionsByChunk.get(chunkId) ?? new Set()
34
- }));
35
- const subpackages = packChunks({
36
- chunks: placeableChunks,
37
- planningBudgetBytes: subpackagePlanningBudget
38
- }).map(createPackedSubpackage);
39
- // This local map accumulates the immutable plan returned to output materialization.
40
- const locationByChunk = new Map();
41
- for (const chunkId of mainChunkIds) {
42
- locationByChunk.set(chunkId, mainPackage);
43
- }
44
- for (const subpackage of subpackages) {
45
- for (const chunkId of subpackage.chunkIds) {
46
- locationByChunk.set(chunkId, subpackage);
47
- }
48
- }
49
- function getLocation(chunkId) {
50
- const location = locationByChunk.get(chunkId);
51
- if (!location) {
52
- throw new Error(`wx placement is missing final chunk: ${chunkId}`);
53
- }
54
- return location;
55
- }
56
- /** Resolves typed ownership from Rolldown's preliminary physical filename before or after finalization. */
57
- function getPackageLocation(chunk) {
58
- return getLocation('preliminaryFileName' in chunk ? chunk.preliminaryFileName : chunk.fileName);
59
- }
60
- return {
61
- getPackageLocation: getPackageLocation,
62
- /** Adds the planned package root to a physical preliminary path without changing the chunk's SystemJS identity. */
63
- getPhysicalChunkId(chunk) {
64
- const location = getPackageLocation(chunk);
65
- return location.kind === 'main' ? chunk.fileName : `${location.root}/${chunk.fileName}`;
66
- },
67
- /** Selects the native loading API directly from typed package ownership. */
68
- getLoadMode(chunk) {
69
- return getPackageLocation(chunk).kind === 'subpackage' ? 'async' : 'sync';
70
- },
71
- /** Assigns each final chunk's Rolldown-owned physical filename and declares typed owners that survived output. */
72
- finalize(bundle) {
73
- const outputChunks = Object.values(bundle).filter((output) => output.type === 'chunk');
74
- // This local mutable set deduplicates typed package owners that retain at least one final output chunk.
75
- const roots = new Set();
76
- for (const chunk of outputChunks) {
77
- // OutputChunk.fileName contains the resolved content hash. preliminaryFileName preserves the exact physical
78
- // candidate with placeholders that identified this chunk when placement was created during renderChunk.
79
- const location = getLocation(chunk.preliminaryFileName);
80
- if (location.kind !== 'subpackage') {
81
- continue;
82
- }
83
- // OutputChunk is mutable in generateBundle. Assigning fileName makes Rolldown retain all chunk metadata and
84
- // write that same chunk at its physical package path; deleting bundle keys or re-emitting would lose identity.
85
- chunk.fileName = `${location.root}/${chunk.fileName}`;
86
- roots.add(location.root);
87
- }
88
- return [...roots].sort().map((root) => ({
89
- name: root.slice(root.lastIndexOf('/') + 1),
90
- root: root,
91
- pages: []
92
- }));
93
- }
94
- };
95
- }
96
- /** Keeps every explicit output entry and its complete static chunk closure in main. */
97
- function findMainChunkIds(chunks) {
98
- const mainChunkIds = new Set();
99
- // The worklist avoids recursion and visits every eager static edge once.
100
- const pending = [...chunks].filter(([, chunk]) => chunk.isEntry).map(([chunkId]) => chunkId);
101
- while (pending.length > 0) {
102
- const chunkId = pending.pop();
103
- if (!chunkId || mainChunkIds.has(chunkId)) {
104
- continue;
105
- }
106
- const chunk = chunks.get(chunkId);
107
- if (!chunk) {
108
- continue;
109
- }
110
- mainChunkIds.add(chunkId);
111
- pending.push(...chunk.imports);
112
- }
113
- return mainChunkIds;
114
- }
115
- /** Creates every load-transition hyperedge and indexes its static closure by chunk. */
116
- function collectTransitionsByChunk({ chunks, mainChunkIds }) {
117
- const transitionsByChunk = new Map();
118
- let transitionId = 0;
119
- for (const chunk of chunks.values()) {
120
- for (const targetId of [...chunk.dynamicImports].sort()) {
121
- if (!chunks.has(targetId) || mainChunkIds.has(targetId)) {
122
- continue;
123
- }
124
- for (const chunkId of collectStaticClosure({
125
- rootId: targetId,
126
- chunks: chunks,
127
- mainChunkIds: mainChunkIds
128
- })) {
129
- const transitions = transitionsByChunk.get(chunkId) ?? new Set();
130
- transitions.add(transitionId);
131
- transitionsByChunk.set(chunkId, transitions);
132
- }
133
- transitionId++;
134
- }
135
- }
136
- return transitionsByChunk;
137
- }
138
- /** Collects one transition's static closure; nested dynamic imports remain independent transitions. */
139
- function collectStaticClosure({ rootId, chunks, mainChunkIds }) {
140
- const closure = new Set();
141
- // The worklist follows static edges only; the visited set terminates cycles.
142
- const pending = [rootId];
143
- while (pending.length > 0) {
144
- const chunkId = pending.pop();
145
- if (!chunkId || closure.has(chunkId) || mainChunkIds.has(chunkId)) {
146
- continue;
147
- }
148
- const chunk = chunks.get(chunkId);
149
- if (!chunk) {
150
- continue;
151
- }
152
- closure.add(chunkId);
153
- pending.push(...chunk.imports);
154
- }
155
- return [...closure].sort();
156
- }
157
- /** Partitions final chunks by transition overlap before best-fit capacity. */
158
- function packChunks({ chunks, planningBudgetBytes }) {
159
- const bins = [];
160
- const orderedChunks = [...chunks].sort(compareChunks);
161
- for (const chunk of orderedChunks) {
162
- const bin = chunk.estimatedBytes <= planningBudgetBytes
163
- ? (findBestBin({ bins: bins, chunk: chunk, planningBudgetBytes: planningBudgetBytes }) ??
164
- createBin(bins))
165
- : createBin(bins);
166
- placeChunk(bin, chunk);
167
- }
168
- return bins;
169
- }
170
- /** Gives globally shared transition demand priority, then size and stable preliminary filename. */
171
- function compareChunks(left, right) {
172
- return (right.transitions.size - left.transitions.size ||
173
- right.estimatedBytes - left.estimatedBytes ||
174
- left.chunkId.localeCompare(right.chunkId));
175
- }
176
- /** Chooses maximum transition overlap, then the fullest fitting package and stable creation order. */
177
- function findBestBin({ bins, chunk, planningBudgetBytes }) {
178
- let best;
179
- for (const bin of bins) {
180
- if (bin.estimatedBytes + chunk.estimatedBytes > planningBudgetBytes) {
181
- continue;
182
- }
183
- const candidate = {
184
- bin: bin,
185
- overlap: countOverlap(bin.transitions, chunk.transitions),
186
- remainingBytes: planningBudgetBytes - bin.estimatedBytes - chunk.estimatedBytes
187
- };
188
- if (!best ||
189
- candidate.overlap > best.overlap ||
190
- (candidate.overlap === best.overlap && candidate.remainingBytes < best.remainingBytes)) {
191
- best = candidate;
192
- }
193
- }
194
- return best?.bin;
195
- }
196
- /** Counts transition-package incidences removed by one candidate placement. */
197
- function countOverlap(left, right) {
198
- const [smaller, larger] = left.size <= right.size ? [left, right] : [right, left];
199
- let overlap = 0;
200
- for (const transition of smaller) {
201
- if (larger.has(transition)) {
202
- overlap++;
203
- }
204
- }
205
- return overlap;
206
- }
207
- /** Creates one planner-local mutable package. */
208
- function createBin(bins) {
209
- const bin = {
210
- chunkIds: [],
211
- estimatedBytes: 0,
212
- transitions: new Set()
213
- };
214
- bins.push(bin);
215
- return bin;
216
- }
217
- /** Applies one irreversible, non-duplicating final chunk assignment. */
218
- function placeChunk(bin, chunk) {
219
- bin.chunkIds.push(chunk.chunkId);
220
- bin.estimatedBytes += chunk.estimatedBytes;
221
- for (const transition of chunk.transitions) {
222
- bin.transitions.add(transition);
223
- }
224
- }
225
- /** Estimates final output bytes from tree-shaken modules plus a bounded generated-chunk allowance. */
226
- function estimateChunkBytes(chunk) {
227
- const renderedModuleBytes = Object.values(chunk.modules).reduce((bytes, module) => bytes + (module.code ? Buffer.byteLength(module.code, 'utf8') : 0), 0);
228
- const moduleWrapperBytes = chunk.moduleIds.length * 64;
229
- const referenceBytes = (chunk.imports.length + chunk.dynamicImports.length) * 32;
230
- return renderedModuleBytes + moduleWrapperBytes + referenceBytes + 64;
231
- }
232
- /** Freezes membership and derives a stable root from sorted preliminary filenames. */
233
- function createPackedSubpackage(bin) {
234
- const chunkIds = [...bin.chunkIds].sort();
235
- const hash = createHash('sha256').update(chunkIds.join('\0')).digest('hex').slice(0, 8);
236
- return {
237
- kind: 'subpackage',
238
- root: `${generatedSubpackageRootPrefix}${hash}`,
239
- chunkIds: chunkIds
240
- };
241
- }
242
- /** Tests the plugin-owned output prefix that physically identifies every generated subpackage. */
243
- export function isGeneratedSubpackageFile(fileName) {
244
- return fileName.startsWith(generatedSubpackageRootPrefix);
245
- }