vite-plugin-taro 0.2.2 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/README.md +83 -106
  2. package/README.zh.md +83 -104
  3. package/dist/node/build-context.d.ts +25 -0
  4. package/dist/node/build-context.js +48 -0
  5. package/dist/node/css/css-pipeline.d.ts +21 -0
  6. package/dist/node/css/css-pipeline.js +129 -0
  7. package/dist/node/plugins/conditional-directives.d.ts +3 -0
  8. package/dist/node/plugins/conditional-directives.js +62 -0
  9. package/dist/node/plugins/taro-runtime.d.ts +5 -0
  10. package/dist/node/plugins/taro-runtime.js +18 -0
  11. package/dist/node/targets/h5/plugin.d.ts +6 -0
  12. package/dist/node/targets/h5/plugin.js +117 -0
  13. package/dist/node/targets/h5/virtual-modules.d.ts +5 -0
  14. package/dist/node/targets/h5/virtual-modules.js +60 -0
  15. package/dist/node/targets/wx/companion-assets.d.ts +19 -0
  16. package/dist/node/targets/wx/companion-assets.js +129 -0
  17. package/dist/node/targets/wx/dev-server/development-session.d.ts +31 -0
  18. package/dist/node/targets/wx/dev-server/development-session.js +202 -0
  19. package/dist/node/targets/wx/dev-server/full-build-scheduler.d.ts +14 -0
  20. package/dist/node/targets/wx/dev-server/full-build-scheduler.js +60 -0
  21. package/dist/node/targets/wx/dev-server/js-utils.d.ts +5 -0
  22. package/dist/node/targets/wx/dev-server/js-utils.js +28 -0
  23. package/dist/node/targets/wx/dev-server/output.d.ts +19 -0
  24. package/dist/node/targets/wx/dev-server/output.js +44 -0
  25. package/dist/node/targets/wx/dev-server/rolldown-runtime-source.d.ts +8 -0
  26. package/dist/node/targets/wx/dev-server/rolldown-runtime-source.js +95 -0
  27. package/dist/node/targets/wx/dev-server/update-server-state.d.ts +65 -0
  28. package/dist/node/targets/wx/dev-server/update-server-state.js +116 -0
  29. package/dist/node/targets/wx/dev-server/update-transport.d.ts +28 -0
  30. package/dist/node/targets/wx/dev-server/update-transport.js +212 -0
  31. package/dist/node/targets/wx/dev-server/vite-bundled-dev-adapter.d.ts +44 -0
  32. package/dist/node/targets/wx/dev-server/vite-bundled-dev-adapter.js +145 -0
  33. package/dist/node/targets/wx/development-files.d.ts +8 -0
  34. package/dist/node/targets/wx/development-files.js +8 -0
  35. package/dist/node/targets/wx/plugin.d.ts +6 -0
  36. package/dist/node/targets/wx/plugin.js +143 -0
  37. package/dist/node/targets/wx/react-refresh.d.ts +4 -0
  38. package/dist/node/targets/wx/react-refresh.js +38 -0
  39. package/dist/node/targets/wx/virtual-modules.d.ts +16 -0
  40. package/dist/node/targets/wx/virtual-modules.js +120 -0
  41. package/dist/node/utils/async.d.ts +8 -0
  42. package/dist/node/utils/async.js +16 -0
  43. package/dist/node/utils/filesystem.d.ts +13 -0
  44. package/dist/node/utils/filesystem.js +43 -0
  45. package/dist/{vite/utils.d.ts → node/utils/modules.d.ts} +2 -2
  46. package/dist/{vite/utils.js → node/utils/modules.js} +10 -3
  47. package/dist/node/utils/packages.d.ts +2 -0
  48. package/dist/node/utils/packages.js +8 -0
  49. package/dist/node/vite-plugin.d.ts +4 -0
  50. package/dist/node/vite-plugin.js +33 -0
  51. package/dist/options.d.ts +21 -0
  52. package/dist/{shim/h5.d.ts → runtime/h5/taro-runtime.d.ts} +3 -1
  53. package/dist/runtime/h5/taro-runtime.js +9 -0
  54. package/dist/runtime/taro/api.d.ts +5 -0
  55. package/dist/{virtual → runtime/taro}/api.js +3 -0
  56. package/dist/runtime/taro/components.d.ts +2 -0
  57. package/dist/runtime/taro/components.js +2 -0
  58. package/dist/runtime/wx/page-update.d.ts +6 -0
  59. package/dist/runtime/wx/page-update.js +157 -0
  60. package/dist/{shim/wx.d.ts → runtime/wx/taro-runtime.d.ts} +1 -0
  61. package/dist/{shim/wx.js → runtime/wx/taro-runtime.js} +1 -0
  62. package/dist/runtime/wx/update-client-state.d.ts +68 -0
  63. package/dist/runtime/wx/update-client-state.js +84 -0
  64. package/dist/runtime/wx/update-client.d.ts +1 -0
  65. package/dist/runtime/wx/update-client.js +170 -0
  66. package/dist/vite.d.ts +2 -2
  67. package/dist/vite.js +1 -1
  68. package/package.json +15 -11
  69. package/src/node/build-context.ts +63 -0
  70. package/src/node/css/css-pipeline.ts +147 -0
  71. package/src/node/plugins/conditional-directives.ts +76 -0
  72. package/src/node/plugins/taro-runtime.ts +22 -0
  73. package/src/node/targets/h5/plugin.ts +135 -0
  74. package/src/node/targets/h5/virtual-modules.ts +71 -0
  75. package/src/node/targets/wx/companion-assets.ts +170 -0
  76. package/src/node/targets/wx/dev-server/development-session.ts +253 -0
  77. package/src/node/targets/wx/dev-server/full-build-scheduler.ts +62 -0
  78. package/src/node/targets/wx/dev-server/js-utils.ts +33 -0
  79. package/src/node/targets/wx/dev-server/output.ts +56 -0
  80. package/src/node/targets/wx/dev-server/rolldown-runtime-source.ts +95 -0
  81. package/src/node/targets/wx/dev-server/update-server-state.ts +183 -0
  82. package/src/node/targets/wx/dev-server/update-transport.ts +261 -0
  83. package/src/node/targets/wx/dev-server/vite-bundled-dev-adapter.ts +203 -0
  84. package/src/node/targets/wx/development-files.ts +11 -0
  85. package/src/node/targets/wx/plugin.ts +163 -0
  86. package/src/node/targets/wx/react-refresh.ts +51 -0
  87. package/src/node/targets/wx/virtual-modules.ts +152 -0
  88. package/src/node/utils/async.ts +19 -0
  89. package/src/node/utils/filesystem.ts +45 -0
  90. package/src/{vite/utils.ts → node/utils/modules.ts} +11 -3
  91. package/src/node/utils/packages.ts +10 -0
  92. package/src/node/vite-plugin.ts +41 -0
  93. package/src/options.ts +25 -0
  94. package/src/runtime/h5/taro-css.d.ts +3 -0
  95. package/src/runtime/h5/taro-runtime.ts +10 -0
  96. package/src/{virtual → runtime/taro}/api.ts +3 -0
  97. package/src/runtime/taro/components.ts +2 -0
  98. package/src/runtime/wx/page-update.ts +230 -0
  99. package/src/runtime/wx/react-refresh.d.ts +20 -0
  100. package/src/{shim/wx.ts → runtime/wx/taro-runtime.ts} +1 -0
  101. package/src/runtime/wx/update-client-state.ts +138 -0
  102. package/src/runtime/wx/update-client.ts +222 -0
  103. package/src/vite.ts +2 -2
  104. package/dist/shim/h5.js +0 -5
  105. package/dist/virtual/api.d.ts +0 -3
  106. package/dist/virtual/components.d.ts +0 -1
  107. package/dist/virtual/components.js +0 -1
  108. package/dist/vite/constants.d.ts +0 -4
  109. package/dist/vite/constants.js +0 -8
  110. package/dist/vite/plugins.d.ts +0 -8
  111. package/dist/vite/plugins.js +0 -186
  112. package/dist/vite/tailwindcss.d.ts +0 -3
  113. package/dist/vite/tailwindcss.js +0 -35
  114. package/dist/vite/targets/h5.d.ts +0 -31
  115. package/dist/vite/targets/h5.js +0 -201
  116. package/dist/vite/targets/wx.d.ts +0 -74
  117. package/dist/vite/targets/wx.js +0 -362
  118. package/dist/vite/types.d.ts +0 -38
  119. package/dist/vite/virtual-modules.d.ts +0 -3
  120. package/dist/vite/virtual-modules.js +0 -13
  121. package/dist/vite/vite-plugin-taro.d.ts +0 -7
  122. package/dist/vite/vite-plugin-taro.js +0 -80
  123. package/src/shim/h5.ts +0 -6
  124. package/src/virtual/components.ts +0 -1
  125. package/src/vite/constants.ts +0 -12
  126. package/src/vite/plugins.ts +0 -218
  127. package/src/vite/tailwindcss.ts +0 -41
  128. package/src/vite/targets/h5.ts +0 -229
  129. package/src/vite/targets/wx.ts +0 -436
  130. package/src/vite/types.ts +0 -48
  131. package/src/vite/virtual-modules.ts +0 -14
  132. package/src/vite/vite-plugin-taro.ts +0 -106
  133. /package/dist/{vite/types.js → options.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-taro",
3
- "version": "0.2.2",
3
+ "version": "0.3.1",
4
4
  "author": "sep2",
5
5
  "description": "Vite 8 plugin for building one React/Taro codebase for WeChat Mini Program and H5 targets.",
6
6
  "type": "module",
@@ -53,7 +53,6 @@
53
53
  "dependencies": {
54
54
  "@babel/core": "^7.29.7",
55
55
  "@rolldown/plugin-babel": "^0.2.3",
56
- "@tailwindcss/vite": "^4.3.1",
57
56
  "@tarojs/components": "^4.2.0",
58
57
  "@tarojs/helper": "^4.2.0",
59
58
  "@tarojs/plugin-platform-h5": "^4.2.0",
@@ -61,26 +60,31 @@
61
60
  "@tarojs/router": "^4.2.0",
62
61
  "@tarojs/runtime": "^4.2.0",
63
62
  "@tarojs/taro": "^4.2.0",
64
- "@vitejs/plugin-react": "^6.0.2",
63
+ "@vitejs/plugin-react": "^6.0.3",
65
64
  "babel-plugin-transform-taroapi": "^4.2.0",
66
- "tailwindcss": "^4.3.1",
67
- "weapp-tailwindcss": "^5.0.13",
68
- "@tarojs/plugin-framework-react": "npm:vite-plugin-taro-plugin-framework-react@0.2.2",
69
- "@tarojs/react": "npm:vite-plugin-taro-react@0.2.2"
65
+ "picocolors": "^1.1.1",
66
+ "react-refresh": "^0.18.0",
67
+ "tailwindcss": "^4.3.2",
68
+ "weapp-tailwindcss": "^5.1.14",
69
+ "@tarojs/plugin-framework-react": "npm:vite-plugin-taro-plugin-framework-react@0.3.1",
70
+ "@tarojs/react": "npm:vite-plugin-taro-react@0.3.1"
70
71
  },
71
72
  "peerDependencies": {
72
73
  "react": "^19.0.0",
73
74
  "react-dom": "^19.0.0",
74
- "vite": "^8.0.0"
75
+ "vite": "^8.1.4"
75
76
  },
76
77
  "devDependencies": {
77
78
  "@types/babel__core": "^7.20.5",
78
- "@types/node": "^26.0.0",
79
- "typescript": "^7.0.1-rc",
80
- "vite": "^8.0.16"
79
+ "@types/node": "^26.1.1",
80
+ "@types/react": "^19.2.17",
81
+ "@types/react-refresh": "^0.14.7",
82
+ "typescript": "^7.0.2",
83
+ "vite": "^8.1.4"
81
84
  },
82
85
  "scripts": {
83
86
  "build": "node ../../scripts/sync-plugin-readme.ts && node ../../scripts/clean-directory.ts dist && tsc --project tsconfig.json",
87
+ "test": "node --test",
84
88
  "typecheck": "tsc --project tsconfig.json --noEmit"
85
89
  }
86
90
  }
