vite-plugin-taro 0.1.8 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -71,7 +71,7 @@ npm run build:h5
71
71
  # Preview the built H5 app
72
72
  npm run preview:h5
73
73
 
74
- # Typecheck with tsgo
74
+ # Typecheck with tsc
75
75
  npm run typecheck
76
76
  ```
77
77
 
@@ -102,11 +102,11 @@ For existing apps or custom project layouts, follow the steps below to wire the
102
102
  npm install -D vite-plugin-taro
103
103
  ```
104
104
 
105
- Your app must also provide Vite 8, React 19, React DOM 19, a TypeScript checker, and Node/React type packages. If your app does not already have them, install the missing packages:
105
+ Your app must also provide Vite 8, React 19, React DOM 19, TypeScript 7, and Node/React type packages. If your app does not already have them, install the missing packages:
106
106
 
107
107
  ```sh
108
108
  npm install react react-dom
109
- npm install -D vite @typescript/native-preview @types/node @types/react @types/react-dom
109
+ npm install -D vite typescript@rc @types/node @types/react @types/react-dom cross-env
110
110
  ```
111
111
 
112
112
  You should NOT have direct dependencies on `@tarojs/*` packages anymore. Remove them if you have.
@@ -281,18 +281,16 @@ Use the same scripts generated by `create-vite-taro`:
281
281
  ```json
282
282
  {
283
283
  "scripts": {
284
- "dev:wx": "NODE_ENV=development VITE_PLUGIN_TARO_TARGET=wx vite build --watch",
285
- "dev:h5": "NODE_ENV=development VITE_PLUGIN_TARO_TARGET=h5 vite",
286
- "build:wx": "NODE_ENV=production VITE_PLUGIN_TARO_TARGET=wx vite build",
287
- "build:h5": "NODE_ENV=production VITE_PLUGIN_TARO_TARGET=h5 vite build",
288
- "preview:h5": "NODE_ENV=production VITE_PLUGIN_TARO_TARGET=h5 vite preview --outDir dist/h5",
289
- "typecheck": "tsgo -b"
284
+ "dev:wx": "cross-env NODE_ENV=development VITE_PLUGIN_TARO_TARGET=wx vite build --watch",
285
+ "dev:h5": "cross-env NODE_ENV=development VITE_PLUGIN_TARO_TARGET=h5 vite",
286
+ "build:wx": "cross-env NODE_ENV=production VITE_PLUGIN_TARO_TARGET=wx vite build",
287
+ "build:h5": "cross-env NODE_ENV=production VITE_PLUGIN_TARO_TARGET=h5 vite build",
288
+ "preview:h5": "cross-env NODE_ENV=production VITE_PLUGIN_TARO_TARGET=h5 vite preview --outDir dist/h5",
289
+ "typecheck": "tsc -b"
290
290
  }
291
291
  }
292
292
  ```
293
293
 
294
- On Windows shells, use `cross-env`.
295
-
296
294
  ### 7. Run each target
297
295
 
298
296
  ```sh
@@ -301,7 +299,7 @@ npm run dev:h5 # Start the H5 dev server
301
299
  npm run build:wx # Build dist/wx
302
300
  npm run build:h5 # Build dist/h5
303
301
  npm run preview:h5 # Preview dist/h5
304
- npm run typecheck # Typecheck with tsgo
302
+ npm run typecheck # Typecheck with tsc
305
303
  ```
306
304
 
307
305
  Open the generated `dist/wx` directory in WeChat DevTools.
@@ -487,7 +485,7 @@ Common scripts:
487
485
  | --- | --- |
488
486
  | `pnpm prepare:taro` | Regenerate the patched React 19 Taro packages from upstream npm tarballs and local patch files. |
489
487
  | `pnpm build:plugin` | Build `packages/vite-plugin-taro` into `dist`. |
490
- | `pnpm typecheck` | Typecheck the plugin and sample app with `tsgo`. |
488
+ | `pnpm typecheck` | Typecheck the plugin and sample app with `tsc`. |
491
489
  | `pnpm lint` | Run Biome checks. |
492
490
  | `pnpm format` | Apply Biome formatting. |
493
491
  | `pnpm dev:sample:wx` | Build the sample WeChat Mini Program in watch mode. Build the plugin first. |
@@ -495,8 +493,9 @@ Common scripts:
495
493
  | `pnpm build:sample:wx` | Build the WeChat Mini Program sample to `packages/loan-genius/dist/wx`. |
496
494
  | `pnpm build:sample:h5` | Build the H5 sample app to `packages/loan-genius/dist/h5`. |
497
495
  | `pnpm preview:sample:h5` | Preview the built H5 sample. |
496
+ | `pnpm changelog` | Regenerate `CHANGELOG.md` from git release tags. |
498
497
  | `pnpm publish:dry` | Dry-run package validation and publishing. |
499
- | `pnpm release <version\|bump>` | Validate, bump versions, create the release commit and tag, and push to trigger CI publishing. |
498
+ | `pnpm release <version\|bump>` | Validate, bump versions, update the changelog, create the release commit and tag, and push to trigger CI publishing. |
500
499
  | `pnpm publish:all` | Publish the public packages in dependency order; mainly used by the tag-based Trusted Publishing workflow. |
501
500
 
502
501
  ## Limitations
package/README.zh.md CHANGED
@@ -71,7 +71,7 @@ npm run build:h5
71
71
  # 预览构建后的 H5 应用
72
72
  npm run preview:h5
73
73
 
74
- # 使用 tsgo 进行类型检查
74
+ # 使用 tsc 进行类型检查
75
75
  npm run typecheck
76
76
  ```
77
77
 
@@ -102,11 +102,11 @@ import { Text, View } from 'virtual:taro/components'
102
102
  npm install -D vite-plugin-taro
103
103
  ```
104
104
 
