vite-plugin-taro 0.0.2 → 0.0.4

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 (42) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +205 -54
  3. package/dist/public/components.js +1 -1
  4. package/dist/public/taro.js +8 -10
  5. package/dist/shim/h5.js +5 -6
  6. package/dist/shim/wx.js +5 -5
  7. package/dist/vite/constants.js +3 -0
  8. package/dist/vite/plugins.js +186 -0
  9. package/dist/vite/tailwindcss.js +35 -0
  10. package/dist/vite/targets/h5.js +202 -0
  11. package/dist/vite/targets/wx.js +364 -0
  12. package/dist/vite/types.js +1 -0
  13. package/dist/vite/{utils.d.ts → utils.js} +13 -4
  14. package/dist/vite/vite-plugin-taro.js +80 -0
  15. package/dist/vite.js +1 -851
  16. package/package.json +23 -24
  17. package/src/public/components.ts +1 -0
  18. package/src/public/taro.ts +10 -0
  19. package/src/shim/h5.ts +6 -0
  20. package/src/shim/wx.ts +6 -0
  21. package/src/vite/constants.ts +5 -0
  22. package/src/vite/plugins.ts +218 -0
  23. package/src/vite/tailwindcss.ts +41 -0
  24. package/src/vite/targets/h5.ts +230 -0
  25. package/src/vite/targets/wx.ts +438 -0
  26. package/{dist/vite/types.d.ts → src/vite/types.ts} +31 -21
  27. package/src/vite/utils.ts +35 -0
  28. package/src/vite/vite-plugin-taro.ts +105 -0
  29. package/src/vite.ts +2 -0
  30. package/dist/public/components.d.ts +0 -1
  31. package/dist/public/taro.js.map +0 -1
  32. package/dist/shim/h5.d.ts +0 -3
  33. package/dist/shim/wx.d.ts +0 -3
  34. package/dist/vite/constants.d.ts +0 -2
  35. package/dist/vite/plugins.d.ts +0 -8
  36. package/dist/vite/tailwindcss.d.ts +0 -3
  37. package/dist/vite/targets/h5.d.ts +0 -31
  38. package/dist/vite/targets/wx.d.ts +0 -74
  39. package/dist/vite/taro.d.ts +0 -7
  40. package/dist/vite.d.ts +0 -2
  41. package/dist/vite.js.map +0 -1
  42. /package/{dist → src}/public/taro.d.ts +0 -0
