vite-plugin-taro 0.5.3 → 0.5.5

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 (33) hide show
  1. package/README.en.md +1 -1
  2. package/README.md +1 -1
  3. package/dist/node/plugins/client/client-taro.js +12 -8
  4. package/dist/node/plugins/h5/create-stencil-client-adapter.d.ts +21 -0
  5. package/dist/node/plugins/h5/create-stencil-client-adapter.js +92 -0
  6. package/dist/node/plugins/h5/plugins.d.ts +10 -0
  7. package/dist/node/plugins/h5/plugins.js +50 -61
  8. package/dist/node/plugins/wx/dev/dev-host.js +103 -216
  9. package/dist/node/plugins/wx/dev/hmr-files.d.ts +4 -5
  10. package/dist/node/plugins/wx/dev/hmr-files.js +18 -8
  11. package/dist/node/plugins/wx/dev/patch-publisher.d.ts +25 -5
  12. package/dist/node/plugins/wx/dev/patch-publisher.js +30 -9
  13. package/dist/node/plugins/wx/dev/react-refresh.d.ts +12 -0
  14. package/dist/node/plugins/wx/dev/react-refresh.js +111 -108
  15. package/dist/node/plugins/wx/dev/wx-dev-options.d.ts +25 -0
  16. package/dist/node/plugins/wx/dev/wx-dev-options.js +147 -0
  17. package/dist/node/utils/oxc-transform.d.ts +21 -0
  18. package/dist/node/utils/oxc-transform.js +58 -0
  19. package/dist/node/utils/serialized-task-queue.d.ts +6 -2
  20. package/dist/node/utils/serialized-task-queue.js +10 -2
  21. package/dist/runtime/wx/dev/dev-runtime.js +70 -26
  22. package/package.json +13 -12
  23. package/src/node/plugins/client/client-taro.ts +13 -8
  24. package/src/node/plugins/h5/create-stencil-client-adapter.ts +110 -0
  25. package/src/node/plugins/h5/plugins.ts +52 -84
  26. package/src/node/plugins/wx/dev/dev-host.ts +121 -256
  27. package/src/node/plugins/wx/dev/hmr-files.ts +20 -8
  28. package/src/node/plugins/wx/dev/patch-publisher.ts +36 -10
  29. package/src/node/plugins/wx/dev/react-refresh.ts +125 -129
  30. package/src/node/plugins/wx/dev/wx-dev-options.ts +200 -0
  31. package/src/node/utils/oxc-transform.ts +77 -0
  32. package/src/node/utils/serialized-task-queue.ts +15 -3
  33. package/src/runtime/wx/dev/dev-runtime.ts +80 -28
package/README.en.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # vite-plugin-taro
2
2
 
