vite-plugin-taro 0.6.7 → 0.6.11

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 (36) hide show
  1. package/README.en.md +3 -0
  2. package/README.md +3 -0
  3. package/dist/node/plugins/wx/dev/dev-host.js +5 -0
  4. package/dist/node/plugins/wx/module/module.d.ts +6 -2
  5. package/dist/node/plugins/wx/module/module.js +12 -3
  6. package/dist/node/plugins/wx/output/files.d.ts +2 -1
  7. package/dist/node/plugins/wx/output/files.js +8 -4
  8. package/dist/node/plugins/wx/output/templates.d.ts +13 -3
  9. package/dist/node/plugins/wx/output/templates.js +107 -41
  10. package/dist/node/plugins/wx/plugins.js +1 -0
  11. package/dist/node/plugins/wx/resolve/resolver.js +2 -1
  12. package/dist/node/plugins/wx/styles/plugins.js +19 -12
  13. package/dist/runtime/wx/capsule/component.d.ts +2 -2
  14. package/dist/runtime/wx/capsule/component.js +3 -2
  15. package/dist/runtime/wx/capsule/taro-runtime.d.ts +1 -1
  16. package/dist/runtime/wx/capsule/taro-runtime.js +1 -1
  17. package/dist/runtime/wx/native/component.js +1 -1
  18. package/dist/runtime/wx/native/custom-wrapper.d.ts +1 -0
  19. package/dist/runtime/wx/native/custom-wrapper.js +3 -0
  20. package/dist/runtime/wx/systemjs/system-core.js +4 -4
  21. package/package.json +30 -5
  22. package/src/node/plugins/wx/dev/dev-host.ts +5 -0
  23. package/src/node/plugins/wx/module/module.ts +14 -3
  24. package/src/node/plugins/wx/output/files.ts +9 -3
  25. package/src/node/plugins/wx/output/templates.ts +151 -56
  26. package/src/node/plugins/wx/plugins.ts +1 -0
  27. package/src/node/plugins/wx/resolve/resolver.ts +3 -0
  28. package/src/node/plugins/wx/styles/plugins.ts +20 -13
  29. package/src/runtime/wx/capsule/component.ts +3 -2
  30. package/src/runtime/wx/capsule/taro-runtime.ts +1 -1
  31. package/src/runtime/wx/native/component.ts +1 -1
  32. package/src/runtime/wx/native/custom-wrapper.ts +4 -0
  33. package/src/runtime/wx/systemjs/system-core.js +4 -4
  34. package/dist/node/plugins/wx/output/json.d.ts +0 -14
  35. package/dist/node/plugins/wx/output/json.js +0 -72
  36. package/src/node/plugins/wx/output/json.ts +0 -109
@@ -124,6 +124,11 @@ export async function createWxDevHost({
124
124
  throw result
125
125
  }
126
126
  await engine.ensureCurrentBuildFinish()
127
+ // onOutput admission happens on Rolldown's callback stack, but its style publication runs asynchronously through
128
+ // hostActions. Drain that transaction before returning control to Vite: otherwise the HTTP server can bind while the
129
+ // initial output action is still finalizing styles, causing both that action and the later listening action to observe
130
+ // the port and rotate the build identity twice.
131
+ await hostActions.waitForIdle()
127
132
  }
128
133
 
129
134
  // Vite binds the port only after initServer (and therefore the initial build) completes, so
@@ -33,9 +33,15 @@ export const componentShellFileName = 'comp.js'
33
33
  /** Identifies the synchronous recursive Component shell source. */
34
34
  export const componentShellPath = resolvePackageFile('dist/runtime/wx/native/component.js')
35
35
 
36
- /** Identifies the recursive Component capsule kept behind the native shell boundary. */
36
+ /** Identifies the recursive Component capsule shared by generated Taro component shells. */
37
37
  export const componentCapsulePath = resolvePackageFile('dist/runtime/wx/capsule/component.js')
38
38
 
39
+ /** Forces Taro's CustomWrapper native shell to emit at its configured root path. */
40
+ export const customWrapperShellFileName = 'custom-wrapper.js'
41
+
42
+ /** Identifies the synchronous CustomWrapper shell source. */
43
+ export const customWrapperShellPath = resolvePackageFile('dist/runtime/wx/native/custom-wrapper.js')
44
+
39
45
  /** Resolves the configured Page component from its route-qualified capsule importer. */
40
46
  export const pageComponentId = '\0vpt:page-component'
41
47
 
@@ -45,7 +51,7 @@ export const pageCapsuleId = '\0vpt:page-capsule'
45
51
  /** Provides the Page capsule source specialized through a stable route query. */