@@ -0,0 +1,438 @@
1
+ import path from 'node:path'
2
+ import { recursiveMerge } from '@tarojs/helper'
3
+ import { Weapp as WechatPlatform } from '@tarojs/plugin-platform-weapp'
4
+ import type { UserConfig } from 'vite'
5
+ import { isProd, nodeRequire } from '../constants.ts'
6
+ import type { JsonObject, VitePluginTaroBuildContext, VitePluginTaroPageOption } from '../types.ts'
7
+ import { createPageComponentImport, normalizeModuleId } from '../utils.ts'
8
+
9
+ const virtualWxAppId = 'virtual:vite-plugin-taro/wx/app'
10
+ const virtualWxCompId = 'virtual:vite-plugin-taro/wx/comp'
11
+ const virtualWxPagePrefix = 'virtual:vite-plugin-taro/wx/page/'
12
+
13
+ /**
14
+ * Checks whether an id belongs to a wx virtual module.
15
+ */
16
+ export function isWxVirtualModuleId(id: string): boolean {
17
+ return id === virtualWxAppId || id === virtualWxCompId || id.startsWith(virtualWxPagePrefix)
18
+ }
19
+
20
+ export function loadWxVirtualModule(cleanId: string, context: VitePluginTaroBuildContext): string | undefined {
21
+ if (cleanId === virtualWxAppId) {
22
+ return createWxAppEntry(context)
23
+ }
24
+
25
+ if (cleanId === virtualWxCompId) {
26
+ return createWxCompEntry()
27
+ }
28
+
29
+ if (!cleanId.startsWith(virtualWxPagePrefix)) {
30
+ return
31
+ }
32
+
33
+ const pagePath = cleanId.slice(virtualWxPagePrefix.length)
34
+ const page = context.pages.find((candidate) => candidate.path === pagePath)
35
+ if (page) {
36
+ return createWxPageEntry(page)
37
+ }
38
+ }
39
+
40
+ const taroWechatComponentsReactPath = nodeRequire.resolve('@tarojs/plugin-platform-weapp/dist/components-react')
41
+ const vitePluginTaroSourcePath = normalizeModuleId(path.dirname(nodeRequire.resolve('vite-plugin-taro/vite')))
42
+ const taroVersion = String(nodeRequire('@tarojs/runtime/package.json').version)
43
+
44
+ /**
45
+ * Configures wx target entry, output, and chunk layout.
46
+ */
47
+ export function createWxViteConfig(context: VitePluginTaroBuildContext): UserConfig {
48
+ return {
49
+ define: createWechatTaroDefines(),
50
+ // https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/webpack/MiniCombination.ts#L22-L84
51
+ resolve: {
52
+ // https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/webpack/MiniBaseConfig.ts#L44-L73
53
+ alias: [{ find: /^@tarojs\/components$/, replacement: taroWechatComponentsReactPath }]
54
+ },
55
+ build: {
56
+ target: 'es2018',
57
+ assetsInlineLimit: 1024,
58
+ cssCodeSplit: false,
59
+ minify: isProd,
60
+ rolldownOptions: {
61
+ // Start from app; page/component chunks below mirror Taro Webpack's generated entries.
62
+ input: { app: virtualWxAppId },
63
+ experimental: {
64
+ // Rolldown's dev debug comments include virtual IDs like "\0virtual:...".
65
+ // WeChat DevTools can blank-screen on those NUL markers, so disable them at the source.
66
+ attachDebugInfo: 'none'
67
+ },
68
+ output: {
69
+ format: 'cjs',
70
+ entryFileNames: '[name].js',
71
+ assetFileNames: 'assets/[name][extname]',
72
+ chunkFileNames: createWechatChunkFileName,
73
+ strictExecutionOrder: true,
74
+ codeSplitting: {
75
+ includeDependenciesRecursively: false,
76
+ minSize: 0,
77
+ // https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/webpack/MiniCombination.ts#L96-L144
78
+ groups: [
79
+ { name: 'taro', test: isWxTaroChunkModule, priority: 100 },
80
+ { name: 'vendors', test: isNodeModule, priority: 10 },
81
+ { name: 'common', minShareCount: 2, minModuleSize: 1, priority: 1 }
82
+ ]
83
+ }
84
+ }
85
+ }
86
+ }
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Creates compile-time constants expected by Taro's WeChat runtime packages.
92
+ *
93
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/webpack/MiniWebpackPlugin.ts#L67-L94
94
+ */
95
+ function createWechatTaroDefines(): Record<string, string> {
96
+ return {
97
+ 'process.env.FRAMEWORK': JSON.stringify('react'),
98
+ 'process.env.SUPPORT_TARO_POLYFILL': JSON.stringify('disabled'),
99
+ 'process.env.TARO_ENV': JSON.stringify('weapp'),
100
+ 'process.env.TARO_PLATFORM': JSON.stringify('mini'),
101
+ 'process.env.TARO_VERSION': JSON.stringify(taroVersion),
102
+ IS_H5: 'false',
103
+ IS_WEAPP: 'true',
104
+ ENABLE_ADJACENT_HTML: 'false',
105
+ ENABLE_CLONE_NODE: 'false',
106
+ ENABLE_CONTAINS: 'false',
107
+ ENABLE_INNER_HTML: 'false',
108
+ ENABLE_MUTATION_OBSERVER: 'false',
109
+ ENABLE_SIZE_APIS: 'false',
110
+ ENABLE_TEMPLATE_CONTENT: 'false'
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Checks whether a module should live in the Taro/framework base chunk.
116
+ * vite-plugin-taro support modules are kept with Taro so pages do not duplicate runtime facades.
117
+ *
118
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/webpack/MiniCombination.ts#L141-L144
119
+ */
120
+ function isWxTaroChunkModule(id: string): boolean {
121
+ const normalizedId = normalizeModuleId(id)
122
+ return normalizedId.includes('/node_modules/@tarojs/') || normalizedId.startsWith(`${vitePluginTaroSourcePath}/`)
123
+ }
124
+
125
+ /**
126
+ * Names Rolldown's helper chunk like Taro webpack's runtime chunk.
127
+ *
128
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/webpack/MiniCombination.ts#L96-L103
129
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/webpack/MiniCombination.ts#L115-L117
130
+ */
131
+ function createWechatChunkFileName(chunkInfo: { name: string }): string {
132
+ return `${chunkInfo.name === 'rolldown-runtime' ? 'runtime' : chunkInfo.name}.js`
133
+ }
134
+
135
+ /**
136
+ * Checks whether a module is a third-party dependency chunk candidate.
137
+ *
138
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/webpack/MiniCombination.ts#L132-L139
139
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-helper/src/utils.ts#L32-L36
140
+ */
141
+ function isNodeModule(id: string): boolean {
142
+ return normalizeModuleId(id).includes('/node_modules/')
143
+ }
144
+
145
+ type WechatAssetSource = string | Uint8Array
146
+
147
+ type WechatBundleModule = {
148
+ renderedExports?: string[]
149
+ }
150
+
151
+ type WechatBundleItem = {
152
+ type: 'asset' | 'chunk'
153
+ source?: WechatAssetSource
154
+ modules?: Record<string, WechatBundleModule>
155
+ }
156
+
157
+ type WechatBundle = Record<string, WechatBundleItem>
158
+
159
+ type WechatTemplateComponentConfig = {
160
+ includes: Set<string>
161
+ exclude: Set<string>
162
+ thirdPartyComponents: Map<string, Set<string>>
163
+ includeAll: boolean
164
+ }
165
+
166
+ type WechatChunkEmitter = {
167
+ emitFile(chunk: { type: 'chunk'; id: string; fileName: string; implicitlyLoadedAfterOneOf: string[] }): string
168
+ }
169
+
170
+ type WechatAssetEmitter = {
171
+ emitFile(asset: { type: 'asset'; fileName: string; source: WechatAssetSource }): string
172
+ }
173
+
174
+ /**
175
+ * Emits page and component chunks like Taro Webpack's MiniPlugin generated entries.
176
+ *
177
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/plugins/MiniPlugin.ts#L228-L243
178
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/plugins/MiniPlugin.ts#L743-L777
179
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/plugins/TaroSingleEntryPlugin.ts#L18-L38
180
+ */
181
+ export function emitWechatImplicitChunksForVirtualApp(
182
+ emitter: WechatChunkEmitter,
183
+ context: VitePluginTaroBuildContext,
184
+ cleanId: string
185
+ ): void {
186
+ if (context.target !== 'wx' || cleanId !== virtualWxAppId) return
187
+
188
+ for (const page of context.pages) {
189
+ emitter.emitFile({
190
+ type: 'chunk',
191
+ id: `${virtualWxPagePrefix}${page.path}`,
192
+ fileName: `${page.path}.js`,
193
+ implicitlyLoadedAfterOneOf: [cleanId]
194
+ })
195
+ }
196
+ emitter.emitFile({
197
+ type: 'chunk',
198
+ id: virtualWxCompId,
199
+ fileName: 'comp.js',
200
+ implicitlyLoadedAfterOneOf: [cleanId]
201
+ })
202
+ }
203
+
204
+ /**
205
+ * Builds the generated WeChat app entry that registers Taro's React App config.
206
+ * vite-plugin-taro omits Taro's generated pxTransform initialization because styles are handled by Tailwind.
207
+ *
208
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-loader/src/app.ts#L54-L63
209
+ */
210
+ export function createWxAppEntry(context: VitePluginTaroBuildContext): string {
211
+ const wechatAppConfigCode = JSON.stringify(context.appConfig)
212
+
213
+ return `import { createReactApp, ReactDOM } from 'vite-plugin-taro/shim/wx'
214
+ import React from 'react'
215
+ import AppComponent from '${context.appComponentImport}'
216
+
217
+ const appConfig = ${wechatAppConfigCode}
218
+ App(createReactApp(AppComponent, React, ReactDOM, appConfig))
219
+ `
220
+ }
221
+
222
+ /**
223
+ * Builds a generated WeChat page entry that registers Taro's Page config.
224
+ *
225
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-loader/src/page.ts#L52-L78
226
+ */
227
+ export function createWxPageEntry(pageOption: VitePluginTaroPageOption): string {
228
+ const wechatPageConfigCode = JSON.stringify(pageOption.config)
229
+ const pageComponentImport = createPageComponentImport(pageOption.path)
230
+ return `import { createPageConfig } from 'vite-plugin-taro/shim/wx'
231
+ import PageComponent from '${pageComponentImport}'
232
+
233
+ const pageConfig = ${wechatPageConfigCode}
234
+ const taroPageConfig = createPageConfig(PageComponent, '${pageOption.path}', { root: { cn: [] } }, pageConfig)
235
+ if (PageComponent && PageComponent.behaviors) {
236
+ taroPageConfig.behaviors = (taroPageConfig.behaviors || []).concat(PageComponent.behaviors)
237
+ }
238
+ Page(taroPageConfig)
239
+ `
240
+ }
241
+
242
+ /**
243
+ * Builds the generated JS companion for comp.wxml/comp.json. Without it WeChat
244
+ * can load recursive markup, but it will not have Taro's properties or `eh` event
245
+ * dispatch method.
246
+ *
247
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/template/comp.ts#L1-L4
248
+ */
249
+ export function createWxCompEntry(): string {
250
+ return `import { createRecursiveComponentConfig } from 'vite-plugin-taro/shim/wx'
251
+
252
+ Component(createRecursiveComponentConfig())
253
+ `
254
+ }
255
+
256
+ /**
257
+ * Creates Taro-style Mini Program template/config/style companion files.
258
+ *
259
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-platform-weapp/src/program.ts#L33-L55
260
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/plugins/MiniPlugin.ts#L1198-L1311
261
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/plugins/MiniPlugin.ts#L1346-L1390
262
+ */
263
+ export function emitWechatAssets(
264
+ emitter: WechatAssetEmitter,
265
+ bundle: WechatBundle,
266
+ context: VitePluginTaroBuildContext
267
+ ): void {
268
+ if (context.target !== 'wx') return
269
+ for (const asset of createWechatAssets(bundle, context)) {
270
+ emitter.emitFile({ type: 'asset', fileName: asset.fileName, source: asset.source })
271
+ }
272
+ }
273
+
274
+ function createWechatAssets(
275
+ bundle: WechatBundle,
276
+ context: VitePluginTaroBuildContext
277
+ ): { fileName: string; source: WechatAssetSource }[] {
278
+ const builder = createWechatTemplateBuilder()
279
+
280
+ return [
281
+ { fileName: 'app.json', source: stringifyJsonAsset(context.appConfig) },
282
+ { fileName: 'app.wxss', source: collectWechatBundleWxss(bundle) },
283
+ { fileName: 'base.wxml', source: builder.buildTemplate(collectWechatTemplateComponentConfig(bundle)) },
284
+ { fileName: 'utils.wxs', source: builder.buildXScript() },
285
+ { fileName: 'comp.wxml', source: builder.buildBaseComponentTemplate('.wxml') },
286
+ { fileName: 'comp.json', source: stringifyJsonAsset(createWechatCompJson()) },
287
+ { fileName: 'project.config.json', source: stringifyJsonAsset(context.projectConfigJson) },
288
+ { fileName: 'sitemap.json', source: stringifyJsonAsset(context.sitemapJson) },
289
+ ...context.pages.flatMap((page) => [
290
+ {
291
+ fileName: `${page.path}.wxml`,
292
+ source: builder.buildPageTemplate(relativeWechatRootAssetFromPage(page.path, 'base.wxml'), {
293
+ content: page.config,
294
+ path: page.path
295
+ })
296
+ },
297
+ {
298
+ fileName: `${page.path}.json`,
299
+ source: stringifyJsonAsset({
300
+ ...page.config,
301
+ usingComponents: {
302
+ comp: relativeWechatRootAssetFromPage(page.path, 'comp')
303
+ }
304
+ })
305
+ },
306
+ { fileName: `${page.path}.wxss`, source: '' }
307
+ ])
308
+ ]
309
+ }
310
+
311
+ function createWechatTemplateBuilder() {
312
+ const wechatPlatform = new WechatPlatform(
313
+ { helper: { recursiveMerge }, modifyWebpackChain() {}, registerPlatform() {} },
314
+ {},
315
+ {}
316
+ )
317
+ wechatPlatform.modifyTemplate({})
318
+ return wechatPlatform.template
319
+ }
320
+
321
+ /**
322
+ * Computes a WeChat import path from a page file to a generated root asset.
323
+ *
324
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/plugins/MiniPlugin.ts#L1270-L1298
325
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-helper/src/utils.ts#L74-L88
326
+ */
327
+ function relativeWechatRootAssetFromPage(wechatPagePath: string, wechatRootAsset: string): string {
328
+ const wechatPageDir = path.posix.dirname(wechatPagePath)
329
+ const relativePath = path.posix.relative(wechatPageDir, wechatRootAsset)
330
+ return relativePath.startsWith('.') ? relativePath : `./${relativePath}`
331
+ }
332
+
333
+ /**
334
+ * Builds Taro's template component include config from official defaults plus
335
+ * the component exports that Rolldown kept in the @tarojs/components bundle.
336
+ *
337
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/utils/component.ts#L3-L8
338
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/plugins/TaroComponentsExportsPlugin.ts#L83-L124
339
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/plugins/TaroLoadChunksPlugin.ts#L165-L180
340
+ */
341
+ function collectWechatTemplateComponentConfig(bundle: WechatBundle): WechatTemplateComponentConfig {
342
+ const wechatComponentConfig: WechatTemplateComponentConfig = {
343
+ includes: new Set([
344
+ 'view',
345
+ 'catch-view',
346
+ 'static-view',
347
+ 'pure-view',
348
+ 'click-view',
349
+ 'scroll-view',
350
+ 'image',
351
+ 'static-image',
352
+ 'text',
353
+ 'static-text'
354
+ ]),
355
+ exclude: new Set(),
356
+ thirdPartyComponents: new Map(),
357
+ includeAll: false
358
+ }
359
+
360
+ const wechatComponentsModule = findBundleModule(bundle, taroWechatComponentsReactPath)
361
+ for (const item of wechatComponentsModule?.renderedExports ?? []) {
362
+ wechatComponentConfig.includes.add(toDashed(item))
363
+ }
364
+
365
+ return wechatComponentConfig
366
+ }
367
+
368
+ function toDashed(s: string) {
369
+ return s.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()
370
+ }
371
+
372
+ /**
373
+ * Finds a module record inside the generated bundle by normalized module ID.
374
+ *
375
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/plugins/TaroComponentsExportsPlugin.ts#L83-L124
376
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/plugins/TaroLoadChunksPlugin.ts#L165-L180
377
+ */
378
+ function findBundleModule(bundle: WechatBundle, resolvedId: string): WechatBundleModule | undefined {
379
+ const normalizedResolvedId = normalizeModuleId(resolvedId)
380
+ for (const item of Object.values(bundle)) {
381
+ if (item.type !== 'chunk') {
382
+ continue
383
+ }
384
+
385
+ const found = Object.entries(item.modules ?? {}).find(([id]) => normalizeModuleId(id) === normalizedResolvedId)
386
+ if (found) {
387
+ return found[1]
388
+ }
389
+ }
390
+ }
391
+
392
+ /**
393
+ * Creates the JSON config for Taro's shared recursive component.
394
+ *
395
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/plugins/MiniPlugin.ts#L1228-L1252
396
+ */
397
+ function createWechatCompJson(): JsonObject {
398
+ return {
399
+ component: true,
400
+ styleIsolation: 'apply-shared',
401
+ // Taro's recursive template can nest <comp />, so the component references
402
+ // itself just like the official runner output.
403
+ usingComponents: { comp: './comp' }
404
+ }
405
+ }
406
+
407
+ /**
408
+ * Converts a WeChat-emitted asset's source into text.
409
+ */
410
+ function getWechatAssetSource(item: WechatBundleItem): string {
411
+ if (typeof item.source === 'string') return item.source
412
+ return item.source ? new TextDecoder().decode(item.source) : ''
413
+ }
414
+
415
+ /**
416
+ * Flattens Vite-emitted CSS into app.wxss and removes the intermediate CSS asset.
417
+ * This is vite-plugin-taro's Vite equivalent of Taro Webpack's app/common style consolidation.
418
+ *
419
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/plugins/MiniPlugin.ts#L1310-L1311
420
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/plugins/MiniPlugin.ts#L1471-L1528
421
+ */
422
+ function collectWechatBundleWxss(bundle: WechatBundle): string {
423
+ const wechatWxssChunks: string[] = []
424
+ for (const [fileName, item] of Object.entries(bundle)) {
425
+ if (item.type !== 'asset' || !fileName.endsWith('.css')) continue
426
+ const source = getWechatAssetSource(item)
427
+ if (source) wechatWxssChunks.push(source)
428
+ delete bundle[fileName]
429
+ }
430
+ return wechatWxssChunks.join('\n')
431
+ }
432
+
433
+ /**
434
+ * Serializes generated Mini Program JSON assets; vite-plugin-taro pretty-prints non-prod output.
435
+ */
436
+ function stringifyJsonAsset(value: JsonObject): string {
437
+ return isProd ? JSON.stringify(value) : JSON.stringify(value, null, 2)
438
+ }
@@ -1,38 +1,48 @@
1
1
  /** Plain JSON object emitted into Mini Program/Web config payloads. */
2
- export type JsonObject = Record<string, unknown>;
2
+ export type JsonObject = Record<string, unknown>
3
+
3
4
  /** Build target handled by this plugin. */
4
- export type TaroTarget = 'wx' | 'h5';
5
+ export type VitePluginTaroTarget = 'wx' | 'h5'
6
+
5
7
  /** Describes one React-backed page shared by WeChat Mini Program and Web builds. */
6
- export type TaroPageOption = {
8
+ export type VitePluginTaroPageOption = {
7
9
  /**
8
10
  * Page route and output path, without file extension.
9
11
  * Example: "pages/index/index" emits pages/index/index.{js,json,wxml,wxss}
10
12
  * for WeChat and becomes the Web router path.
11
13
  */
12
- path: string;
14
+ path: string
15
+
13
16
  /** Page JSON config merged into WeChat JSON and Web route config. */
14
- config: JsonObject;
15
- };
17
+ config: JsonObject
18
+ }
19
+
16
20
  /** Required build inputs for the custom Vite/Rolldown Taro renderer plugin. */
17
- export interface TaroPluginOptions {
21
+ export interface VitePluginTaroOptions {
18
22
  /** Active target for this Vite invocation. */
19
- target: TaroTarget;
23
+ target: VitePluginTaroTarget
24
+
20
25
  /** Source file that default-exports the root React app component. */
21
- app: string;
26
+ app: string
27
+
22
28
  /** Ordered page list; also becomes app.json.pages and Web route order. */
23
- pages: TaroPageOption[];
29
+ pages: VitePluginTaroPageOption[]
30
+
24
31
  /** Base app.json content. Its pages field is overwritten from options.pages. */
25
- appJson: JsonObject;
32
+ appJson: JsonObject
33
+
26
34
  /** project.config.json content emitted at the Mini Program root. */
27
- projectConfigJson: JsonObject;
35
+ projectConfigJson: JsonObject
36
+
28
37
  /** sitemap.json content emitted at the Mini Program root. */
29
- sitemapJson: JsonObject;
38
+ sitemapJson: JsonObject
39
+ }
40
+
41
+ export type VitePluginTaroBuildContext = {
42
+ target: VitePluginTaroTarget
43
+ appComponentImport: string
44
+ pages: VitePluginTaroPageOption[]
45
+ appConfig: JsonObject
46
+ projectConfigJson: JsonObject
47
+ sitemapJson: JsonObject
30
48
  }
31
- export type TaroBuildContext = {
32
- target: TaroTarget;
33
- appComponentImport: string;
34
- pages: TaroPageOption[];
35
- appConfig: JsonObject;
36
- projectConfigJson: JsonObject;
37
- sitemapJson: JsonObject;
38
- };
@@ -0,0 +1,35 @@
1
+ import path from 'node:path'
2
+
3
+ /**
4
+ * Derives a page component import from a Taro-style page path.
5
+ *
6
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/plugins/MiniPlugin.ts#L660-L668
7
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-webpack5-runner/src/utils/app.ts#L74-L90
8
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-loader/src/h5.ts#L12-L21
9
+ */
10
+ export function createPageComponentImport(pagePath: string): string {
11
+ return toImportPath(`src/${pagePath}.tsx`)
12
+ }
13
+
14
+ /**
15
+ * Converts a local file path into an absolute ESM import path for Vite.
16
+ */
17
+ export function toImportPath(filePath: string): string {
18
+ return path.resolve(filePath)
19
+ }
20
+
21
+ /**
22
+ * Removes Rollup/Vite's internal virtual-module prefix before ID comparisons.
23
+ */
24
+ export function stripVirtualPrefix(id: string): string {
25
+ return id.startsWith('\0') ? id.slice(1) : id
26
+ }
27
+
28
+ /**
29
+ * Uses Taro-style slash normalization, plus Vite query-string stripping for module IDs.
30
+ *
31
+ * https://github.com/NervJS/taro/blob/f0e5c39d5f04290db975670411e23c3a396e15f8/packages/taro-helper/src/utils.ts#L32-L34
32
+ */
33
+ export function normalizeModuleId(id: string): string {
34
+ return id.replace(/\\/g, '/').replace(/\?.*$/, '')
35
+ }
@@ -0,0 +1,105 @@
1
+ import type { Plugin, PluginOption, UserConfig } from 'vite'
2
+ import { createVitePluginTaroConditionalDirectivePlugin } from './plugins.ts'
3
+ import { createTailwindcssPlugins } from './tailwindcss.ts'
4
+ import {
5
+ createH5SupportPlugins,
6
+ createH5ViteConfig,
7
+ createWebIndexHtmlTags,
8
+ isH5VirtualModuleId,
9
+ loadH5VirtualModule
10
+ } from './targets/h5.ts'
11
+ import {
12
+ createWxViteConfig,
13
+ emitWechatAssets,
14
+ emitWechatImplicitChunksForVirtualApp,
15
+ isWxVirtualModuleId,
16
+ loadWxVirtualModule
17
+ } from './targets/wx.ts'
18
+ import type { VitePluginTaroBuildContext, VitePluginTaroOptions } from './types.ts'
19
+ import { stripVirtualPrefix, toImportPath } from './utils.ts'
20
+
21
+ /**
22
+ * Creates the Vite/Rolldown plugin that emits either WeChat Mini Program files
23
+ * or a Taro Web app using the official Taro runtime packages.
24
+ */
25
+ export default function vitePluginTaro(options: VitePluginTaroOptions): PluginOption[] {
26
+ const context = createVitePluginTaroBuildContext(options)
27
+
28
+ return [
29
+ createVitePluginTaroConditionalDirectivePlugin(context),
30
+ ...createTargetSupportPlugins(context),
31
+ ...createTailwindcssPlugins(context),
32
+ createVitePluginTaroPlugin(context)
33
+ ]
34
+ }
35
+
36
+ function createTargetSupportPlugins(context: VitePluginTaroBuildContext): PluginOption[] {
37
+ switch (context.target) {
38
+ case 'h5':
39
+ return createH5SupportPlugins()
40
+ default:
41
+ return []
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Creates the vite-plugin-taro plugin that emits H5 or Wx outputs.
47
+ */
48
+ function createVitePluginTaroPlugin(context: VitePluginTaroBuildContext): Plugin {
49
+ return {
50
+ name: 'vite-plugin-taro',
51
+ enforce: 'post',
52
+
53
+ /** Configures Vite/Rolldown for the active target. */
54
+ config: {
55
+ order: 'pre',
56
+ handler: (): UserConfig => {
57
+ return context.target === 'wx' ? createWxViteConfig(context) : createH5ViteConfig()
58
+ }
59
+ },
60
+
61
+ /** Marks generated app/page/component entries as virtual modules. */
62
+ resolveId(id) {
63
+ if (isWxVirtualModuleId(id) || isH5VirtualModuleId(id)) return `\0${id}`
64
+ },
65
+
66
+ /** Supplies source code for each virtual entry module. */
67
+ load(id) {
68
+ const cleanId = stripVirtualPrefix(id)
69
+
70
+ emitWechatImplicitChunksForVirtualApp(this, context, cleanId)
71
+
72
+ return loadWxVirtualModule(cleanId, context) ?? loadH5VirtualModule(cleanId, context)
73
+ },
74
+
75
+ /** Injects the generated Web entry into the app shell before Vite scans HTML imports. */
76
+ transformIndexHtml: {
77
+ order: 'pre',
78
+ handler() {
79
+ return createWebIndexHtmlTags(context)
80
+ }
81
+ },
82
+
83
+ /** Emits the WeChat JSON/WXML/WXS/WXSS files that are not JS bundle chunks. */
84
+ generateBundle(_, bundle) {
85
+ emitWechatAssets(this, bundle, context)
86
+ }
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Normalizes user options into the shared data used by both target builders.
92
+ */
93
+ function createVitePluginTaroBuildContext(options: VitePluginTaroOptions): VitePluginTaroBuildContext {
94
+ return {
95
+ target: options.target,
96
+ appComponentImport: toImportPath(options.app),
97
+ pages: options.pages,
98
+ appConfig: {
99
+ ...options.appJson,
100
+ pages: options.pages.map((page) => page.path)
101
+ },
102
+ projectConfigJson: options.projectConfigJson,
103
+ sitemapJson: options.sitemapJson
104
+ }
105
+ }
package/src/vite.ts ADDED
@@ -0,0 +1,2 @@
1
+ export type { VitePluginTaroOptions, VitePluginTaroPageOption, VitePluginTaroTarget } from './vite/types.ts'
2
+ export { default } from './vite/vite-plugin-taro.ts'
@@ -1 +0,0 @@
1
- export * from '@tarojs/components';
@@ -1 +0,0 @@
1
- {"version":3,"file":"taro.js","names":[],"sources":["../../src/public/taro.ts"],"sourcesContent":["import { hooks } from '@tarojs/runtime'\nimport Taro from '@tarojs/taro'\n\nif (hooks.isExist('initNativeApi')) {\n hooks.call('initNativeApi', Taro)\n}\n\n// @ts-expect-error @tarojs/taro declares export= types, but vite-plugin-taro target aliases expose runtime named exports.\nexport * from '@tarojs/taro'\nexport default Taro\n"],"mappings":";;;;AAGA,IAAI,MAAM,QAAQ,eAAe,GAC7B,MAAM,KAAK,iBAAiB,IAAI;AAKpC,IAAA,eAAe"}
package/dist/shim/h5.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export { createReactApp } from '@tarojs/plugin-framework-react/dist/runtime';
2
- export { createBrowserHistory, createHashHistory, createRouter, handleAppMount } from '@tarojs/router';
3
- export { window } from '@tarojs/runtime';
package/dist/shim/wx.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export { createReactApp } from '@tarojs/plugin-framework-react/dist/runtime';
2
- export { default as ReactDOM } from '@tarojs/react';
3
- export { createPageConfig, createRecursiveComponentConfig } from '@tarojs/runtime';
@@ -1,2 +0,0 @@
1
- export declare const isProd: boolean;
2
- export declare const nodeRequire: NodeJS.Require;