vite-plugin-taro 0.5.9 → 0.5.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +1 -1
- package/README.md +1 -1
- package/dist/node/plugins/wx/dev/plugins.js +8 -0
- package/dist/node/plugins/wx/dev/wx-dev-options.js +3 -17
- package/dist/node/plugins/wx/placement/placer.js +17 -3
- package/package.json +3 -3
- package/src/node/plugins/wx/dev/plugins.ts +8 -0
- package/src/node/plugins/wx/dev/wx-dev-options.ts +3 -18
- package/src/node/plugins/wx/placement/placer.ts +19 -3
- package/dist/node/plugins/wx/dev/empty-output-directory.d.ts +0 -4
- package/dist/node/plugins/wx/dev/empty-output-directory.js +0 -17
- package/src/node/plugins/wx/dev/empty-output-directory.ts +0 -22
package/README.en.md
CHANGED
|
@@ -20,7 +20,7 @@ Continue with the [Quick Start guide](https://vpt.js.org/guides/quick-start/).
|
|
|
20
20
|
|
|
21
21
|
### React Hot Reload in WeChat DevTools
|
|
22
22
|
|
|
23
|
-
<video src="https://github.com/user-attachments/assets/
|
|
23
|
+
<video src="https://github.com/user-attachments/assets/cb93daf5-1827-496a-bb74-8397975accf6" controls autoplay muted loop playsinline width="100%"></video>
|
|
24
24
|
|
|
25
25
|
- **Vite 8 + React 19** Build one codebase for WeChat Mini Program and Web with the Vite ecosystem.
|
|
26
26
|
- **Hot reload** Preserve App data, the active page, React component state, and input state while editing.
|
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ npm create vite-taro@latest my-app
|
|
|
21
21
|
|
|
22
22
|
### 已支持微信开发者工具的 React 热更新
|
|
23
23
|
|
|
24
|
-
<video src="https://github.com/user-attachments/assets/
|
|
24
|
+
<video src="https://github.com/user-attachments/assets/cb93daf5-1827-496a-bb74-8397975accf6" controls autoplay muted loop playsinline width="100%"></video>
|
|
25
25
|
|
|
26
26
|
- **Vite 8 + React 19** 基于 Vite 生态,一份代码覆盖微信小程序与 Web。
|
|
27
27
|
- **热更新** 编辑代码时保留 App 数据、当前页面、React 组件状态与输入状态。
|
|
@@ -23,6 +23,14 @@ export function createWxDevelopmentPlugin(options) {
|
|
|
23
23
|
config() {
|
|
24
24
|
return {
|
|
25
25
|
build: {
|
|
26
|
+
// The development output is the live Mini Program project opened by WeChat DevTools, not a disposable
|
|
27
|
+
// build artifact. Deleting and recreating its directory tree during a dev-server restart disrupts
|
|
28
|
+
// DevTools' hot-reload watcher; recreating the same paths does not reliably attach that watcher again.
|
|
29
|
+
// The host then continues writing hmr/patches.js, but DevTools no longer observes it and therefore never
|
|
30
|
+
// re-executes the Page shell that consumes and acknowledges the patches. Keep the watched paths present
|
|
31
|
+
// across host restarts and let the initial complete build overwrite active outputs. This plugin applies
|
|
32
|
+
// only to `serve`; production builds retain Vite's normal output cleanup.
|
|
33
|
+
emptyOutDir: false,
|
|
26
34
|
// Disable maps in resolved environment config as well as final output so Oxc and Babel skip producing
|
|
27
35
|
// intermediate maps that Rolldown would discard.
|
|
28
36
|
sourcemap: false
|
|
@@ -5,7 +5,6 @@ import { once } from '../../../utils/once.js';
|
|
|
5
5
|
import { resolvePackageFile } from '../../../utils/packages.js';
|
|
6
6
|
import { appShellFileName } from '../module.js';
|
|
7
7
|
import { createWxDevMode } from './create-wx-dev-mode.js';
|
|
8
|
-
import { createInitialOutputDirectoryCleaner } from './empty-output-directory.js';
|
|
9
8
|
/** Installs the physical WX output and runtime conventions over Vite's browser-oriented bundled-development options. */
|
|
10
9
|
export function installWxDevOptions({ bundledDev, server, options }) {
|
|
11
10
|
// The buildEnd hook and its one-shot result belong to the same abstraction. Consumers can await startup without receiving
|
|
@@ -42,26 +41,13 @@ export function installWxDevOptions({ bundledDev, server, options }) {
|
|
|
42
41
|
});
|
|
43
42
|
rolldownOptions.experimental ??= {};
|
|
44
43
|
rolldownOptions.experimental.devMode = createWxDevMode(rolldownOptions.experimental.devMode, await bundleRuntimeSource());
|
|
45
|
-
const initializeOutputDirectory = createInitialOutputDirectoryCleaner(server.config.build.outDir);
|
|
46
|
-
const initializeOutputDirectoryPlugin = {
|
|
47
|
-
name: 'vpt:wx-initialize-output-directory',
|
|
48
|
-
renderStart: {
|
|
49
|
-
order: 'pre',
|
|
50
|
-
// DevEngine bypasses Vite's build-only output preparation. Remove stale startup contents once, before
|
|
51
|
-
// Rolldown starts treating its in-memory incremental output as authoritative for later complete builds.
|
|
52
|
-
handler: initializeOutputDirectory
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
44
|
const reportInitialBuildPlugin = {
|
|
56
45
|
name: 'vpt:wx-report-initial-build',
|
|
57
46
|
buildEnd: settleInitialBuild
|
|
58
47
|
};
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
reportInitialBuildPlugin,
|
|
63
|
-
createViteReporter(server)
|
|
64
|
-
];
|
|
48
|
+
// Preserve the physical paths watched by WeChat DevTools across host restarts; the complete build overwrites every
|
|
49
|
+
// active output without disrupting the hot-reload watcher.
|
|
50
|
+
rolldownOptions.plugins = [rolldownOptions.plugins, reportInitialBuildPlugin, createViteReporter(server)];
|
|
65
51
|
disableViteOxcSourcemap(rolldownOptions.plugins);
|
|
66
52
|
return rolldownOptions;
|
|
67
53
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
1
2
|
import { getWxExecutionKind, isTransportModule } from '../module.js';
|
|
2
3
|
import { createPlacementPlan, getSubpackageName, isGeneratedSubpackageFile, mainPackage } from './plan.js';
|
|
3
4
|
/**
|
|
@@ -94,9 +95,9 @@ export function createPlacer() {
|
|
|
94
95
|
if (location.kind === 'main') {
|
|
95
96
|
return 'assets/[name]-[hash].js';
|
|
96
97
|
}
|
|
97
|
-
// The
|
|
98
|
-
//
|
|
99
|
-
return `${location.root}/assets
|
|
98
|
+
// The package group replaces Rolldown's [name], so recover the first bundled source file's name from
|
|
99
|
+
// the final chunk module list instead of leaking the generated package hash into the filename.
|
|
100
|
+
return `${location.root}/assets/${getFirstModuleName(chunk)}-[hash].js`;
|
|
100
101
|
},
|
|
101
102
|
// Keep generic assets independent of native output identities assigned after bundling.
|
|
102
103
|
assetFileNames: 'assets/[name]-[hash][extname]'
|
|
@@ -138,6 +139,19 @@ export function createPlacer() {
|
|
|
138
139
|
}
|
|
139
140
|
};
|
|
140
141
|
}
|
|
142
|
+
/** Uses the first bundled source filename as the readable identity of a generated subpackage chunk. */
|
|
143
|
+
function getFirstModuleName(chunk) {
|
|
144
|
+
const firstModuleId = chunk.moduleIds[0];
|
|
145
|
+
if (!firstModuleId) {
|
|
146
|
+
throw new Error('wx subpackage chunk has no source modules');
|
|
147
|
+
}
|
|
148
|
+
const normalizedId = firstModuleId.replaceAll('\\', '/');
|
|
149
|
+
const suffixIndex = normalizedId.search(/[?#]/);
|
|
150
|
+
const cleanId = suffixIndex === -1 ? normalizedId : normalizedId.slice(0, suffixIndex);
|
|
151
|
+
const fileName = path.posix.basename(cleanId);
|
|
152
|
+
const extension = path.posix.extname(fileName);
|
|
153
|
+
return extension ? fileName.slice(0, -extension.length) : fileName;
|
|
154
|
+
}
|
|
141
155
|
/** Compares main by discriminant and generated subpackages by their unique physical root. */
|
|
142
156
|
function hasSameLocation(left, right) {
|
|
143
157
|
return left.kind === 'main' ? right.kind === 'main' : right.kind === 'subpackage' && left.root === right.root;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-taro",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.11",
|
|
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",
|
|
@@ -75,8 +75,8 @@
|
|
|
75
75
|
"rolldown": "1.2.3",
|
|
76
76
|
"tailwindcss": "^4.3.3",
|
|
77
77
|
"weapp-tailwindcss": "^5.2.11",
|
|
78
|
-
"@tarojs/
|
|
79
|
-
"@tarojs/react": "npm:vite-plugin-taro-react@0.5.
|
|
78
|
+
"@tarojs/react": "npm:vite-plugin-taro-react@0.5.11",
|
|
79
|
+
"@tarojs/plugin-framework-react": "npm:vite-plugin-taro-plugin-framework-react@0.5.11"
|
|
80
80
|
},
|
|
81
81
|
"peerDependencies": {
|
|
82
82
|
"react": "^19.0.0",
|
|
@@ -29,6 +29,14 @@ export function createWxDevelopmentPlugin(options: VitePluginTaroOptions): Plugi
|
|
|
29
29
|
config() {
|
|
30
30
|
return {
|
|
31
31
|
build: {
|
|
32
|
+
// The development output is the live Mini Program project opened by WeChat DevTools, not a disposable
|
|
33
|
+
// build artifact. Deleting and recreating its directory tree during a dev-server restart disrupts
|
|
34
|
+
// DevTools' hot-reload watcher; recreating the same paths does not reliably attach that watcher again.
|
|
35
|
+
// The host then continues writing hmr/patches.js, but DevTools no longer observes it and therefore never
|
|
36
|
+
// re-executes the Page shell that consumes and acknowledges the patches. Keep the watched paths present
|
|
37
|
+
// across host restarts and let the initial complete build overwrite active outputs. This plugin applies
|
|
38
|
+
// only to `serve`; production builds retain Vite's normal output cleanup.
|
|
39
|
+
emptyOutDir: false,
|
|
32
40
|
// Disable maps in resolved environment config as well as final output so Oxc and Babel skip producing
|
|
33
41
|
// intermediate maps that Rolldown would discard.
|
|
34
42
|
sourcemap: false
|
|
@@ -8,7 +8,6 @@ import { once } from '../../../utils/once.ts'
|
|
|
8
8
|
import { resolvePackageFile } from '../../../utils/packages.ts'
|
|
9
9
|
import { appShellFileName } from '../module.ts'
|
|
10
10
|
import { createWxDevMode } from './create-wx-dev-mode.ts'
|
|
11
|
-
import { createInitialOutputDirectoryCleaner } from './empty-output-directory.ts'
|
|
12
11
|
|
|
13
12
|
export type BundledDevRolldownOptions = InputOptions & {
|
|
14
13
|
experimental?: {
|
|
@@ -77,28 +76,14 @@ export function installWxDevOptions({
|
|
|
77
76
|
await bundleRuntimeSource()
|
|
78
77
|
)
|
|
79
78
|
|
|
80
|
-
const initializeOutputDirectory = createInitialOutputDirectoryCleaner(server.config.build.outDir)
|
|
81
|
-
const initializeOutputDirectoryPlugin: Plugin = {
|
|
82
|
-
name: 'vpt:wx-initialize-output-directory',
|
|
83
|
-
renderStart: {
|
|
84
|
-
order: 'pre',
|
|
85
|
-
// DevEngine bypasses Vite's build-only output preparation. Remove stale startup contents once, before
|
|
86
|
-
// Rolldown starts treating its in-memory incremental output as authoritative for later complete builds.
|
|
87
|
-
handler: initializeOutputDirectory
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
79
|
const reportInitialBuildPlugin: Plugin = {
|
|
92
80
|
name: 'vpt:wx-report-initial-build',
|
|
93
81
|
buildEnd: settleInitialBuild
|
|
94
82
|
}
|
|
95
83
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
reportInitialBuildPlugin,
|
|
100
|
-
createViteReporter(server)
|
|
101
|
-
]
|
|
84
|
+
// Preserve the physical paths watched by WeChat DevTools across host restarts; the complete build overwrites every
|
|
85
|
+
// active output without disrupting the hot-reload watcher.
|
|
86
|
+
rolldownOptions.plugins = [rolldownOptions.plugins, reportInitialBuildPlugin, createViteReporter(server)]
|
|
102
87
|
disableViteOxcSourcemap(rolldownOptions.plugins)
|
|
103
88
|
|
|
104
89
|
return rolldownOptions
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
1
2
|
import type { Rolldown } from 'vite'
|
|
2
3
|
import { getWxExecutionKind, isTransportModule } from '../module.ts'
|
|
3
4
|
import {
|
|
@@ -117,9 +118,9 @@ export function createPlacer() {
|
|
|
117
118
|
if (location.kind === 'main') {
|
|
118
119
|
return 'assets/[name]-[hash].js'
|
|
119
120
|
}
|
|
120
|
-
// The
|
|
121
|
-
//
|
|
122
|
-
return `${location.root}/assets
|
|
121
|
+
// The package group replaces Rolldown's [name], so recover the first bundled source file's name from
|
|
122
|
+
// the final chunk module list instead of leaking the generated package hash into the filename.
|
|
123
|
+
return `${location.root}/assets/${getFirstModuleName(chunk)}-[hash].js`
|
|
123
124
|
},
|
|
124
125
|
// Keep generic assets independent of native output identities assigned after bundling.
|
|
125
126
|
assetFileNames: 'assets/[name]-[hash][extname]'
|
|
@@ -165,6 +166,21 @@ export function createPlacer() {
|
|
|
165
166
|
}
|
|
166
167
|
}
|
|
167
168
|
|
|
169
|
+
/** Uses the first bundled source filename as the readable identity of a generated subpackage chunk. */
|
|
170
|
+
function getFirstModuleName(chunk: Rolldown.PreRenderedChunk): string {
|
|
171
|
+
const firstModuleId = chunk.moduleIds[0]
|
|
172
|
+
if (!firstModuleId) {
|
|
173
|
+
throw new Error('wx subpackage chunk has no source modules')
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const normalizedId = firstModuleId.replaceAll('\\', '/')
|
|
177
|
+
const suffixIndex = normalizedId.search(/[?#]/)
|
|
178
|
+
const cleanId = suffixIndex === -1 ? normalizedId : normalizedId.slice(0, suffixIndex)
|
|
179
|
+
const fileName = path.posix.basename(cleanId)
|
|
180
|
+
const extension = path.posix.extname(fileName)
|
|
181
|
+
return extension ? fileName.slice(0, -extension.length) : fileName
|
|
182
|
+
}
|
|
183
|
+
|
|
168
184
|
/** Compares main by discriminant and generated subpackages by their unique physical root. */
|
|
169
185
|
function hasSameLocation(left: PackageLocation, right: PackageLocation): boolean {
|
|
170
186
|
return left.kind === 'main' ? right.kind === 'main' : right.kind === 'subpackage' && left.root === right.root
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
/** Creates the one startup cleanup allowed before Rolldown begins tracking incremental output in memory. */
|
|
2
|
-
export declare function createInitialOutputDirectoryCleaner(directory: string): () => Promise<void>;
|
|
3
|
-
/** Empties an output directory without replacing the directory itself or deleting Git metadata. */
|
|
4
|
-
export declare function emptyOutputDirectory(directory: string): Promise<void>;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs/promises';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import { once } from '../../../utils/once.js';
|
|
4
|
-
/** Creates the one startup cleanup allowed before Rolldown begins tracking incremental output in memory. */
|
|
5
|
-
export function createInitialOutputDirectoryCleaner(directory) {
|
|
6
|
-
// Later full builds suppress byte-identical emitted assets. Clearing again would delete those files behind Rolldown's
|
|
7
|
-
// output cache, so the writer would correctly emit no bytes and leave the physical Mini Program incomplete.
|
|
8
|
-
return once(() => emptyOutputDirectory(directory));
|
|
9
|
-
}
|
|
10
|
-
/** Empties an output directory without replacing the directory itself or deleting Git metadata. */
|
|
11
|
-
export async function emptyOutputDirectory(directory) {
|
|
12
|
-
await fs.mkdir(directory, { recursive: true });
|
|
13
|
-
const entries = await fs.readdir(directory);
|
|
14
|
-
await Promise.all(entries
|
|
15
|
-
.filter((entry) => entry !== '.git')
|
|
16
|
-
.map((entry) => fs.rm(path.join(directory, entry), { force: true, recursive: true })));
|
|
17
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs/promises'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
import { once } from '../../../utils/once.ts'
|
|
4
|
-
|
|
5
|
-
/** Creates the one startup cleanup allowed before Rolldown begins tracking incremental output in memory. */
|
|
6
|
-
export function createInitialOutputDirectoryCleaner(directory: string): () => Promise<void> {
|
|
7
|
-
// Later full builds suppress byte-identical emitted assets. Clearing again would delete those files behind Rolldown's
|
|
8
|
-
// output cache, so the writer would correctly emit no bytes and leave the physical Mini Program incomplete.
|
|
9
|
-
return once(() => emptyOutputDirectory(directory))
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/** Empties an output directory without replacing the directory itself or deleting Git metadata. */
|
|
13
|
-
export async function emptyOutputDirectory(directory: string): Promise<void> {
|
|
14
|
-
await fs.mkdir(directory, { recursive: true })
|
|
15
|
-
const entries = await fs.readdir(directory)
|
|
16
|
-
|
|
17
|
-
await Promise.all(
|
|
18
|
-
entries
|
|
19
|
-
.filter((entry) => entry !== '.git')
|
|
20
|
-
.map((entry) => fs.rm(path.join(directory, entry), { force: true, recursive: true }))
|
|
21
|
-
)
|
|
22
|
-
}
|