46
52
  export const pageCapsulePath = resolvePackageFile('dist/runtime/wx/capsule/page.js')
47
53
 
48
- /** Identifies the Taro facade shared by the App, Page, and recursive Component capsules. */
54
+ /** Identifies the Taro facade shared by the App, Page, and generated component capsules. */
49
55
  export const taroRuntimePath = resolvePackageFile('dist/runtime/wx/capsule/taro-runtime.js')
50
56
 
51
57
  /** Identifies the reusable synchronous native Page shell source. */
@@ -61,7 +67,12 @@ export type WxExecutionKind = 'native' | 'capsule' | 'amphibious'
61
67
 
62
68
  // These fixed source identities describe entry roles independently from the final execution kind. A capsule entry may,
63
69
  // for example, become amphibious when Rolldown coalesces its generated runtime into the same output chunk.
64
- const shellModuleIds: ReadonlySet<string> = new Set([appShellPath, componentShellPath, pageShellPath])
70
+ const shellModuleIds: ReadonlySet<string> = new Set([
71
+ appShellPath,
72
+ componentShellPath,
73
+ customWrapperShellPath,
74
+ pageShellPath
75
+ ])
65
76
  const capsuleModuleIds: ReadonlySet<string> = new Set([appCapsulePath, componentCapsulePath, pageCapsulePath])
66
77
  const amphibiousModuleIds: ReadonlySet<string> = new Set([bootstrapPath, rolldownRuntimeId])
67
78
  const transportModuleIds: ReadonlySet<string> = new Set([transportPath])
@@ -2,7 +2,6 @@ import type { Rolldown } from 'vite'
2
2
  import type { VptOptions } from '../../../../options.ts'
3
3
  import { createNativeComponentOutput } from '../native/create-native-component-output.ts'
4
4
  import type { GeneratedSubpackage, PackageLocation } from '../placer/placement.ts'
5
- import { createJsonAssets } from './json.ts'
6
5
  import { createTemplateAssets } from './templates.ts'
7
6
 
8
7
  /** Creates every compiler-owned WX file derived from the final Rolldown bundle. */
@@ -10,12 +9,14 @@ export async function createOutputFiles({
10
9
  bundle,
11
10
  options,
12
11
  subpackages,
12
+ isProduction,
13
13
  getModuleInfo,
14
14
  getPackageLocation
15
15
  }: {
16
16
  bundle: Rolldown.OutputBundle
17
17
  options: VptOptions
18
18
  subpackages: readonly GeneratedSubpackage[]
19
+ isProduction: boolean
19
20
  getModuleInfo: (moduleId: string) => { meta: Rolldown.CustomPluginOptions } | null
20
21
  getPackageLocation(chunk: Rolldown.OutputChunk): PackageLocation
21
22
  }): Promise<Rolldown.EmittedFile[]> {
@@ -27,8 +28,13 @@ export async function createOutputFiles({
27
28
  fileName: 'app.wxss',
28
29
  source: '@import "./assets/global.wxss";\n'
29
30
  },
30
- ...createJsonAssets({ options, subpackages, nativeComponents: nativeOutput.registrations }),
31
- ...createTemplateAssets(bundle, options, nativeOutput.registrations),
31
+ ...createTemplateAssets({
32
+ bundle: bundle,
33
+ options: options,
34
+ subpackages: subpackages,
35
+ nativeComponents: nativeOutput.registrations,
36
+ isProduction: isProduction
37
+ }),
32
38
  ...nativeOutput.files
33
39
  ]
34
40
  }
@@ -1,10 +1,11 @@
1
1
  import { recursiveMerge } from '@tarojs/helper'
2
2
  import { Weapp as WxPlatform } from '@tarojs/plugin-platform-weapp'
3
3
  import type { Rolldown } from 'vite'
4
- import type { VptJsonObject, VptOptions } from '../../../../options.ts'
4
+ import type { VptJsonObject, VptOptions, VptPageOption } from '../../../../options.ts'
5
5
  import { normalizeModuleId } from '../../../utils/modules.ts'
6
6
  import { packageRequire } from '../../../utils/packages.ts'
7
- import { renderJson } from './json.ts'
7
+ import { createAppConfig } from '../../../utils/project-config.ts'
8
+ import { type GeneratedSubpackage, isGeneratedSubpackageFile } from '../placer/placement.ts'
8
9
  import { toRootRelativePath } from './relative-root.ts'
9
10
 