@@ -0,0 +1,63 @@
1
+ import path from 'node:path'
2
+ import type { ConfigEnv, ResolvedConfig } from 'vite'
3
+ import type { JsonObject, VitePluginTaroOptions, VitePluginTaroPageOption, VitePluginTaroTarget } from '../options.ts'
4
+ import { CssPipeline } from './css/css-pipeline.ts'
5
+
6
+ type ProjectContext = Readonly<{
7
+ target: VitePluginTaroTarget
8
+ appComponentFile: string
9
+ pages: readonly VitePluginTaroPageOption[]
10
+ appConfig: JsonObject
11
+ projectConfigJson: JsonObject
12
+ projectPrivateConfigJson?: JsonObject
13
+ sitemapJson: JsonObject
14
+ }>
15
+
16
+ /** Owns the shared project, Vite lifecycle state, and cross-target services for one build. */
17
+ export class BuildContext {
18
+ readonly project: ProjectContext
19
+ readonly css: CssPipeline
20
+ private developmentMode: boolean | undefined
21
+ private resolvedViteConfig: ResolvedConfig | undefined
22
+
23
+ constructor(options: VitePluginTaroOptions) {
24
+ this.project = {
25
+ target: options.target,
26
+ appComponentFile: path.resolve(options.app),
27
+ pages: options.pages,
28
+ appConfig: {
29
+ ...options.appJson,
30
+ pages: options.pages.map((page) => page.path)
31
+ },
32
+ projectConfigJson: options.projectConfigJson,
33
+ projectPrivateConfigJson: options.projectPrivateConfigJson,
34
+ sitemapJson: options.sitemapJson
35
+ }
36
+ this.css = new CssPipeline(options.target)
37
+ }
38
+
39
+ configure(environment: ConfigEnv): void {
40
+ if (this.developmentMode !== undefined)
41
+ throw new Error('vite-plugin-taro build context was already configured.')
42
+ this.developmentMode = environment.command === 'serve'
43
+ }
44
+
45
+ resolve(config: ResolvedConfig): void {
46
+ if (this.developmentMode === undefined) {
47
+ throw new Error('vite-plugin-taro build context resolved before it was configured.')
48
+ }
49
+ if (this.resolvedViteConfig) throw new Error('vite-plugin-taro build context was already resolved.')
50
+ this.resolvedViteConfig = config
51
+ this.css.resolve(config.root)
52
+ }
53
+
54
+ get development(): boolean {
55
+ if (this.developmentMode === undefined) throw new Error('vite-plugin-taro build context is not configured.')
56
+ return this.developmentMode
57
+ }
58
+
59
+ get vite(): ResolvedConfig {
60
+ if (!this.resolvedViteConfig) throw new Error('vite-plugin-taro build context is not resolved.')
61
+ return this.resolvedViteConfig
62
+ }
63
+ }
@@ -0,0 +1,147 @@
1
+ import path from 'node:path'
2
+ import type { Plugin } from 'vite'
3
+ import { createContext } from 'weapp-tailwindcss/core'
4
+ import { createWeappTailwindcssGenerator, resolveTailwindV4Source } from 'weapp-tailwindcss/generator'
5
+ import type { VitePluginTaroTarget } from '../../options.ts'
6
+ import { normalizeModuleId } from '../utils/modules.ts'
7
+
8
+ const wxStyleOptions = {
9
+ cssCalc: false,
10
+ autoprefixer: false,
11
+ rem2rpx: true,
12
+ px2rpx: true
13
+ } as const
14
+
15
+ type WxCssContext = ReturnType<typeof createContext>
16
+ type CssTransformResult = { code: string; map: null }
17
+
18
+ /** Owns CSS generation and the class-name state shared by normal chunks and literal WX patches. */
19
+ export class CssPipeline {
20
+ readonly plugin: Plugin
21
+ private readonly target: VitePluginTaroTarget
22
+ private readonly runtimeClassSet = new Set<string>()
23
+ private projectRoot: string | undefined
24
+ private wxContext: WxCssContext | undefined
25
+
26
+ constructor(target: VitePluginTaroTarget) {
27
+ this.target = target
28
+ this.plugin = this.createPlugin()
29
+ }
30
+
31
+ resolve(projectRoot: string): void {
32
+ if (this.projectRoot) throw new Error('vite-plugin-taro CSS pipeline was already resolved.')
33
+ this.projectRoot = projectRoot
34
+ this.wxContext = this.target === 'wx' ? createWxCssContext(projectRoot) : undefined
35
+ }
36
+
37
+ async transformWxClassNames(code: string, filename: string): Promise<CssTransformResult> {
38
+ if (!this.wxContext || this.runtimeClassSet.size === 0) return { code, map: null }
39
+ const result = await this.wxContext.transformJs(code, {
40
+ runtimeSet: this.runtimeClassSet,
41
+ filename,
42
+ generateMap: false
43
+ })
44
+ return { code: result.code, map: null }
45
+ }
46
+
47
+ private createPlugin(): Plugin {
48
+ const pipeline = this
49
+ return {
50
+ name: 'vite-plugin-taro:css',
51
+ enforce: 'pre',
52
+
53
+ buildStart() {
54
+ pipeline.runtimeClassSet.clear()
55
+ },
56
+
57
+ async transform(code, id) {
58
+ if (!isCssModuleId(id) || !shouldGenerateTailwindCss(code)) return
59
+
60
+ const projectRoot = pipeline.getProjectRoot()
61
+ const cssFile = resolveCssFile(id, projectRoot)
62
+ const cssBase = path.dirname(cssFile)
63
+ const source = await resolveTailwindV4Source({
64
+ projectRoot,
65
+ cwd: projectRoot,
66
+ base: cssBase,
67
+ css: code,
68
+ cssSources: [{ file: cssFile, base: cssBase, css: code, dependencies: [cssFile] }]
69
+ })
70
+ const generator = createWeappTailwindcssGenerator(source)
71
+ const generated = await generator.generate({
72
+ target: pipeline.target === 'wx' ? 'weapp' : 'web',
73
+ scanSources: true,
74
+ candidates: [],
75
+ styleOptions: pipeline.target === 'wx' ? wxStyleOptions : undefined
76
+ })
77
+
78
+ for (const className of generated.classSet) pipeline.runtimeClassSet.add(className)
79
+ for (const dependency of generated.dependencies) this.addWatchFile(dependency)
80
+ return generated.css
81
+ },
82
+
83
+ async renderChunk(code, chunk) {
84
+ if (pipeline.target !== 'wx') return
85
+ return await pipeline.transformWxClassNames(code, chunk.fileName)
86
+ },
87
+
88
+ async generateBundle(_, bundle) {
89
+ if (pipeline.target !== 'wx') return
90
+ const core = pipeline.getWxContext()
91
+ await Promise.all(
92
+ Object.entries(bundle).map(async ([fileName, item]) => {
93
+ if (item.type === 'asset' && fileName.endsWith('.css')) {
94
+ await transformWxssAsset(core, item)
95
+ }
96
+ })
97
+ )
98
+ }
99
+ }
100
+ }
101
+
102
+ private getProjectRoot(): string {
103
+ if (!this.projectRoot) throw new Error('vite-plugin-taro CSS pipeline was used before configuration resolved.')
104
+ return this.projectRoot
105
+ }
106
+
107
+ private getWxContext(): WxCssContext {
108
+ if (!this.wxContext) throw new Error('vite-plugin-taro expected a resolved WeChat CSS pipeline.')
109
+ return this.wxContext
110
+ }
111
+ }
112
+
113
+ function createWxCssContext(projectRoot: string): WxCssContext {
114
+ return createContext({
115
+ appType: 'taro',
116
+ tailwindcssBasedir: projectRoot,
117
+ generator: { target: 'weapp' },
118
+ ...wxStyleOptions,
119
+ logLevel: 'silent'
120
+ })
121
+ }
122
+
123
+ async function transformWxssAsset(core: WxCssContext, item: { source?: string | Uint8Array }): Promise<void> {
124
+ const result = await core.transformWxss(getAssetSource(item), { isMainChunk: true })
125
+ item.source = result.css
126
+ }
127
+
128
+ function shouldGenerateTailwindCss(code: string): boolean {
129
+ const tailwindEntryImportPattern =
130
+ /@(import|reference)\s+(?:url\(\s*)?(?:["'])tailwindcss(?:\/(?:theme|preflight|utilities)(?:\.css)?)?(?:["'])/
131
+ return code.includes('tailwindcss') && tailwindEntryImportPattern.test(code)
132
+ }
133
+
134
+ function isCssModuleId(id: string): boolean {
135
+ return /\.(?:css|scss|sass|less|styl|stylus)(?:$|[?#])/.test(id)
136
+ }
137
+
138
+ function getAssetSource(item: { source?: string | Uint8Array }): string {
139
+ if (typeof item.source === 'string') return item.source
140
+ return item.source ? new TextDecoder().decode(item.source) : ''
141
+ }
142
+
143
+ function resolveCssFile(id: string, root: string): string {
144
+ const normalizedId = normalizeModuleId(id)
145
+ const cleanId = normalizedId.startsWith('/@fs/') ? normalizedId.slice('/@fs'.length) : normalizedId
146
+ return path.isAbsolute(cleanId) ? cleanId : path.resolve(root, cleanId)
147
+ }
@@ -0,0 +1,76 @@
1
+ import type { Plugin } from 'vite'
2
+ import type { VitePluginTaroTarget } from '../../options.ts'
3
+ import type { BuildContext } from '../build-context.ts'
4
+ import { normalizeModuleId } from '../utils/modules.ts'
5
+
6
+ export function createConditionalDirectivePlugin(context: BuildContext): Plugin {
7
+ return {
8
+ name: 'vite-plugin-taro:conditional-directives',
9
+ enforce: 'pre',
10
+ transform(code, id) {
11
+ if (!isConditionalDirectiveSource(id) || !code.includes('#if')) return
12
+ return { code: transformConditionalDirectives(code, context.project.target), map: null }
13
+ }
14
+ }
15
+ }
16
+
17
+ function isConditionalDirectiveSource(id: string): boolean {
18
+ const normalizedId = normalizeModuleId(id)
19
+ return !normalizedId.includes('/node_modules/') && /\.(?:[cm]?[jt]sx?|css|s[ac]ss|less|styl)$/.test(normalizedId)
20
+ }
21
+
22
+ type Directive = {
23
+ name: 'ifdef' | 'ifndef' | 'else' | 'endif'
24
+ target: string
25
+ }
26
+
27
+ type DirectiveFrame = {
28
+ parentActive: boolean
29
+ matched: boolean
30
+ active: boolean
31
+ }
32
+
33
+ function transformConditionalDirectives(code: string, target: VitePluginTaroTarget): string {
34
+ const lines = code.match(/[^\n]*(?:\n|$)/g) ?? []
35
+ const frames: DirectiveFrame[] = []
36
+ let transformed = ''
37
+
38
+ for (const line of lines) {
39
+ if (!line) continue
40
+ const directive = parseDirective(line)
41
+ const lineEnding = line.match(/\r?\n$/)?.[0] ?? ''
42
+ if (!directive) {
43
+ transformed += frames.every((frame) => frame.active) ? line : lineEnding
44
+ continue
45
+ }
46
+
47
+ if (directive.name === 'ifdef' || directive.name === 'ifndef') {
48
+ const parentActive = frames.every((frame) => frame.active)
49
+ const targetMatched = directive.target.toLowerCase() === target
50
+ const matched = directive.name === 'ifdef' ? targetMatched : !targetMatched
51
+ frames.push({ parentActive, matched, active: parentActive && matched })
52
+ } else if (directive.name === 'else') {
53
+ const frame = frames.at(-1)
54
+ if (frame) frame.active = frame.parentActive && !frame.matched
55
+ } else {
56
+ frames.pop()
57
+ }
58
+ transformed += lineEnding
59
+ }
60
+
61
+ return transformed
62
+ }
63
+
64
+ function parseDirective(line: string): Directive | undefined {
65
+ const match = line.match(/^\s*(?:(?:\/\/)|(?:\/\*))\s*#(ifdef|ifndef|if|elif|else|endif)\b([^*\r\n]*)/)
66
+ if (!match) return
67
+ const name = match[1]
68
+ if (name === 'if' || name === 'elif') {
69
+ throw new Error(`vite-plugin-taro no longer supports #${name}; use #ifdef, #ifndef, or #else.`)
70
+ }
71
+ if (name !== 'ifdef' && name !== 'ifndef' && name !== 'else' && name !== 'endif') return
72
+ return {
73
+ name,
74
+ target: match[2]?.replace(/\*\/$/, '').trim() ?? ''
75
+ }
76
+ }
@@ -0,0 +1,22 @@
1
+ import type { Plugin } from 'vite'
2
+ import { resolvePackageFile } from '../utils/packages.ts'
3
+
4
+ /** Public IDs used by Taro's API transform and generated target modules. */
5
+ export const virtualTaroApiId = 'virtual:taro/api'
6
+ const virtualTaroComponentsId = 'virtual:taro/components'
7
+
8
+ const runtimeModules = new Map([
9
+ [virtualTaroApiId, resolvePackageFile('dist/runtime/taro/api.js')],
10
+ [virtualTaroComponentsId, resolvePackageFile('dist/runtime/taro/components.js')]
11
+ ])
12
+
13
+ /** Resolves target-neutral Taro shims once instead of duplicating this concern in every target plugin. */
14
+ export function createTaroRuntimePlugin(): Plugin {
15
+ return {
16
+ name: 'vite-plugin-taro:runtime',
17
+ enforce: 'pre',
18
+ resolveId(id) {
19
+ return runtimeModules.get(id)
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,135 @@
1
+ import type { types as BabelTypes, NodePath, PluginObj } from '@babel/core'
2
+ import babel from '@rolldown/plugin-babel'
3
+ import type { Plugin, PluginOption, UserConfig } from 'vite'
4
+ import type { BuildContext } from '../../build-context.ts'
5
+ import { virtualTaroApiId } from '../../plugins/taro-runtime.ts'
6
+ import { stripVirtualPrefix } from '../../utils/modules.ts'
7
+ import { packageRequire } from '../../utils/packages.ts'
8
+ import { createH5IndexHtmlTags, isH5VirtualModuleId, loadH5VirtualModule } from './virtual-modules.ts'
9
+
10
+ /** Creates the plugins that own the complete H5 target lifecycle. */
11
+ export function createH5TargetPlugins(context: BuildContext): PluginOption[] {
12
+ return [...createH5SupportPlugins(), createH5TargetPlugin(context)]
13
+ }
14
+
15
+ function createH5TargetPlugin(context: BuildContext): Plugin {
16
+ return {
17
+ name: 'vite-plugin-taro:h5',
18
+
19
+ resolveId: {
20
+ order: 'pre',
21
+ handler(id) {
22
+ return isH5VirtualModuleId(id) ? `\0${id}` : undefined
23
+ }
24
+ },
25
+
26
+ load: {
27
+ order: 'post',
28
+ handler(id) {
29
+ return loadH5VirtualModule(stripVirtualPrefix(id), context)
30
+ }
31
+ },
32
+
33
+ transformIndexHtml: {
34
+ order: 'pre',
35
+ handler() {
36
+ return createH5IndexHtmlTags(context)
37
+ }
38
+ }
39
+ }
40
+ }
41
+
42
+ /** Creates H5-only Babel transforms for Stencil CSS ordering and Taro API imports. */
43
+ function createH5SupportPlugins(): PluginOption[] {
44
+ return [
45
+ babel({
46
+ include: /[\\/]@stencil[\\/]core[\\/]internal[\\/]client[\\/]index\.js(?:\?.*)?$/,
47
+ exclude: [],
48
+ plugins: [rewriteStencilStyleInsertion]
49
+ }),
50
+ babel({
51
+ plugins: [
52
+ [
53
+ packageRequire.resolve('babel-plugin-transform-taroapi'),
54
+ {
55
+ packageName: virtualTaroApiId,
56
+ definition: packageRequire(
57
+ packageRequire.resolve('@tarojs/plugin-platform-h5/dist/definition.json')
58
+ )
59
+ }
60
+ ]
61
+ ]
62
+ })
63
+ ]
64
+ }
65
+
66
+ /** Keeps Stencil-injected Taro component styles before application stylesheets. */
67
+ function rewriteStencilStyleInsertion(): PluginObj {
68
+ return {
69
+ name: 'rewrite-stencil-style-insertion',
70
+ visitor: {
71
+ CallExpression(path: NodePath<BabelTypes.CallExpression>) {
72
+ if (!isStencilStyleInsertBeforeCall(path)) return
73
+ path.get('arguments.1').replaceWithSourceString(
74
+ `scopeId.startsWith('sc-taro-') ? styleContainerNode.querySelector('style,link[rel="stylesheet"]') : styleContainerNode.querySelector('link')`
75
+ )
76
+ }
77
+ }
78
+ }
79
+ }
80
+
81
+ function isStencilStyleInsertBeforeCall(path: NodePath<BabelTypes.CallExpression>): boolean {
82
+ return (
83
+ path.get('callee').matchesPattern('styleContainerNode.insertBefore') &&
84
+ path.get('arguments.0').toString() === 'styleElm' &&
85
+ path.get('arguments.1').toString() === "styleContainerNode.querySelector('link')"
86
+ )
87
+ }
88
+
89
+ /** Supplies the complete H5 target configuration from the same target owner as its plugins. */
90
+ export function createH5ViteConfig(context: BuildContext): UserConfig {
91
+ return {
92
+ define: createH5TaroDefines(),
93
+ resolve: {
94
+ mainFields: ['main:h5', 'browser', 'module', 'jsnext:main', 'jsnext'],
95
+ alias: [
96
+ {
97
+ find: /^@stencil\/core\/internal\/client$/,
98
+ replacement: packageRequire.resolve('@stencil/core/internal/client', {
99
+ paths: [packageRequire.resolve('@tarojs/components/package.json')]
100
+ })
101
+ },
102
+ {
103
+ find: /^@tarojs\/components$/,
104
+ replacement: packageRequire.resolve('@tarojs/components/lib/react')
105
+ },
106
+ {
107
+ find: /^@tarojs\/components\/dist\/components$/,
108
+ replacement: packageRequire.resolve('@tarojs/components/dist/components')
109
+ },
110
+ {
111
+ find: /^@tarojs\/taro$/,
112
+ replacement: packageRequire.resolve('@tarojs/plugin-platform-h5/dist/runtime/apis')
113
+ }
114
+ ]
115
+ },
116
+ optimizeDeps: {
117
+ exclude: ['@stencil/core/internal/client']
118
+ },
119
+ build: {
120
+ target: 'es2018',
121
+ minify: !context.development
122
+ }
123
+ }
124
+ }
125
+
126
+ function createH5TaroDefines(): Record<string, string> {
127
+ return {
128
+ 'process.env.FRAMEWORK': JSON.stringify('react'),
129
+ 'process.env.SUPPORT_TARO_POLYFILL': JSON.stringify('disabled'),
130
+ 'process.env.TARO_ENV': JSON.stringify('h5'),
131
+ 'process.env.TARO_PLATFORM': JSON.stringify('web'),
132
+ 'process.env.SUPPORT_DINGTALK_NAVIGATE': JSON.stringify('disabled'),
133
+ DEPRECATED_ADAPTER_COMPONENT: 'false'
134
+ }
135
+ }
@@ -0,0 +1,71 @@
1
+ import type { HtmlTagDescriptor } from 'vite'
2
+ import type { JsonObject, VitePluginTaroPageOption } from '../../../options.ts'
3
+ import type { BuildContext } from '../../build-context.ts'
4
+ import { createPageComponentImportPath, toViteFileImportPath } from '../../utils/modules.ts'
5
+ import { resolvePackageFile } from '../../utils/packages.ts'
6
+
7
+ const h5TaroRuntimeImportPath = toViteFileImportPath(resolvePackageFile('dist/runtime/h5/taro-runtime.js'))
8
+
9
+ const virtualH5EntryId = 'virtual:vite-plugin-taro/h5'
10
+
11
+ export function isH5VirtualModuleId(id: string): boolean {
12
+ return id === virtualH5EntryId
13
+ }
14
+
15
+ export function loadH5VirtualModule(id: string, context: BuildContext): string | undefined {
16
+ if (id === virtualH5EntryId) return createH5EntrySource(context)
17
+ }
18
+
19
+ export function createH5IndexHtmlTags(context: BuildContext): HtmlTagDescriptor[] | undefined {
20
+ if (context.project.target !== 'h5') return
21
+ return [
22
+ {
23
+ tag: 'script',
24
+ attrs: { type: 'module' },
25
+ children: `import '${virtualH5EntryId}'`,
26
+ injectTo: 'body'
27
+ }
28
+ ]
29
+ }
30
+
31
+ function createH5EntrySource(context: BuildContext): string {
32
+ const appConfig = JSON.stringify(createH5AppConfig(context.project.appConfig))
33
+ const routes = createH5RoutesSource(context.project.pages)
34
+ return `import {
35
+ createHashHistory,
36
+ createReactApp,
37
+ createRouter,
38
+ handleAppMount,
39
+ window
40
+ } from ${JSON.stringify(h5TaroRuntimeImportPath)}
41
+ import React from 'react'
42
+ import ReactDOM from 'react-dom/client'
43
+ import AppComponent from ${JSON.stringify(toViteFileImportPath(context.project.appComponentFile))}
44
+
45
+ const config = window.__taroAppConfig = ${appConfig}
46
+ config.routes = ${routes}
47
+ const app = createReactApp(AppComponent, React, ReactDOM, config)
48
+ const history = createHashHistory({ window })
49
+ handleAppMount(config, history)
50
+ createRouter(history, app, config, React)
51
+ `
52
+ }
53
+
54
+ function createH5AppConfig(sharedAppConfig: JsonObject): JsonObject {
55
+ return { router: {}, ...sharedAppConfig }
56
+ }
57
+
58
+ function createH5RoutesSource(pages: readonly VitePluginTaroPageOption[]): string {
59
+ const routes = pages.map((page) =>
60
+ [
61
+ 'Object.assign({',
62
+ ` path: ${JSON.stringify(page.path)},`,
63
+ ' load: async function(context, params) {',
64
+ ` const page = await import(${JSON.stringify(createPageComponentImportPath(page.path))})`,
65
+ ' return [page, context, params]',
66
+ ' }',
67
+ `}, ${JSON.stringify(page.config)})`
68
+ ].join('\n')
69
+ )
70
+ return `[\n${routes.join(',\n')}\n]`
71
+ }