3
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)
4
+ ![Vite](https://img.shields.io/npm/dependency-version/vite-plugin-taro/peer/vite?label=Vite)
5
5
  [![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6
6
 
7
7
  [简体中文](README.md) | English
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # vite-plugin-taro
2
2
 
3
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)
4
+ ![Vite](https://img.shields.io/npm/dependency-version/vite-plugin-taro/peer/vite?label=Vite)
5
5
  [![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6
6
 
7
7
  简体中文 | [English](README.en.md)
@@ -1,5 +1,5 @@
1
1
  import { normalizeModuleId } from '../../utils/modules.js';
2
- import { packageRequire, resolvePackageFile } from '../../utils/packages.js';
2
+ import { resolvePackageFile } from '../../utils/packages.js';
3
3
  import { clientTaroNativeId } from './constant.js';
4
4
  import { injectTaroFrameworkApis } from './inject-taro-framework-apis.js';
5
5
  /*
@@ -26,13 +26,19 @@ const clientTaroModules = new Map([
26
26
  ]);
27
27
  /** Creates the shared Taro facade backed by the selected target's API implementation. */
28
28
  export function createClientTaroPlugin(target) {
29
- const platformTaroPath = resolvePlatformTaroPath(target);
29
+ const platformTaroId = resolvePlatformTaroId(target);
30
30
  return {
31
31
  name: 'vpt:client-taro',
32
32
  enforce: 'pre',
33
- resolveId(id, importer) {
33
+ async resolveId(id, importer) {
34
34
  if (id === '@tarojs/taro') {
35
- return isClientTaroFacade(importer) ? platformTaroPath : clientTaroApiPath;
35
+ if (!isClientTaroFacade(importer)) {
36
+ return clientTaroApiPath;
37
+ }
38
+ // Delegate the platform backend to Vite instead of returning an absolute dependency path. H5 marks this
39
+ // backend as an optimization root, so delegation lets Vite substitute its prebundled facade. Removing it
40
+ // bypasses CommonJS interop and exposes backend details such as base64-js directly to the browser.
41
+ return this.resolve(platformTaroId, importer, { skipSelf: true });
36
42
  }
37
43
  return clientTaroModules.get(id);
38
44
  },
@@ -44,10 +50,8 @@ export function createClientTaroPlugin(target) {
44
50
  }
45
51
  };
46
52
  }
47
- function resolvePlatformTaroPath(target) {
48
- return target === 'h5'
49
- ? packageRequire.resolve('@tarojs/plugin-platform-h5/dist/runtime/apis')
50
- : packageRequire.resolve('@tarojs/taro');
53
+ function resolvePlatformTaroId(target) {
54
+ return target === 'h5' ? '@tarojs/plugin-platform-h5/dist/runtime/apis' : '@tarojs/taro';
51
55
  }
52
56
  function isClientTaroFacade(importer) {
53
57
  return importer !== undefined && normalizeModuleId(importer) === normalizedClientTaroApiPath;
@@ -0,0 +1,21 @@
1
+ import type { Plugin } from 'vite';
2
+ /**
3
+ * Creates the compiler-owned adaptation of Stencil's client style insertion.
4
+ *
5
+ * Taro components inject their styles through this internal client. Its default insertion point places those styles
6
+ * after application CSS, allowing component defaults to override application rules. The adapter is registered in both
7
+ * Vite's application pipeline and the independent dependency-optimization build: removing either registration leaves
8
+ * production or development with an unadapted client. This explicit dual registration removes the former optimization
9
+ * exclusion while keeping one transformation implementation.
10
+ */
11
+ export declare function createStencilClientAdapter(): Plugin;
12
+ /**
13
+ * Applies the shared Stencil adaptation with one Oxc parse and one range edit.
14
+ *
15
+ * The physical module check is essential because the optimizer and application pipelines can
16
+ * present query-suffixed or platform-normalized IDs. Transforming by source text alone could
17
+ * modify user code that happens to contain the same insertion expression. Source maps remain
18
+ * enabled because this adapter runs before Vite/Rolldown's later transforms in both pipelines;
19
+ * dropping the map would attribute downstream diagnostics to the edited generated positions.
20
+ */
21
+ export declare function adaptStencilClient(code: string, id: string): import("../../utils/transform.ts").AstTransformResult | undefined;
@@ -0,0 +1,92 @@
1
+ import { normalizeModuleId } from '../../utils/modules.js';
2
+ import { transformWithOxcWalker } from '../../utils/oxc-transform.js';
3
+ import { packageRequire } from '../../utils/packages.js';
4
+ const stencilClientPath = packageRequire.resolve('@stencil/core/internal/client', {
5
+ paths: [packageRequire.resolve('@tarojs/components/package.json')]
6
+ });
7
+ const normalizedStencilClientPath = normalizeModuleId(stencilClientPath);
8
+ /**
9
+ * Creates the compiler-owned adaptation of Stencil's client style insertion.
10
+ *
11
+ * Taro components inject their styles through this internal client. Its default insertion point places those styles
12
+ * after application CSS, allowing component defaults to override application rules. The adapter is registered in both
13
+ * Vite's application pipeline and the independent dependency-optimization build: removing either registration leaves
14
+ * production or development with an unadapted client. This explicit dual registration removes the former optimization
15
+ * exclusion while keeping one transformation implementation.
16
+ */
17
+ export function createStencilClientAdapter() {
18
+ return {
19
+ name: 'vpt:h5-stencil-client',
20
+ transform: adaptStencilClient
21
+ };
22
+ }
23
+ /**
24
+ * Applies the shared Stencil adaptation with one Oxc parse and one range edit.
25
+ *
26
+ * The physical module check is essential because the optimizer and application pipelines can
27
+ * present query-suffixed or platform-normalized IDs. Transforming by source text alone could
28
+ * modify user code that happens to contain the same insertion expression. Source maps remain
29
+ * enabled because this adapter runs before Vite/Rolldown's later transforms in both pipelines;
30
+ * dropping the map would attribute downstream diagnostics to the edited generated positions.
31
+ */
32
+ export function adaptStencilClient(code, id) {
33
+ if (normalizeModuleId(id) !== normalizedStencilClientPath) {
34
+ return;
35
+ }
36
+ return transformWithOxcWalker({
37
+ code,
38
+ filename: id,
39
+ sourcemap: true,
40
+ createVisitor: createStencilVisitor
41
+ });
42
+ }
43
+ /**
44
+ * Finds Stencil's exact default style insertion call and replaces only its insertion anchor.
45
+ *
46
+ * Stencil normally inserts `styleElm` before the first stylesheet link. During Vite development,
47
+ * application CSS is commonly represented by a `<style>` element instead, so that link-only
48
+ * lookup returns `null` and Taro component defaults are appended after application CSS. Those
49
+ * defaults then override the application's selectors despite having the same specificity.
50
+ *
51
+ * Taro Stencil components are identified by the `sc-taro-` scope prefix. For those components,
52
+ * the replacement anchors before the first `<style>` or stylesheet `<link>`, keeping component
53
+ * defaults before application rules. The original link-only lookup is preserved for every other
54
+ * Stencil component so VPT does not globally redefine upstream style-ordering behavior.
55
+ */
56
+ function createStencilVisitor(editor) {
57
+ return function enter(node) {
58
+ if (node.type !== 'CallExpression' ||
59
+ node.callee.type !== 'MemberExpression' ||
60
+ node.callee.computed ||
61
+ node.callee.object.type !== 'Identifier' ||
62
+ node.callee.object.name !== 'styleContainerNode' ||
63
+ node.callee.property.type !== 'Identifier' ||
64
+ node.callee.property.name !== 'insertBefore') {
65
+ return;
66
+ }
67
+ // Match the complete upstream call, not merely `insertBefore`: range edits have no
68
+ // generated-AST type safety, so a broad match could silently alter unrelated runtime
69
+ // behavior when Stencil changes its implementation.
70
+ const [style, query] = node.arguments;
71
+ const selector = query?.type === 'CallExpression' ? query.arguments[0] : undefined;
72
+ if (node.arguments.length !== 2 ||
73
+ style?.type !== 'Identifier' ||
74
+ style.name !== 'styleElm' ||
75
+ query?.type !== 'CallExpression' ||
76
+ query.callee.type !== 'MemberExpression' ||
77
+ query.callee.computed ||
78
+ query.callee.object.type !== 'Identifier' ||
79
+ query.callee.object.name !== 'styleContainerNode' ||
80
+ query.callee.property.type !== 'Identifier' ||
81
+ query.callee.property.name !== 'querySelector' ||
82
+ selector?.type !== 'Literal' ||
83
+ selector.value !== 'link') {
84
+ return;
85
+ }
86
+ // Replace only the second argument expression. Preserving the surrounding Stencil
87
+ // source avoids Babel-style whole-file regeneration and keeps its formatting, comments,
88
+ // and source positions stable. Removing this edit restores the H5 cascade bug described
89
+ // above; applying it unconditionally would change non-Taro Stencil components.
90
+ editor.overwrite(query.start, query.end, 'scopeId.startsWith("sc-taro-") ? styleContainerNode.querySelector("style,link[rel=\\"stylesheet\\"]") : styleContainerNode.querySelector("link")');
91
+ };
92
+ }
@@ -2,3 +2,13 @@ import type { PluginOption } from 'vite';
2
2
  import type { VitePluginTaroOptions } from '../../../options.ts';
3
3
  /** Creates the plugins that own the H5 target. */
4
4
  export declare function createH5TargetPlugins(options: VitePluginTaroOptions): PluginOption[];
5
+ /**
6
+ * Coarse source prefilter for the upstream Taro API transform.
7
+ *
8
+ * The plugin has two independent responsibilities: adapting imports from the compiler facade and normalizing camel-case
9
+ * H5 ARIA attributes. Matching `aria` followed by any uppercase letter is intentionally broader than Taro's current
10
+ * attribute table. A duplicated exact list would silently stop routing files through Babel when upstream adds another
11
+ * attribute, while a broad false positive costs only one unnecessary transform. Ordinary application modules match
12
+ * neither branch and remain entirely outside Babel's parser and generator.
13
+ */
14
+ export declare const h5TaroApiTransformCodeFilter: RegExp;
@@ -1,10 +1,10 @@
1
- import { types } from '@babel/core';
2
- import babel from '@rolldown/plugin-babel';
1
+ import babel, { defineRolldownBabelPreset } from '@rolldown/plugin-babel';
3
2
  import { esTarget } from '../../utils/constant.js';
4
3
  import { toViteFileImportPath } from '../../utils/modules.js';
5
4
  import { packageRequire } from '../../utils/packages.js';
6
5
  import { clientTaroApiId } from '../client/client-taro.js';
7
6
  import { h5AppPath } from './constant.js';
7
+ import { createStencilClientAdapter } from './create-stencil-client-adapter.js';
8
8
  import { createModuleResolver } from './resolver/module-resolver.js';
9
9
  /** Creates the plugins that own the H5 target. */
10
10
  export function createH5TargetPlugins(options) {
@@ -21,12 +21,6 @@ function createH5TargetPlugin(options) {
21
21
  resolve: {
22
22
  mainFields: ['main:h5', 'browser', 'module', 'jsnext:main', 'jsnext'],
23
23
  alias: [
24
- {
25
- find: /^@stencil\/core\/internal\/client$/,
26
- replacement: packageRequire.resolve('@stencil/core/internal/client', {
27
- paths: [packageRequire.resolve('@tarojs/components/package.json')]
28
- })
29
- },
30
24
  {
31
25
  find: /^@tarojs\/components$/,
32
26
  replacement: packageRequire.resolve('@tarojs/components/lib/react')
@@ -38,7 +32,15 @@ function createH5TargetPlugin(options) {
38
32
  ]
39
33
  },
40
34
  optimizeDeps: {
41
- exclude: ['@stencil/core/internal/client']
35
+ // The compiler-owned H5 app and Taro facade are injected after Vite's initial HTML scan. Prebundle
36
+ // the facade's platform backend as one boundary so its CommonJS implementation details receive
37
+ // interop without duplicating their package list. ReactDOM needs the same treatment for the H5 app.
38
+ include: ['@tarojs/plugin-platform-h5/dist/runtime/apis', 'react-dom/client'],
39
+ // Dependency optimization is its own Rolldown build and does not run application transform plugins.
40
+ // Register the same adapter there so optimized Taro components cannot embed Stencil's original client.
41
+ rolldownOptions: {
42
+ plugins: [createStencilClientAdapter()]
43
+ }
42
44
  },
43
45
  build: {
44
46
  target: esTarget
@@ -86,64 +88,51 @@ function createH5IndexHtmlTags() {
86
88
  }
87
89
  ];
88
90
  }
89
- /** Creates H5-only Babel transforms for Stencil CSS ordering and Taro API imports. */
91
+ /**
92
+ * Coarse source prefilter for the upstream Taro API transform.
93
+ *
94
+ * The plugin has two independent responsibilities: adapting imports from the compiler facade and normalizing camel-case
95
+ * H5 ARIA attributes. Matching `aria` followed by any uppercase letter is intentionally broader than Taro's current
96
+ * attribute table. A duplicated exact list would silently stop routing files through Babel when upstream adds another
97
+ * attribute, while a broad false positive costs only one unnecessary transform. Ordinary application modules match
98
+ * neither branch and remain entirely outside Babel's parser and generator.
99
+ */
100
+ export const h5TaroApiTransformCodeFilter = /virtual:taro\/api|\baria[A-Z]/;
101
+ /** Creates a filterable Babel preset containing Taro's upstream, scope-aware API transform. */
102
+ function createH5TaroApiPreset() {
103
+ const transformTaroApiPath = packageRequire.resolve('babel-plugin-transform-taroapi');
104
+ const definition = packageRequire(packageRequire.resolve('@tarojs/plugin-platform-h5/dist/definition.json'));
105
+ return defineRolldownBabelPreset({
106
+ preset: function h5TaroApiPreset() {
107
+ return {
108
+ plugins: [
109
+ [
110
+ transformTaroApiPath,
111
+ {
112
+ packageName: clientTaroApiId,
113
+ definition
114
+ }
115
+ ]
116
+ ]
117
+ };
118
+ },
119
+ rolldown: {
120
+ // @rolldown/plugin-babel can lift a preset filter into its native transform hook. The Taro plugin must be
121
+ // nested in this preset rather than passed through Babel's top-level `plugins`: explicit plugins may apply
122
+ // to every module, so their presence deliberately disables Rolldown's preset-level code filtering.
123
+ filter: { code: h5TaroApiTransformCodeFilter }
124
+ }
125
+ });
126
+ }
127
+ /** Creates H5-only transforms for Stencil CSS ordering and Taro API imports. */
90
128
  function createH5SupportPlugins() {
91
129
  return [
130
+ createStencilClientAdapter(),
92
131
  babel({
93
- include: /[\\/]@stencil[\\/]core[\\/]internal[\\/]client[\\/]index\.js(?:\?.*)?$/,
94
- exclude: [],
95
- plugins: [rewriteStencilStyleInsertion]
96
- }),
97
- babel({
98
- plugins: [
99
- [
100
- packageRequire.resolve('babel-plugin-transform-taroapi'),
101
- {
102
- packageName: clientTaroApiId,
103
- definition: packageRequire(packageRequire.resolve('@tarojs/plugin-platform-h5/dist/definition.json'))
104
- }
105
- ]
106
- ]
132
+ presets: [createH5TaroApiPreset()]
107
133
  })
108
134
  ];
109
135
  }
110
- /** Keeps Stencil-injected Taro component styles before application stylesheets. */
111
- function rewriteStencilStyleInsertion() {
112
- return {
113
- name: 'vpt:rewrite-stencil-style-insertion',
114
- visitor: {
115
- CallExpression(callPath) {
116
- if (!isStencilStyleInsertBeforeCall(callPath)) {
117
- return;
118
- }
119
- callPath
120
- .get('arguments.1')
121
- .replaceWith(types.conditionalExpression(types.callExpression(types.memberExpression(types.identifier('scopeId'), types.identifier('startsWith')), [types.stringLiteral('sc-taro-')]), createStyleQuery('style,link[rel="stylesheet"]'), createStyleQuery('link')));
122
- }
123
- }
124
- };
125
- }
126
- /** Identifies Stencil's default component-style insertion call. */
127
- function isStencilStyleInsertBeforeCall(callPath) {
128
- const { callee, arguments: callArguments } = callPath.node;
129
- return (types.isMemberExpression(callee) &&
130
- types.isIdentifier(callee.object, { name: 'styleContainerNode' }) &&
131
- types.isIdentifier(callee.property, { name: 'insertBefore' }) &&
132
- types.isIdentifier(callArguments[0], { name: 'styleElm' }) &&
133
- isStyleQuery(callArguments[1], 'link'));
134
- }
135
- /** Identifies one style-container querySelector call. */
136
- function isStyleQuery(node, selector) {
137
- return (types.isCallExpression(node) &&
138
- types.isMemberExpression(node.callee) &&
139
- types.isIdentifier(node.callee.object, { name: 'styleContainerNode' }) &&
140
- types.isIdentifier(node.callee.property, { name: 'querySelector' }) &&
141
- types.isStringLiteral(node.arguments[0], { value: selector }));
142
- }
143
- /** Creates one style-container querySelector call. */
144
- function createStyleQuery(selector) {
145
- return types.callExpression(types.memberExpression(types.identifier('styleContainerNode'), types.identifier('querySelector')), [types.stringLiteral(selector)]);
146
- }
147
136
  /** Creates H5 Taro compile-time constants. */
148
137
  function createH5Defines() {
149
138
  return {