105
- 你的应用还必须提供 Vite 8、React 19、React DOM 19、TypeScript 检查器,以及 Node/React 类型包。如果应用尚未安装它们,请安装缺失的包:
105
+ 你的应用还必须提供 Vite 8、React 19、React DOM 19、TypeScript 7,以及 Node/React 类型包。如果应用尚未安装它们,请安装缺失的包:
106
106
 
107
107
  ```sh
108
108
  npm install react react-dom
109
- npm install -D vite @typescript/native-preview @types/node @types/react @types/react-dom
109
+ npm install -D vite typescript@rc @types/node @types/react @types/react-dom cross-env
110
110
  ```
111
111
 
112
112
  你不应再直接依赖任何 `@tarojs/*` 包。如果已经依赖,请将它们移除。
@@ -281,18 +281,16 @@ export default function IndexPage() {
281
281
  ```json
282
282
  {
283
283
  "scripts": {
284
- "dev:wx": "NODE_ENV=development VITE_PLUGIN_TARO_TARGET=wx vite build --watch",
285
- "dev:h5": "NODE_ENV=development VITE_PLUGIN_TARO_TARGET=h5 vite",
286
- "build:wx": "NODE_ENV=production VITE_PLUGIN_TARO_TARGET=wx vite build",
287
- "build:h5": "NODE_ENV=production VITE_PLUGIN_TARO_TARGET=h5 vite build",
288
- "preview:h5": "NODE_ENV=production VITE_PLUGIN_TARO_TARGET=h5 vite preview --outDir dist/h5",
289
- "typecheck": "tsgo -b"
284
+ "dev:wx": "cross-env NODE_ENV=development VITE_PLUGIN_TARO_TARGET=wx vite build --watch",
285
+ "dev:h5": "cross-env NODE_ENV=development VITE_PLUGIN_TARO_TARGET=h5 vite",
286
+ "build:wx": "cross-env NODE_ENV=production VITE_PLUGIN_TARO_TARGET=wx vite build",
287
+ "build:h5": "cross-env NODE_ENV=production VITE_PLUGIN_TARO_TARGET=h5 vite build",
288
+ "preview:h5": "cross-env NODE_ENV=production VITE_PLUGIN_TARO_TARGET=h5 vite preview --outDir dist/h5",
289
+ "typecheck": "tsc -b"
290
290
  }
291
291
  }
292
292
  ```
293
293
 
294
- 在 Windows shell 中,请使用 `cross-env`。
295
-
296
294
  ### 7. 运行每个目标
297
295
 
298
296
  ```sh
@@ -301,7 +299,7 @@ npm run dev:h5 # 启动 H5 开发服务器
301
299
  npm run build:wx # 构建 dist/wx
302
300
  npm run build:h5 # 构建 dist/h5
303
301
  npm run preview:h5 # 预览 dist/h5
304
- npm run typecheck # 使用 tsgo 进行类型检查
302
+ npm run typecheck # 使用 tsc 进行类型检查
305
303
  ```
306
304
 
307
305
  在微信开发者工具中打开生成的 `dist/wx` 目录。
@@ -487,7 +485,7 @@ pnpm typecheck
487
485
  | --- | --- |
488
486
  | `pnpm prepare:taro` | 从上游 npm tarball 和本地 patch 文件重新生成打过补丁的 React 19 Taro 包。 |
489
487
  | `pnpm build:plugin` | 将 `packages/vite-plugin-taro` 构建到 `dist`。 |
490
- | `pnpm typecheck` | 使用 `tsgo` 对插件和示例应用进行类型检查。 |
488
+ | `pnpm typecheck` | 使用 `tsc` 对插件和示例应用进行类型检查。 |
491
489
  | `pnpm lint` | 运行 Biome 检查。 |
492
490
  | `pnpm format` | 应用 Biome 格式化。 |
493
491
  | `pnpm dev:sample:wx` | 以 watch 模式构建微信小程序示例。请先构建插件。 |
@@ -495,8 +493,9 @@ pnpm typecheck
495
493
  | `pnpm build:sample:wx` | 将微信小程序示例构建到 `packages/loan-genius/dist/wx`。 |
496
494
  | `pnpm build:sample:h5` | 将 H5 示例应用构建到 `packages/loan-genius/dist/h5`。 |
497
495
  | `pnpm preview:sample:h5` | 预览构建后的 H5 示例。 |
496
+ | `pnpm changelog` | 从 git release tag 重新生成 `CHANGELOG.md`。 |
498
497
  | `pnpm publish:dry` | 干运行包校验和发布流程。 |
499
- | `pnpm release <version\|bump>` | 验证发布、更新版本、创建 release commit 和 tag,并推送触发 CI 发布。 |
498
+ | `pnpm release <version\|bump>` | 验证发布、更新版本、更新 changelog、创建 release commit 和 tag,并推送触发 CI 发布。 |
500
499
  | `pnpm publish:all` | 按依赖顺序发布公开包;主要由基于 tag 的 Trusted Publishing 工作流调用。 |
501
500
 
502
501
  ## 限制
@@ -1,10 +1,8 @@
1
1
  import { createRequire } from 'node:module';
2
2
  import path from 'node:path';
3
+ import { toImportPath } from './utils.js';
3
4
  export const isProd = process.env.NODE_ENV === 'production';
4
5
  export const nodeRequire = createRequire(import.meta.url);
5
6
  const packageRoot = path.dirname(nodeRequire.resolve('vite-plugin-taro/package.json'));
6
- export const h5ShimImportPath = normalizeFileImport(path.join(packageRoot, 'dist/shim/h5.js'));
7
- export const wxShimImportPath = normalizeFileImport(path.join(packageRoot, 'dist/shim/wx.js'));
8
- function normalizeFileImport(filePath) {
9
- return filePath.replace(/\\/g, '/');
10
- }
7
+ export const h5ShimImportPath = toImportPath(path.join(packageRoot, 'dist/shim/h5.js'));
8
+ export const wxShimImportPath = toImportPath(path.join(packageRoot, 'dist/shim/wx.js'));
@@ -1,7 +1,7 @@
1
1
  import babel from '@rolldown/plugin-babel';
2
2
  import react from '@vitejs/plugin-react';
3
3
  import { h5ShimImportPath, isProd, nodeRequire } from '../constants.js';
4
- import { createPageComponentImport } from '../utils.js';
4
+ import { createPageComponentImport, toImportPath } from '../utils.js';
5
5
  import { virtualTaroApiId } from '../virtual-modules.js';
6
6
  const virtualH5Id = 'virtual:vite-plugin-taro/h5';
7
7
  const patchStencilCssOrder = true;
@@ -149,8 +149,8 @@ export function createWebIndexHtmlTags(context) {
149
149
  export function createWebEntry(context) {
150
150
  const webAppConfigCode = JSON.stringify(createWebAppConfig(context.appConfig));
151
151
  const webRoutesConfigCode = createWebRoutesConfig(context.pages);
152
- return `import ${JSON.stringify(nodeRequire.resolve('@tarojs/components/global.css'))}
153
- import ${JSON.stringify(nodeRequire.resolve('@tarojs/components/dist/taro-components/taro-components.css'))}
152
+ return `import ${JSON.stringify(toImportPath(nodeRequire.resolve('@tarojs/components/global.css')))}
153
+ import ${JSON.stringify(toImportPath(nodeRequire.resolve('@tarojs/components/dist/taro-components/taro-components.css')))}
154
154
  import {
155
155
  createHashHistory,
156
156
  createReactApp,
@@ -160,7 +160,7 @@ import {
160
160
  } from ${JSON.stringify(h5ShimImportPath)}
161
161
  import React from 'react'
162
162
  import ReactDOM from 'react-dom/client'
163
- import AppComponent from '${context.appComponentImport}'
163
+ import AppComponent from ${JSON.stringify(context.appComponentImport)}
164
164
 
165
165
  const config = window.__taroAppConfig = ${webAppConfigCode}
166
166
  config.routes = ${webRoutesConfigCode}
@@ -162,7 +162,7 @@ export function createWxAppEntry(context) {
162
162
  const wechatAppConfigCode = JSON.stringify(context.appConfig);
163
163
  return `import { createReactApp, ReactDOM } from ${JSON.stringify(wxShimImportPath)}
164
164
  import React from 'react'
165
- import AppComponent from '${context.appComponentImport}'
165
+ import AppComponent from ${JSON.stringify(context.appComponentImport)}
166
166
 
167
167
  const appConfig = ${wechatAppConfigCode}
168
168
  App(createReactApp(AppComponent, React, ReactDOM, appConfig))
@@ -177,7 +177,7 @@ export function createWxPageEntry(pageOption) {
177
177
  const wechatPageConfigCode = JSON.stringify(pageOption.config);
178
178
  const pageComponentImport = createPageComponentImport(pageOption.path);
179
179
  return `import { createPageConfig } from ${JSON.stringify(wxShimImportPath)}
180
- import PageComponent from '${pageComponentImport}'
180
+ import PageComponent from ${JSON.stringify(pageComponentImport)}
181
181
 
182
182
  const pageConfig = ${wechatPageConfigCode}
183
183
  const taroPageConfig = createPageConfig(PageComponent, '${pageOption.path}', { root: { cn: [] } }, pageConfig)
@@ -10,10 +10,13 @@ export function createPageComponentImport(pagePath) {
10
10
  return toImportPath(`src/${pagePath}.tsx`);
11
11
  }
12
12
  /**
13
- * Converts a local file path into an absolute ESM import path for Vite.
13
+ * Converts a local file path into a Vite file-system import specifier.
14
+ *
15
+ * Rolldown does not reliably resolve raw Windows absolute paths from virtual
16
+ * module source, so generated imports use Vite's /@fs/ prefix instead.
14
17
  */
15
18
  export function toImportPath(filePath) {
16
- return path.resolve(filePath);
19
+ return `/@fs/${normalizeModuleId(path.resolve(filePath))}`;
17
20
  }
18
21
  /**
19
22
  * Removes Rollup/Vite's internal virtual-module prefix before ID comparisons.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-taro",
3
- "version": "0.1.8",
3
+ "version": "0.2.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",
@@ -32,7 +32,6 @@
32
32
  "client.d.ts",
33
33
  "LICENSE",
34
34
  "README.md",
35
- "README.en.md",
36
35
  "README.zh.md"
37
36
  ],
38
37
  "keywords": [
@@ -65,8 +64,8 @@
65
64
  "babel-plugin-transform-taroapi": "^4.2.0",
66
65
  "tailwindcss": "^4.3.1",
67
66
  "weapp-tailwindcss": "^5.0.13",
68
- "@tarojs/plugin-framework-react": "npm:vite-plugin-taro-plugin-framework-react@0.1.8",
69
- "@tarojs/react": "npm:vite-plugin-taro-react@0.1.8"
67
+ "@tarojs/react": "npm:vite-plugin-taro-react@0.2.1",
68
+ "@tarojs/plugin-framework-react": "npm:vite-plugin-taro-plugin-framework-react@0.2.1"
70
69
  },
71
70
  "peerDependencies": {
72
71
  "react": "^19.0.0",
@@ -76,11 +75,11 @@
76
75
  "devDependencies": {
77
76
  "@types/babel__core": "^7.20.5",
78
77
  "@types/node": "^26.0.0",
79
- "@typescript/native-preview": "latest",
78
+ "typescript": "^7.0.1-rc",
80
79
  "vite": "^8.0.16"
81
80
  },
82
81
  "scripts": {
83
- "build": "node ../../scripts/sync-plugin-readme.ts && rm -rf dist && tsgo --project tsconfig.json",
84
- "typecheck": "tsgo --project tsconfig.json --noEmit"
82
+ "build": "node ../../scripts/sync-plugin-readme.ts && node ../../scripts/clean-directory.ts dist && tsc --project tsconfig.json",
83
+ "typecheck": "tsc --project tsconfig.json --noEmit"
85
84
  }
86
85
  }
@@ -1,5 +1,6 @@
1
1
  import { createRequire } from 'node:module'
2
2
  import path from 'node:path'
3
+ import { toImportPath } from './utils.ts'
3
4
 
4
5
  export const isProd = process.env.NODE_ENV === 'production'
5
6
 
@@ -7,9 +8,5 @@ export const nodeRequire = createRequire(import.meta.url)
7
8
 
8
9
  const packageRoot = path.dirname(nodeRequire.resolve('vite-plugin-taro/package.json'))
9
10
 
10
- export const h5ShimImportPath = normalizeFileImport(path.join(packageRoot, 'dist/shim/h5.js'))
11
- export const wxShimImportPath = normalizeFileImport(path.join(packageRoot, 'dist/shim/wx.js'))
12
-
13
- function normalizeFileImport(filePath: string): string {
14
- return filePath.replace(/\\/g, '/')
15
- }
11
+ export const h5ShimImportPath = toImportPath(path.join(packageRoot, 'dist/shim/h5.js'))
12
+ export const wxShimImportPath = toImportPath(path.join(packageRoot, 'dist/shim/wx.js'))
@@ -4,7 +4,7 @@ import react from '@vitejs/plugin-react'
4
4
  import type { HtmlTagDescriptor, PluginOption, UserConfig } from 'vite'
5
5
  import { h5ShimImportPath, isProd, nodeRequire } from '../constants.ts'
6
6
  import type { JsonObject, VitePluginTaroBuildContext, VitePluginTaroPageOption } from '../types.ts'
7
- import { createPageComponentImport } from '../utils.ts'
7
+ import { createPageComponentImport, toImportPath } from '../utils.ts'
8
8
  import { virtualTaroApiId } from '../virtual-modules.ts'
9
9
 
10
10
  const virtualH5Id = 'virtual:vite-plugin-taro/h5'
@@ -173,8 +173,8 @@ export function createWebEntry(context: VitePluginTaroBuildContext): string {
173
173
  const webAppConfigCode = JSON.stringify(createWebAppConfig(context.appConfig))
174
174
  const webRoutesConfigCode = createWebRoutesConfig(context.pages)
175
175
 
176
- return `import ${JSON.stringify(nodeRequire.resolve('@tarojs/components/global.css'))}
177
- import ${JSON.stringify(nodeRequire.resolve('@tarojs/components/dist/taro-components/taro-components.css'))}
176
+ return `import ${JSON.stringify(toImportPath(nodeRequire.resolve('@tarojs/components/global.css')))}
177
+ import ${JSON.stringify(toImportPath(nodeRequire.resolve('@tarojs/components/dist/taro-components/taro-components.css')))}
178
178
  import {
179
179
  createHashHistory,
180
180
  createReactApp,
@@ -184,7 +184,7 @@ import {
184
184
  } from ${JSON.stringify(h5ShimImportPath)}
185
185
  import React from 'react'
186
186
  import ReactDOM from 'react-dom/client'
187
- import AppComponent from '${context.appComponentImport}'
187
+ import AppComponent from ${JSON.stringify(context.appComponentImport)}
188
188
 
189
189
  const config = window.__taroAppConfig = ${webAppConfigCode}
190
190
  config.routes = ${webRoutesConfigCode}
@@ -212,7 +212,7 @@ export function createWxAppEntry(context: VitePluginTaroBuildContext): string {
212
212
 
213
213
  return `import { createReactApp, ReactDOM } from ${JSON.stringify(wxShimImportPath)}
214
214
  import React from 'react'
215
- import AppComponent from '${context.appComponentImport}'
215
+ import AppComponent from ${JSON.stringify(context.appComponentImport)}
216
216
 
217
217
  const appConfig = ${wechatAppConfigCode}
218
218
  App(createReactApp(AppComponent, React, ReactDOM, appConfig))
@@ -228,7 +228,7 @@ export function createWxPageEntry(pageOption: VitePluginTaroPageOption): string
228
228
  const wechatPageConfigCode = JSON.stringify(pageOption.config)
229
229
  const pageComponentImport = createPageComponentImport(pageOption.path)
230
230
  return `import { createPageConfig } from ${JSON.stringify(wxShimImportPath)}
231
- import PageComponent from '${pageComponentImport}'
231
+ import PageComponent from ${JSON.stringify(pageComponentImport)}
232
232
 
233
233
  const pageConfig = ${wechatPageConfigCode}
234
234
  const taroPageConfig = createPageConfig(PageComponent, '${pageOption.path}', { root: { cn: [] } }, pageConfig)
package/src/vite/utils.ts CHANGED
@@ -12,10 +12,13 @@ export function createPageComponentImport(pagePath: string): string {
12
12
  }
13
13
 
14
14
  /**
15
- * Converts a local file path into an absolute ESM import path for Vite.
15
+ * Converts a local file path into a Vite file-system import specifier.
16
+ *
17
+ * Rolldown does not reliably resolve raw Windows absolute paths from virtual
18
+ * module source, so generated imports use Vite's /@fs/ prefix instead.
16
19
  */
17
20
  export function toImportPath(filePath: string): string {
18
- return path.resolve(filePath)
21
+ return `/@fs/${normalizeModuleId(path.resolve(filePath))}`
19
22
  }
20
23
 
21
24
  /**
package/README.en.md DELETED
@@ -1,543 +0,0 @@
1
- # vite-plugin-taro
2
-
3
- [![npm version](https://img.shields.io/npm/v/vite-plugin-taro.svg)](https://www.npmjs.com/package/vite-plugin-taro)
4
- ![Vite compatibility](https://registry.vite.dev/api/badges?package=vite-plugin-taro&tool=vite)
5
- [![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6
-
7
- [简体中文](README.zh.md) | English
8
-
9
- Build WeChat Mini Apps with the latest standards-based frontend stack: Vite 8, React 19, and Tailwind CSS v4.
10
-
11
- `vite-plugin-taro` is for applications that want Taro's cross-platform React components and APIs, but prefer Vite instead of Taro webpack. You only need this plugin to build a complete WeChat Mini Program.
12
-
13
- Live demo: <https://sep2.github.io/vite-plugin-taro>. See [Sample app](https://github.com/sep2/vite-plugin-taro/tree/main/packages/loan-genius/README.md) how to run it locally.
14
-
15
- - **Native Vite builds** Use standard Vite 8 config instead of legacy webpack configuration, with support for all Vite plugins.
16
- - **Hot reload** Both WeChat Mini Program and H5 support dev-mode watch, with Vite 8 HMR/rebuilds for fast feedback.
17
- - **Battle-tested Taro foundation** Use the full set of Taro APIs and components instead of reinventing cross-platform primitives.
18
- - **Tailwind ready** Built-in Tailwind CSS v4 support for both WeChat Mini Program and H5 styles.
19
- - **Conditional compilation** Use Taro-style `#ifdef` / `#ifndef` / `#if` blocks to split code and styles by WeChat / web target.
20
- - **Workspace friendly** Supports standalone apps and monorepos, with npm, pnpm, Yarn, Bun, and other package managers.
21
- - **Type-friendly** The project supports TypeScript all the way.
22
- - **WeChat Skyline** Support WeChat Mini Program output with Skyline rendering mode.
23
-
24
- ## Quick start
25
-
26
- Use `create-vite-taro` for new apps. It scaffolds a Vite 8 + React 19 + Tailwind CSS v4 + Taro 4 project.
27
-
28
- ### 1. Create and install
29
-
30
- ```sh
31
- # Create a new app from the default template
32
- npm create vite-taro@latest my-app
33
-
34
- # Enter the project and install dependencies
35
- cd my-app
36
- npm install
37
- ```
38
-
39
- ### 2. Configure WeChat Mini Program App ID
40
-
41
- The template creates `.env.local`. Set `VITE_PLUGIN_TARO_WECHAT_APP_ID` to your WeChat Mini Program App ID.
42
-
43
- ### 3. Run in development
44
-
45
- ```sh
46
- # WeChat Mini Program: rebuild dist/wx in watch mode
47
- npm run dev:wx
48
-
49
- # Then open dist/wx in WeChat DevTools
50
-
51
- # H5: start the Vite dev server
52
- npm run dev:h5
53
-
54
- # Then open the standard Vite dev URL in your browser
55
- # http://localhost:5173
56
- ```
57
-
58
- You can keep `npm run dev:wx` and `npm run dev:h5` running at the same time in separate terminals.
59
-
60
- Note: Because of WeChat DevTools and Mini Program runtime limitations, hot reload/fast rebuilds for the WeChat target may not always apply cleanly. For day-to-day iteration, prefer the H5 Vite dev server for fast feedback, and periodically verify the Mini Program result in WeChat DevTools.
61
-
62
- ### 4. Build, preview, and typecheck
63
-
64
- ```sh
65
- # Production WeChat Mini Program output
66
- npm run build:wx
67
-
68
- # Production H5 output
69
- npm run build:h5
70
-
71
- # Preview the built H5 app
72
- npm run preview:h5
73
-
74
- # Typecheck with tsgo
75
- npm run typecheck
76
- ```
77
-
78
- ### 5. Use Taro virtual modules
79
-
80
- Use these imports in app code:
81
-
82
- ```tsx
83
- import Taro from 'virtual:taro/api'
84
- import { Text, View } from 'virtual:taro/components'
85
- ```
86
-
87
- | Import | Use |
88
- | --- | --- |
89
- | `virtual:taro/components` | Taro React components such as `View`, `Text`, `Button`, `Image`, and `ScrollView`. |
90
- | `virtual:taro/api` | Taro APIs and hooks such as `Taro.navigateTo`, `Taro.getWindowInfo`, and `Taro.useLaunch`. |
91
-
92
- Usage is the same as Taro itself; see the [Taro website](https://docs.taro.zone) for component and API details.
93
-
94
- You no longer need to install `@tarojs/*` packages; application code should not import from `@tarojs/*`.
95
-
96
-
97
- ## Manual setup for existing apps
98
-
99
- For existing apps or custom project layouts, follow the steps below to wire the plugin manually. First, install the plugin:
100
-
101
- ```sh
102
- npm install -D vite-plugin-taro
103
- ```
104
-
105
- Your app must also provide Vite 8, React 19, React DOM 19, a TypeScript checker, and Node/React type packages. If your app does not already have them, install the missing packages:
106
-
107
- ```sh
108
- npm install react react-dom
109
- npm install -D vite @typescript/native-preview @types/node @types/react @types/react-dom
110
- ```
111
-
112
- You should NOT have direct dependencies on `@tarojs/*` packages anymore. Remove them if you have.
113
-
114
- The steps below create this source shape:
115
-
116
- ```text
117
- my-app/
118
- ├── index.html
119
- ├── package.json
120
- ├── tsconfig.json
121
- ├── vite.config.ts
122
- └── src/
123
- ├── app.css
124
- ├── app.ts
125
- └── pages/
126
- └── index/
127
- └── index.tsx
128
- ```
129
-
130
- You can also see a sample layout at [packages/loan-genius](https://github.com/sep2/vite-plugin-taro/tree/main/packages/loan-genius).
131
-
132
- ### 1. Add TypeScript declarations
133
-
134
- Add the plugin client types to `tsconfig.json` so TypeScript knows about the virtual modules:
135
-
136
- ```json
137
- {
138
- "compilerOptions": {
139
- "jsx": "react-jsx",
140
- "moduleResolution": "bundler",
141
- "types": ["vite/client", "vite-plugin-taro/client"]
142
- },
143
- "include": ["src"]
144
- }
145
- ```
146
-
147
- ### 2. Configure Vite
148
-
149
- Create `vite.config.ts` and choose the plugin target from an environment variable:
150
-
151
- ```ts
152
- import { defineConfig, loadEnv } from 'vite'
153
- import vitePluginTaro, { type VitePluginTaroTarget } from 'vite-plugin-taro'
154
-
155
- const targetEnvName = 'VITE_PLUGIN_TARO_TARGET'
156
-
157
- function getTarget(env: Record<string, string>): VitePluginTaroTarget {
158
- const target = env[targetEnvName]
159
- if (target === 'wx' || target === 'h5') return target
160
- throw new Error(`${targetEnvName} must be "wx" or "h5".`)
161
- }
162
-
163
- export default defineConfig(({ mode }) => {
164
- const env = loadEnv(mode, process.cwd(), 'VITE_PLUGIN_TARO_')
165
- const target = getTarget(env)
166
-
167
- return {
168
- build: {
169
- outDir: `dist/${target}`
170
- },
171
- plugins: [
172
- vitePluginTaro({
173
- target,
174
- app: 'src/app.ts',
175
- pages: [
176
- {
177
- path: 'pages/index/index',
178
- config: {
179
- navigationBarTitleText: 'Home'
180
- }
181
- }
182
- ],
183
- appJson: {
184
- window: {
185
- navigationBarTitleText: 'Demo',
186
- navigationBarBackgroundColor: '#ffffff'
187
- }
188
- },
189
- projectConfigJson: {
190
- appid: env.VITE_PLUGIN_TARO_WECHAT_APP_ID || 'touristappid',
191
- projectname: 'demo',
192
- compileType: 'miniprogram'
193
- },
194
- sitemapJson: {
195
- rules: [{ action: 'allow', page: '*' }]
196
- }
197
- })
198
- ]
199
- }
200
- })
201
- ```
202
-
203
- Important conventions:
204
-
205
- - `target` must be `wx` or `h5` for each Vite run.
206
- - `app` is the root React app component module. It should default-export the app component.
207
- - Every `pages[].path` maps to a file at `src/${path}.tsx`. For example, `pages/index/index` requires `src/pages/index/index.tsx`.
208
- - `appJson.pages` is generated from `pages`; any `pages` field you put in `appJson` is overwritten.
209
- - The plugin does not read Taro CLI config files such as `config/index.ts`, `app.config.ts`, or page `config.ts` files. Pass app and page config through the plugin options.
210
-
211
- ### 3. Create the app component
212
-
213
- `src/app.ts` is the shared application wrapper. It receives the current page as `children`.
214
-
215
- ```tsx
216
- import Taro from 'virtual:taro/api'
217
- import type { PropsWithChildren } from 'react'
218
- import './app.css'
219
-
220
- function App({ children }: PropsWithChildren) {
221
- Taro.useLaunch(() => {
222
- console.log('App launched')
223
- })
224
-
225
- return children
226
- }
227
-
228
- export default App
229
- ```
230
-
231
- Import global styles from the app component. They are collected into `app.wxss` for WeChat builds and included in H5 output.
232
-
233
- ### 4. Create a page component
234
-
235
- `src/pages/index/index.tsx` is the React component for `pages/index/index`.
236
-
237
- ```tsx
238
- import Taro from 'virtual:taro/api'
239
- import { Button, Text, View } from 'virtual:taro/components'
240
-
241
- export default function IndexPage() {
242
- const windowInfo = Taro.getWindowInfo()
243
-
244
- return (
245
- <View className="p-4">
246
- <Text>Viewport width: {windowInfo.windowWidth}</Text>
247
- <Button
248
- onClick={() => {
249
- Taro.showToast({ title: 'Hello from Taro' })
250
- }}
251
- >
252
- Show toast
253
- </Button>
254
- </View>
255
- )
256
- }
257
- ```
258
-
259
- ### 5. Add the H5 HTML shell
260
-
261
- For H5, keep a normal Vite `index.html` with an `#app` mount node. The plugin injects the generated Taro H5 entry automatically, so you do not need a normal Vite `src/main.tsx` script.
262
-
263
- ```html
264
- <!doctype html>
265
- <html lang="en">
266
- <head>
267
- <meta charset="UTF-8" />
268
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
269
- <title>Taro Vite App</title>
270
- </head>
271
- <body>
272
- <div id="app"></div>
273
- </body>
274
- </html>
275
- ```
276
-
277
- ### 6. Add scripts
278
-
279
- Use the same scripts generated by `create-vite-taro`:
280
-
281
- ```json
282
- {
283
- "scripts": {
284
- "dev:wx": "NODE_ENV=development VITE_PLUGIN_TARO_TARGET=wx vite build --watch",
285
- "dev:h5": "NODE_ENV=development VITE_PLUGIN_TARO_TARGET=h5 vite",
286
- "build:wx": "NODE_ENV=production VITE_PLUGIN_TARO_TARGET=wx vite build",
287
- "build:h5": "NODE_ENV=production VITE_PLUGIN_TARO_TARGET=h5 vite build",
288
- "preview:h5": "NODE_ENV=production VITE_PLUGIN_TARO_TARGET=h5 vite preview --outDir dist/h5",
289
- "typecheck": "tsgo -b"
290
- }
291
- }
292
- ```
293
-
294
- On Windows shells, use `cross-env`.
295
-
296
- ### 7. Run each target
297
-
298
- ```sh
299
- npm run dev:wx # Rebuild dist/wx in watch mode
300
- npm run dev:h5 # Start the H5 dev server
301
- npm run build:wx # Build dist/wx
302
- npm run build:h5 # Build dist/h5
303
- npm run preview:h5 # Preview dist/h5
304
- npm run typecheck # Typecheck with tsgo
305
- ```
306
-
307
- Open the generated `dist/wx` directory in WeChat DevTools.
308
-
309
- | Target | Meaning | Output dir |
310
- | --- | --- | --- |
311
- | `wx` | WeChat Mini Program in both dev/prod mode. | `dist/wx` |
312
- | `h5` | H5 production output. | `dist/h5` |
313
-
314
- ## Options
315
-
316
- ```ts
317
- type VitePluginTaroTarget = 'wx' | 'h5'
318
-
319
- type VitePluginTaroPageOption = {
320
- path: string
321
- config: Record<string, unknown>
322
- }
323
-
324
- type VitePluginTaroOptions = {
325
- target: VitePluginTaroTarget
326
- app: string
327
- pages: VitePluginTaroPageOption[]
328
- appJson: Record<string, unknown>
329
- projectConfigJson: Record<string, unknown>
330
- sitemapJson: Record<string, unknown>
331
- }
332
- ```
333
-
334
- | Option | Description |
335
- | --- | --- |
336
- | `target` | Active target for this Vite invocation. Use `wx` for WeChat Mini Program and `h5` for Web. |
337
- | `app` | Source file that default-exports the root React app component, for example `src/app.ts` or `src/app.tsx`. |
338
- | `pages` | Ordered page list. The order becomes `app.json.pages` and the H5 route order. |
339
- | `pages[].path` | Taro-style route and output path without extension, for example `pages/index/index`. The page component must exist at `src/${path}.tsx`. |
340
- | `pages[].config` | Page config merged into the generated WeChat page JSON and H5 route config. |
341
- | `appJson` | Base app config. The plugin overwrites the `pages` field from `options.pages`. |
342
- | `projectConfigJson` | WeChat `project.config.json` content emitted for `wx` builds. It is required by the option type even when the current target is `h5`. |
343
- | `sitemapJson` | WeChat `sitemap.json` content emitted for `wx` builds. It is required by the option type even when the current target is `h5`. |
344
-
345
- ## Styling
346
-
347
- You can use plain CSS, CSS modules, or Tailwind CSS v4.
348
-
349
- For Tailwind CSS v4, import Tailwind from a global CSS file such as `src/app.css`:
350
-
351
- ```css
352
- @import "tailwindcss/theme.css";
353
- @import "tailwindcss/preflight.css";
354
- @import "tailwindcss/utilities.css";
355
-
356
- @source "./";
357
- ```
358
-
359
- The plugin registers `weapp-tailwindcss` for `wx` builds and `@tailwindcss/vite` for `h5` builds. For `wx`, CSS emitted by Vite is collected into `app.wxss`, and page `.wxss` companion files are emitted for each page.
360
-
361
- ## Conditional compilation
362
-
363
- The plugin strips inactive Taro-style conditional comment blocks before Vite parses source. This works in TypeScript, JavaScript, JSX/TSX, CSS, Sass, Less, and Stylus files outside `node_modules`.
364
-
365
- ```ts
366
- // #ifdef wx
367
- console.log('WeChat only')
368
- // #endif
369
-
370
- // #ifdef h5
371
- console.log('H5 only')
372
- // #endif
373
-
374
- // #if wx && !h5
375
- console.log('WeChat expression')
376
- // #elif h5
377
- console.log('H5 expression')
378
- // #else
379
- console.log('fallback')
380
- // #endif
381
- ```
382
-
383
- Supported directives are `#ifdef`, `#ifndef`, `#if`, `#elif`, `#else`, and `#endif`. Conditions use the plugin target tokens `wx` and `h5`; `#if` expressions support `!`, `&&`, and `||`.
384
-
385
- ## Output by target
386
-
387
- ### WeChat Mini Program
388
-
389
- For `target: 'wx'`, the plugin configures Vite to emit WeChat-compatible CommonJS chunks and Mini Program companion files.
390
-
391
- Typical output:
392
-
393
- ```text
394
- dist/wx/
395
- ├── app.js
396
- ├── app.json
397
- ├── app.wxss
398
- ├── base.wxml
399
- ├── comp.js
400
- ├── comp.json
401
- ├── comp.wxml
402
- ├── project.config.json
403
- ├── sitemap.json
404
- ├── utils.wxs
405
- └── pages/**
406
- ```
407
-
408
- Open `dist/wx` with WeChat DevTools; do not open the source project directory.
409
-
410
- ### H5
411
-
412
- For `target: 'h5'`, the plugin injects a generated module into `index.html`, imports Taro's H5 component styles, builds route records from `pages`, and mounts the app with Taro's hash-history router. Routes use the page paths from your config, for example `#/pages/index/index`.
413
-
414
- ## Migrating from Taro
415
-
416
- You can keep most React page components, business logic, assets, and styles, but the build entry moves from Taro CLI config to Vite config.
417
-
418
- Migration checklist:
419
-
420
- 1. Install `vite-plugin-taro` and create `vite.config.ts` with `vitePluginTaro(...)`.
421
- 2. Move app config and page config into the plugin options. The plugin does not read Taro CLI files such as `config/index.ts`, `app.config.ts`, or page `config.ts` files.
422
- 3. Register every page in `pages`. Each page path must match `src/${path}.tsx`.
423
- 4. Replace Taro scripts with Vite scripts that set `VITE_PLUGIN_TARO_TARGET=wx` or `VITE_PLUGIN_TARO_TARGET=h5`.
424
- 5. For H5, add a normal Vite `index.html` with `<div id="app"></div>` and no separate `src/main.tsx` entry.
425
- 6. Replace application imports from `@tarojs/*` with the plugin virtual modules.
426
-
427
- Before:
428
-
429
- ```tsx
430
- import Taro from '@tarojs/taro'
431
- import { Text, View } from '@tarojs/components'
432
- ```
433
-
434
- After:
435
-
436
- ```tsx
437
- import Taro from 'virtual:taro/api'
438
- import { Text, View } from 'virtual:taro/components'
439
- ```
440
-
441
- Direct `@tarojs/*` imports in application code are forbidden. Let the plugin own Taro runtime resolution so WeChat and H5 builds receive the correct target-specific aliases.
442
-
443
- ## Sample app
444
-
445
- The sample app lives in [`packages/loan-genius`](https://github.com/sep2/vite-plugin-taro/tree/main/packages/loan-genius). It demonstrates the page convention, target selection, WeChat output, H5 routing, and Tailwind styling.
446
-
447
- ```sh
448
- git clone https://github.com/sep2/vite-plugin-taro.git
449
-
450
- # Install dependencies
451
- pnpm install
452
-
453
- # Run once, it generates the patched Taro packages
454
- pnpm prepare:taro
455
-
456
- # Build the plugin for sample app to use
457
- pnpm build:plugin
458
-
459
- # Run the sample app in WeChat
460
- pnpm dev:sample:wx
461
-
462
- # Build the sample app to WeChat output
463
- pnpm build:sample:wx
464
-
465
- # Run the sample app in H5 dev mode
466
- pnpm dev:sample:h5
467
-
468
- # Build the sample app to H5 output and preview it
469
- pnpm build:sample:h5
470
- pnpm preview:sample:h5
471
- ```
472
-
473
- Open `packages/loan-genius/dist/wx` with WeChat DevTools to test the Mini Program output.
474
-
475
- ## Develop this repository
476
-
477
- ```sh
478
- pnpm install
479
- pnpm prepare:taro
480
- pnpm build:plugin
481
- pnpm typecheck
482
- ```
483
-
484
- Common scripts:
485
-
486
- | Script | Description |
487
- | --- | --- |
488
- | `pnpm prepare:taro` | Regenerate the patched React 19 Taro packages from upstream npm tarballs and local patch files. |
489
- | `pnpm build:plugin` | Build `packages/vite-plugin-taro` into `dist`. |
490
- | `pnpm typecheck` | Typecheck the plugin and sample app with `tsgo`. |
491
- | `pnpm lint` | Run Biome checks. |
492
- | `pnpm format` | Apply Biome formatting. |
493
- | `pnpm dev:sample:wx` | Build the sample WeChat Mini Program in watch mode. Build the plugin first. |
494
- | `pnpm dev:sample:h5` | Start the sample H5 app in Vite dev mode. Build the plugin first. |
495
- | `pnpm build:sample:wx` | Build the WeChat Mini Program sample to `packages/loan-genius/dist/wx`. |
496
- | `pnpm build:sample:h5` | Build the H5 sample app to `packages/loan-genius/dist/h5`. |
497
- | `pnpm preview:sample:h5` | Preview the built H5 sample. |
498
- | `pnpm publish:dry` | Dry-run package validation and publishing. |
499
- | `pnpm release <version\|bump>` | Validate, bump versions, create the release commit and tag, and push to trigger CI publishing. |
500
- | `pnpm publish:all` | Publish the public packages in dependency order; mainly used by the tag-based Trusted Publishing workflow. |
501
-
502
- ## Limitations
503
-
504
- - Only `wx` and `h5` targets are generated today.
505
- - Application code must not import `@tarojs/*` packages directly.
506
-
507
- ## Troubleshooting
508
-
509
- | Problem | Check |
510
- | --- | --- |
511
- | `VITE_PLUGIN_TARO_TARGET must be "wx" or "h5"` | Set the target environment variable in your script or `.env` file. |
512
- | `pnpm install` says dependency build scripts were ignored | Run `pnpm approve-builds` and approve the requested dependency build scripts. |
513
- | A page cannot be resolved | Confirm that `pages[].path` has a matching `src/${path}.tsx` file. |
514
- | WeChat DevTools cannot open the app | Open the generated `dist/wx` folder and check `projectConfigJson.appid`. |
515
- | H5 shows a blank page | Keep `<div id="app"></div>` in `index.html`, register the plugin, and avoid adding a separate default Vite `main.tsx` entry. |
516
- | Taro APIs are missing or behave differently | Remove direct `@tarojs/*` imports from application code and import Taro from `virtual:taro/api`. |
517
- | Components render without expected styles on H5 | Import components from `virtual:taro/components` and keep the plugin enabled for the `h5` target. |
518
- | Tailwind classes do not appear | Ensure your global CSS imports Tailwind and includes an `@source` path that covers your source files. |
519
-
520
- ## Release workflow
521
-
522
- This repository publishes automatically with npm Trusted Publishing and GitHub Actions. Normal pushes to `main` do not publish; only tags matching `v*.*.*` trigger `.github/workflows/publish.yml`.
523
-
524
- Create a release:
525
-
526
- ```sh
527
- pnpm release patch
528
- ```
529
-
530
- `pnpm release` requires a clean `main` working tree, runs `pnpm version:bump`, validates with `pnpm publish:dry -- --no-git-check`, creates the `chore: release vX.Y.Z` commit and `vX.Y.Z` tag, then pushes the branch and tag to trigger CI. You can also release an exact version or prerelease:
531
-
532
- ```sh
533
- pnpm release 0.2.0
534
- pnpm release prerelease --preid beta
535
- pnpm release patch --dry-run
536
- pnpm release patch --no-push
537
- ```
538
-
539
- CI runs `pnpm publish:all -- --no-git-check`, packs packages in dependency order, and publishes public packages through npm OIDC. Do not configure `NPM_TOKEN` for the publish workflow; each npm package's Trusted Publisher should point to `publish.yml`.
540
-
541
- ## License
542
-
543
- MIT