10
11
  type TemplateComponentConfig = {
@@ -14,28 +15,49 @@ type TemplateComponentConfig = {
14
15
  includeAll: boolean
15
16
  }
16
17
 
18
+ type NativeComponentRegistration = {
19
+ name: string
20
+ componentPath: string
21
+ fields: readonly string[]
22
+ }
23
+
24
+ const customWrapperName = 'custom-wrapper'
17
25
  const taroComponentsModulePath = packageRequire.resolve('@tarojs/plugin-platform-weapp/dist/components-react')
18
26
 
19
- /** Creates Taro's shared WeChat templates and native WXML/WXSS companions for every Page. */
20
- export function createTemplateAssets(
21
- bundle: Rolldown.OutputBundle,
22
- options: VptOptions,
23
- nativeComponents: readonly {
24
- name: string
25
- fields: readonly string[]
26
- }[]
27
- ): Rolldown.EmittedAsset[] {
27
+ /** Creates every JSON, WXML, WXS, and Page WXSS asset owned by Taro's native rendering boundary. */
28
+ export function createTemplateAssets({
29
+ bundle,
30
+ options,
31
+ subpackages,
32
+ nativeComponents,
33
+ isProduction
34
+ }: {
35
+ bundle: Rolldown.OutputBundle
36
+ options: VptOptions
37
+ subpackages: readonly GeneratedSubpackage[]
38
+ nativeComponents: readonly NativeComponentRegistration[]
39
+ isProduction: boolean
40
+ }): Rolldown.EmittedAsset[] {
28
41
  const templateBuilder = createTemplateBuilder()
42
+ const componentConfig = collectTemplateComponentConfig(bundle, nativeComponents)
43
+ const recursiveComponentJson = createRecursiveComponentJson()
44
+
45
+ const jsonAsset = (fileName: string, value: VptJsonObject) => createJsonAsset(fileName, value, isProduction)
29
46
 
30
47
  return [
31
- createAsset(
32
- 'base.wxml',
33
- templateBuilder.buildBaseTemplate(collectTemplateComponentConfig(bundle, nativeComponents))
34
- ),
48
+ jsonAsset('app.json', createAppJson({ options, subpackages, nativeComponents })),
49
+
50
+ createAsset('base.wxml', templateBuilder.buildBaseTemplate(componentConfig)),
35
51
  createAsset('utils.wxs', templateBuilder.buildXScript()),
52
+
36
53
  createAsset('comp.wxml', templateBuilder.buildBaseComponentTemplate('.wxml')),
37
- createAsset('comp.json', renderJson(createComponentJson())),
54
+ jsonAsset('comp.json', recursiveComponentJson),
55
+
56
+ createAsset('custom-wrapper.wxml', templateBuilder.buildCustomComponentTemplate('.wxml')),
57
+ jsonAsset('custom-wrapper.json', recursiveComponentJson),
58
+
38
59
  ...options.pages.flatMap((page) => [
60
+ jsonAsset(`${page.path}.json`, createPageJson(page)),
39
61
  createAsset(
40
62
  `${page.path}.wxml`,
41
63
  templateBuilder.buildPageTemplate(toRootRelativePath(page.path, 'base.wxml'), {
@@ -44,7 +66,13 @@ export function createTemplateAssets(
44
66
  })
45
67
  ),
46
68
  createAsset(`${page.path}.wxss`, '')
47
- ])
69
+ ]),
70
+
71
+ jsonAsset('project.config.json', options.projectConfigJson),
72
+ ...(options.projectPrivateConfigJson
73
+ ? [jsonAsset('project.private.config.json', options.projectPrivateConfigJson)]
74
+ : []),
75
+ ...(options.sitemapJson ? [jsonAsset('sitemap.json', options.sitemapJson)] : [])
48
76
  ]
49
77
  }
50
78
 
@@ -68,16 +96,19 @@ export function createTemplateAssets(
68
96
  *
69
97
  * Build-time output
70
98
  * -----------------
71
- * createTemplateAssets still asks one builder for the normal five products: shared base.wxml, utils.wxs, comp.wxml,
72
- * comp.json, and each Page WXML. This adapter specializes only the two products that own the native join:
99
+ * createTemplateAssets asks one builder for shared base.wxml, utils.wxs, comp.wxml, custom-wrapper.wxml, and each Page WXML.
100
+ * This adapter specializes the products that own the native join:
73
101
  *
74
- * - shared base.wxml receives branch-local slot forwarding plus vpt_fragment and vpt_page_outlet template definitions;
102
+ * - shared base.wxml receives branch-local slot forwarding at comp boundaries plus vpt_fragment and vpt_page_outlet
103
+ * template definitions;
75
104
  * - each Page WXML replaces Taro's root:root entry with one generic comp bound to app and one caller-owned taro_tmpl bound
76
105
  * to page as that component's default slot.
77
106
  *
78
- * utils.wxs remains Taro's normal compact-node dispatcher. comp.wxml and comp.json remain Taro's generic depth-reset
79
- * component and still know only i, l, virtual-host behavior, and eh event dispatch. There is one shared template namespace,
80
- * no Page-specific base file, no App/Page mode property, and no Page object threaded through App template data.
107
+ * utils.wxs remains Taro's normal compact-node dispatcher. comp.wxml and custom-wrapper.wxml retain Taro's generic compact
108
+ * rendering contracts; their JSON companions register only recursive boundaries, while runtime configs retain standard
109
+ * event dispatch. CustomWrapper keeps Taro's Page-local ownership model and is not made slot-transparent for App wrapping.
110
+ * There is one shared template namespace, no Page-specific base file, no App/Page mode property, and no Page object threaded
111
+ * through App template data.
81
112
  *
82
113
  * First native Page
83
114
  * -----------------
@@ -100,7 +131,7 @@ export function createTemplateAssets(
100
131
  * -> comp.wxml (owns App eh, imports unchanged utils.wxs and shared base.wxml)
101
132
  * -> tmpl_0_vpt_fragment (iterates the real App compact roots in app.cn)
102
133
  * -> stock Taro templates (render App hosts and recurse through their cn arrays)
103
- * -> depth-reset <comp i="{{i}}" l="{{l}}">
134
+ * -> native recursion boundary <comp ...>
104
135
  * -> forwards <slot /> only when this compact subtree root has i.vo
105
136
  * -> tmpl_0_vpt_page_outlet at React's exact {children} position
106
137
  * -> <slot />
@@ -116,8 +147,8 @@ export function createTemplateAssets(
116
147
  * Slots transfer caller-owned light DOM only. They do not transfer the caller's named-template table or WXS modules. App
117
148
  * dispatch runs inside comp.wxml, so vpt_fragment and vpt_page_outlet must live in base.wxml imported by that component.
118
149
  * Putting those definitions in buildPageTemplate produces Page WXML that compiles, but component runtime dispatch fails with
119
- * `Template tmpl_0_vpt_fragment not found`. Shared base.wxml makes the names visible in the root and every depth-reset comp
120
- * scope and emits them once rather than once per Page.
150
+ * `Template tmpl_0_vpt_fragment not found`. Shared base.wxml makes the names visible in the root and every recursive
151
+ * component scope and emits them once rather than once per Page.
121
152
  *
122
153
  * Projection-spine ownership
123
154
  * --------------------------
@@ -125,8 +156,8 @@ export function createTemplateAssets(
125
156
  * skips the unchanged root-side suffix, gives old leaf-side nodes the ordinary host prop vo=false, and gives new ones vo=true.
126
157
  * Taro's existing lazy structural hydration runs later and therefore serializes those props without projection-specific
127
158
  * scheduler or hydrate behavior. If React replaces the outlet host while moving it, the renderer finds the unique new marker
128
- * once and caches its new ancestor array. At a depth reset, i.vo makes forwarding an O(1) local decision; WXML never searches
129
- * descendants, and Page trees instantiate no unnamed slot.
159
+ * once and caches its new ancestor array. At each depth-reset comp boundary, i.vo makes forwarding an O(1) local decision;
160
+ * WXML never searches descendants, and Page trees instantiate no unnamed slot.
130
161
  *
131
162
  * Steady-state updates and navigation
132
163
  * -----------------------------------
@@ -139,11 +170,12 @@ export function createTemplateAssets(
139
170
  *
140
171
  * Method responsibilities
141
172
  * -----------------------
142
- * 1. buildBaseTemplate wraps Taro's buildTemplate output, preserves every stock host template, guards the slot at Taro's
143
- * existing depth-reset call site with i.vo, and adds the two private definitions to the shared namespace.
173
+ * 1. buildBaseTemplate preserves stock host templates, makes each depth-reset comp boundary slot-transparent through i.vo,
174
+ * and adds the two private definitions to the shared namespace.
144
175
  * 2. buildPageTemplate owns only the Page boundary: app binding, page binding, and the single Page-content slot.
145
176
  * 3. buildXScript delegates unchanged because routing metadata already travels inside compact node i.
146
177
  * 4. buildBaseComponentTemplate delegates unchanged so recursive comp remains generic and feature-independent.
178
+ * 5. buildCustomComponentTemplate delegates unchanged so CustomWrapper renders compact children in its own native scope.
147
179
  *
148
180
  * H5 never calls this WX output builder. Its App continues to receive ordinary Fragment children and none of these native
149
181
  * data roots, templates, custom-component boundaries, or slot rules enter the browser build.
@@ -246,6 +278,10 @@ function createTemplateBuilder() {
246
278
  */
247
279
  return taroTemplateBuilder.buildBaseComponentTemplate(ext)
248
280
  },
281
+ buildCustomComponentTemplate: (ext: string) => {
282
+ // CustomWrapper renders its compact children in its own native scope; imported base templates perform dispatch.
283
+ return taroTemplateBuilder.buildCustomComponentTemplate(ext)
284
+ },
249
285
  buildPageTemplate: (baseTempPath: string, page: Record<string, unknown>) => {
250
286
  const source = taroTemplateBuilder.buildPageTemplate(baseTempPath, page)
251
287
 
@@ -267,16 +303,15 @@ function createTemplateBuilder() {
267
303
  }
268
304
  }
269
305
 
270
- /** Creates template metadata from reachable Taro hosts and native component JSX fields. */
306
+ /** Creates template metadata from reachable Taro hosts, the standard CustomWrapper boundary, and native JSX fields. */
271
307
  function collectTemplateComponentConfig(
272
308
  bundle: Rolldown.OutputBundle,
273
- nativeComponents: readonly {
274
- name: string
275
- fields: readonly string[]
276
- }[]
309
+ nativeComponents: readonly NativeComponentRegistration[]
277
310
  ): TemplateComponentConfig {
278
- // This local config accumulates names in output order before the template builder consumes it.
279
- const config: TemplateComponentConfig = {
311
+ const components = findBundleModule(bundle, taroComponentsModulePath)
312
+ const renderedComponentNames = (components?.renderedExports ?? []).map(toDashed)
313
+
314
+ return {
280
315
  includes: new Set([
281
316
  'view',
282
317
  'catch-view',
@@ -287,20 +322,16 @@ function collectTemplateComponentConfig(
287
322
  'image',
288
323
  'static-image',
289
324
  'text',
290
- 'static-text'
325
+ 'static-text',
326
+ ...renderedComponentNames.filter((name) => name !== customWrapperName)
291
327
  ]),
292
328
  exclude: new Set(),
293
- thirdPartyComponents: new Map(),
329
+ thirdPartyComponents: new Map<string, Set<string>>([
330
+ [customWrapperName, new Set<string>()],
331
+ ...nativeComponents.map((component) => [component.name, new Set(component.fields)] as const)
332
+ ]),
294
333
  includeAll: false
295
334
  }
296
- const components = findBundleModule(bundle, taroComponentsModulePath)
297
- for (const name of components?.renderedExports ?? []) {
298
- config.includes.add(toDashed(name))
299
- }
300
- for (const component of nativeComponents) {
301
- config.thirdPartyComponents.set(component.name, new Set(component.fields))
302
- }
303
- return config
304
335
  }
305
336
 
306
337
  /** Finds one module in the final chunk metadata. */
@@ -322,22 +353,86 @@ function toDashed(value: string): string {
322
353
  return value.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()
323
354
  }
324
355
 
325
- /** Creates the recursive component configuration expected by Taro's templates. */
326
- function createComponentJson(): VptJsonObject {
356
+ /** Creates App JSON with globally inherited native registrations and generated subpackages. */
357
+ function createAppJson({
358
+ options,
359
+ subpackages,
360
+ nativeComponents
361
+ }: {
362
+ options: VptOptions
363
+ subpackages: readonly GeneratedSubpackage[]
364
+ nativeComponents: readonly NativeComponentRegistration[]
365
+ }): VptJsonObject {
366
+ const appConfig = createAppConfig(options)
367
+ const nativeUsingComponents = nativeComponents.map(({ name, componentPath }) => [name, componentPath])
368
+
369
+ // Cross-package components require a placeholder while WeChat downloads their generated subpackage. Paths are
370
+ // root-absolute, so remove the leading slash before testing the output-relative subpackage prefix.
371
+ // https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages/async.html
372
+ // https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/placeholder.html
373
+ const componentPlaceholders = nativeComponents.flatMap(({ name, componentPath }) =>
374
+ isGeneratedSubpackageFile(componentPath.slice(1)) ? ([[name, 'view']] as const) : []
375
+ )
376
+
377
+ return {
378
+ ...appConfig,
379
+ ...(nativeUsingComponents.length > 0
380
+ ? {
381
+ usingComponents: {
382
+ ...(isJsonObject(appConfig.usingComponents) ? appConfig.usingComponents : {}),
383
+ ...Object.fromEntries(nativeUsingComponents)
384
+ }
385
+ }
386
+ : {}),
387
+ ...(componentPlaceholders.length > 0
388
+ ? {
389
+ componentPlaceholder: {
390
+ ...(isJsonObject(appConfig.componentPlaceholder) ? appConfig.componentPlaceholder : {}),
391
+ ...Object.fromEntries(componentPlaceholders)
392
+ }
393
+ }
394
+ : {}),
395
+ ...(subpackages.length > 0 ? { subPackages: subpackages } : {})
396
+ }
397
+ }
398
+
399
+ /** Preserves configured Page JSON and registers the generated recursive component entries. */
400
+ function createPageJson(page: VptPageOption): VptJsonObject {
401
+ const usingComponents = isJsonObject(page.config.usingComponents) ? page.config.usingComponents : {}
402
+
403
+ return {
404
+ ...page.config,
405
+ usingComponents: {
406
+ ...usingComponents,
407
+ comp: toRootRelativePath(page.path, 'comp'),
408
+ [customWrapperName]: toRootRelativePath(page.path, customWrapperName)
409
+ }
410
+ }
411
+ }
412
+
413
+ /** Creates the shared recursive component configuration used by comp and CustomWrapper. */
414
+ function createRecursiveComponentJson(): VptJsonObject {
327
415
  return {
328
416
  component: true,
329
417
  styleIsolation: 'apply-shared',
330
418
  usingComponents: {
331
- comp: './comp'
419
+ comp: './comp',
420
+ [customWrapperName]: `./${customWrapperName}`
332
421
  }
333
422
  }
334
423
  }
335
424
 
336
- /** Creates one emitted template or style asset. */
425
+ /** Tests whether a configured JSON value can be merged as an object. */
426
+ function isJsonObject(value: unknown): value is VptJsonObject {
427
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
428
+ }
429
+
430
+ /** Creates compact production JSON and readable development JSON. */
431
+ function createJsonAsset(fileName: string, value: VptJsonObject, isProduction: boolean): Rolldown.EmittedAsset {
432
+ return createAsset(fileName, isProduction ? JSON.stringify(value) : `${JSON.stringify(value, null, 4)}\n`)
433
+ }
434
+
435
+ /** Creates one emitted text asset. */
337
436
  function createAsset(fileName: string, source: string): Rolldown.EmittedAsset {
338
- return {
339
- type: 'asset',
340
- fileName,
341
- source
342
- }
437
+ return { type: 'asset', fileName: fileName, source: source }
343
438
  }
@@ -147,6 +147,7 @@ function createWxPlugin(options: VptOptions, resolver: WxResolver, placement: Wx
147
147
  bundle,
148
148
  options,
149
149
  subpackages,
150
+ isProduction: this.environment.config.isProduction,
150
151
  getModuleInfo: (moduleId) => this.getModuleInfo(moduleId),
151
152
  getPackageLocation: placement.getPackageLocation
152
153
  })
@@ -11,6 +11,8 @@ import {
11
11
  componentCapsulePath,
12
12
  componentShellFileName,
13
13
  componentShellPath,
14
+ customWrapperShellFileName,
15
+ customWrapperShellPath,
14
16
  pageCapsuleId,
15
17
  pageCapsulePath,
16
18
  pageComponentId,
@@ -107,6 +109,7 @@ function createEntryGraph(pages: readonly VptPageOption[]) {
107
109
  ['app-capsule', appCapsulePath],
108
110
  [componentShellFileName, componentShellPath],
109
111
  ['component-capsule', componentCapsulePath],
112
+ [customWrapperShellFileName, customWrapperShellPath],
110
113
  ...pageEntries.flatMap((entry) => {
111
114
  return [
112
115
  [entry.shellName, entry.shellId],
@@ -191,6 +191,19 @@ export function createWxStylePlugin(applicationEntryIds: readonly string[]): WxS
191
191
  return finalizeOutput(entryIds, styleByModuleId, context.getModuleInfo.bind(context), weappContext, javaScript)
192
192
  }
193
193
 
194
+ /** Invalidates every Tailwind root fed by one changed compiler dependency. */
195
+ const invalidateTailwindDependencies = (dependencyId: string): void => {
196
+ styleByModuleId.forEach((style, styleId) => {
197
+ if (style.tailwind?.dependencies.has(dependencyId)) {
198
+ styleByModuleId.set(styleId, {
199
+ css: style.css,
200
+ // The owning root transform replaces the generator using current source and plugin context.
201
+ tailwind: { ...style.tailwind, invalidated: true }
202
+ })
203
+ }
204
+ })
205
+ }
206
+
194
207
  /** Releases native compiler resources while retaining captured CSS needed by subsequent output callbacks. */
195
208
  const disposeTailwindRoots = (): void => {
196
209
  styleByModuleId.forEach((style, styleId) => {
@@ -282,20 +295,14 @@ export function createWxStylePlugin(applicationEntryIds: readonly string[]): WxS
282
295
  return { code: compiled.css, map: null }
283
296
  }
284
297
  },
285
- /** Marks roots whose compiler inputs changed; Rolldown still decides when those roots are transformed. */
298
+ /** Invalidates compiler state before Rolldown transforms roots selected through their watched dependencies. */
299
+ hotUpdate(update) {
300
+ invalidateTailwindDependencies(normalizeModuleId(update.file))
301
+ return update.modules
302
+ },
303
+ /** Marks roots whose compiler inputs changed for non-HMR Rolldown watch lifecycles. */
286
304
  watchChange(id) {
287
- const dependencyId = normalizeModuleId(id)
288
-
289
- // A dependency may feed multiple roots, so every retained root must be checked before the next transform wave.
290
- styleByModuleId.forEach((style, styleId) => {
291
- if (style.tailwind?.dependencies.has(dependencyId)) {
292
- styleByModuleId.set(styleId, {
293
- css: style.css,
294
- // Delay generator replacement until the owning root transform has current root source and graph context.
295
- tailwind: { ...style.tailwind, invalidated: true }
296
- })
297
- }
298
- })
305
+ invalidateTailwindDependencies(normalizeModuleId(id))
299
306
  },
300
307
  generateBundle: {
301
308
  // Vite must finish chunking and CSS extraction before VPT can finalize the complete WX output transaction.
@@ -1,6 +1,7 @@
1
- // Keep recursive Component activation behind the same App initialization barrier as Page activation.
1
+ // Keep generated recursive component activation behind the same App initialization barrier as Page activation.
2
2
  import './app.ts'
3
3
 
4
4
  import { createRecursiveComponentConfig } from './taro-runtime.ts'
5
5
 
6
- export default createRecursiveComponentConfig('comp')
6
+ export const componentConfig = createRecursiveComponentConfig('comp')
7
+ export const customWrapperConfig = createRecursiveComponentConfig('custom-wrapper')
@@ -1,6 +1,6 @@
1
1
  /** biome-ignore-all assist/source/organizeImports: keep side effect orders */
2
2
 
3
- /** Taro runtime exports shared by the App, Page, and recursive Component capsules. */
3
+ /** Taro runtime exports shared by the App, Page, and generated recursive component capsules. */
4
4
  import '@tarojs/plugin-platform-weapp/dist/runtime.js'
5
5
 
6
6
  export { createReactApp } from '@tarojs/plugin-framework-react/dist/runtime'
@@ -1,4 +1,4 @@
1
1
  import '../amphibious/bootstrap.ts'
2
- import componentConfig from '../capsule/component.ts'
2
+ import { componentConfig } from '../capsule/component.ts'
3
3
 
4
4
  Component(componentConfig)
@@ -0,0 +1,4 @@
1
+ import '../amphibious/bootstrap.ts'
2
+ import { customWrapperConfig } from '../capsule/component.ts'
3
+
4
+ Component(customWrapperConfig)
@@ -18,8 +18,8 @@
18
18
  var envGlobal = global
19
19
  var hasSymbol = typeof Symbol !== 'undefined'
20
20
 
21
- function errMsg(errCode, msg) {
22
- return (msg || '') + ' (SystemJS https://github.com/systemjs/systemjs/blob/main/docs/errors.md#' + errCode + ')'
21
+ function createMissingRegistrationError(id) {
22
+ return Error('Module did not instantiate: ' + id)
23
23
  }
24
24
 
25
25
  export { REGISTRY, systemJSPrototype }
@@ -70,7 +70,7 @@ function linkLoadSync(loader, id) {
70
70
 
71
71
  var registration = loader.instantiate(id)
72
72
  if (isThenable(registration)) throw createAsyncGraphError(id)
73
- if (!registration) throw Error(errMsg(2, id))
73
+ if (!registration) throw createMissingRegistrationError(id)
74
74
 
75
75
  // This row is intentionally mutable SystemJS-owned linking and execution state.
76
76
  var load = {
@@ -188,7 +188,7 @@ export function getOrCreateLoad(loader, id, firstParentUrl, meta) {
188
188
  })
189
189
  .then(
190
190
  function (registration) {
191
- if (!registration) throw Error(errMsg(2, id))
191
+ if (!registration) throw createMissingRegistrationError(id)
192
192
  var declared = registration[1](
193
193
  createExport(load),
194
194
  registration[1].length === 2 ? createDeclarationContext(loader, id) : undefined
@@ -1,14 +0,0 @@
1
- import type { Rolldown } from 'vite';
2
- import type { VptJsonObject, VptOptions } from '../../../../options.ts';
3
- import { type GeneratedSubpackage } from '../placer/placement.ts';
4
- /** Creates every configured native JSON asset. */
5
- export declare function createJsonAssets({ options, subpackages, nativeComponents }: {
6
- options: VptOptions;
7
- subpackages: readonly GeneratedSubpackage[];
8
- nativeComponents: readonly {
9
- name: string;
10
- componentPath: string;
11
- }[];
12
- }): Rolldown.EmittedAsset[];
13
- /** Serializes one native JSON object with stable formatting. */
14
- export declare function renderJson(value: VptJsonObject): string;
@@ -1,72 +0,0 @@
1
- import { createAppConfig } from '../../../utils/project-config.js';
2
- import { isGeneratedSubpackageFile } from '../placer/placement.js';
3
- import { toRootRelativePath } from './relative-root.js';
4
- /** Creates every configured native JSON asset. */
5
- export function createJsonAssets({ options, subpackages, nativeComponents }) {
6
- return [
7
- createJsonAsset('app.json', createAppJson({ options: options, subpackages: subpackages, nativeComponents: nativeComponents })),
8
- ...options.pages.map((page) => createJsonAsset(`${page.path}.json`, createPageJson(page))),
9
- createJsonAsset('project.config.json', options.projectConfigJson),
10
- ...(options.projectPrivateConfigJson
11
- ? [createJsonAsset('project.private.config.json', options.projectPrivateConfigJson)]
12
- : []),
13
- ...(options.sitemapJson ? [createJsonAsset('sitemap.json', options.sitemapJson)] : [])
14
- ];
15
- }
16
- /** Creates App JSON with globally inherited native registrations and generated subpackages. */
17
- function createAppJson({ options, subpackages, nativeComponents }) {
18
- const appConfig = createAppConfig(options);
19
- const nativeUsingComponents = nativeComponents.map(({ name, componentPath }) => [name, componentPath]);
20
- // Cross-package components require a placeholder while WeChat downloads their generated subpackage. Paths are
21
- // root-absolute, so remove the leading slash before testing the output-relative subpackage prefix.
22
- // https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages/async.html
23
- // https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/placeholder.html
24
- const componentPlaceholders = nativeComponents.flatMap(({ name, componentPath }) => isGeneratedSubpackageFile(componentPath.slice(1)) ? [[name, 'view']] : []);
25
- return {
26
- ...appConfig,
27
- ...(nativeUsingComponents.length > 0
28
- ? {
29
- usingComponents: {
30
- ...(isJsonObject(appConfig.usingComponents) ? appConfig.usingComponents : {}),
31
- ...Object.fromEntries(nativeUsingComponents)
32
- }
33
- }
34
- : {}),
35
- ...(componentPlaceholders.length > 0
36
- ? {
37
- componentPlaceholder: {
38
- ...(isJsonObject(appConfig.componentPlaceholder) ? appConfig.componentPlaceholder : {}),
39
- ...Object.fromEntries(componentPlaceholders)
40
- }
41
- }
42
- : {}),
43
- ...(subpackages.length > 0 ? { subPackages: subpackages } : {})
44
- };
45
- }
46
- /** Preserves configured Page JSON and registers only Taro's local recursive component entry. */
47
- function createPageJson(page) {
48
- const usingComponents = isJsonObject(page.config.usingComponents) ? page.config.usingComponents : {};
49
- return {
50
- ...page.config,
51
- usingComponents: {
52
- ...usingComponents,
53
- comp: toRootRelativePath(page.path, 'comp')
54
- }
55
- };
56
- }
57
- /** Tests whether a configured JSON value can be merged as an object. */
58
- function isJsonObject(value) {
59
- return typeof value === 'object' && value !== null && !Array.isArray(value);
60
- }
61
- /** Serializes one native JSON object with stable formatting. */
62
- export function renderJson(value) {
63
- return `${JSON.stringify(value, null, 4)}\n`;
64
- }
65
- /** Creates one native JSON asset. */
66
- function createJsonAsset(fileName, value) {
67
- return {
68
- type: 'asset',
69
- fileName,
70
- source: renderJson(value)
71
- };
72
- }