vite-plugin-rnw 0.0.7 → 0.0.8-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 +1 -34
- package/dist/index.d.ts +5 -65
- package/dist/index.js +81 -324
- package/package.json +6 -22
- package/dist/index.cjs +0 -472
- package/dist/index.d.cts +0 -68
- package/dist/refresh-runtime.js +0 -648
package/README.md
CHANGED
|
@@ -2,12 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A vite plugin for React Native Web projects.
|
|
4
4
|
|
|
5
|
-
This plugin
|
|
6
|
-
|
|
7
|
-
- enable [Fast Refresh](https://www.npmjs.com/package/react-refresh) in development (requires react >= 16.9)
|
|
8
|
-
- use the [automatic JSX runtime](https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html)
|
|
9
|
-
- use custom Babel plugins/presets
|
|
10
|
-
- small installation size
|
|
5
|
+
This plugin uses the [react plugin](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) internally and applies a lot of fixes for react native web on top.
|
|
11
6
|
|
|
12
7
|
```js
|
|
13
8
|
// vite.config.js
|
|
@@ -69,31 +64,3 @@ rnw({
|
|
|
69
64
|
}
|
|
70
65
|
})
|
|
71
66
|
```
|
|
72
|
-
|
|
73
|
-
#### Proposed syntax
|
|
74
|
-
|
|
75
|
-
If you are using ES syntax that are still in proposal status (e.g. class properties), you can selectively enable them with the `babel.parserOpts.plugins` option:
|
|
76
|
-
|
|
77
|
-
```js
|
|
78
|
-
rnw({
|
|
79
|
-
babel: {
|
|
80
|
-
parserOpts: {
|
|
81
|
-
plugins: ["decorators-legacy"],
|
|
82
|
-
},
|
|
83
|
-
},
|
|
84
|
-
});
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
This option does not enable _code transformation_. That is handled by esbuild.
|
|
88
|
-
|
|
89
|
-
**Note:** TypeScript syntax is handled automatically.
|
|
90
|
-
|
|
91
|
-
Here's the [complete list of Babel parser plugins](https://babeljs.io/docs/en/babel-parser#ecmascript-proposalshttpsgithubcombabelproposals).
|
|
92
|
-
|
|
93
|
-
## Consistent components exports
|
|
94
|
-
|
|
95
|
-
For React refresh to work correctly, your file should only export React components. You can find a good explanation in the [Gatsby docs](https://www.gatsbyjs.com/docs/reference/local-development/fast-refresh/#how-it-works).
|
|
96
|
-
|
|
97
|
-
If an incompatible change in exports is found, the module will be invalidated and HMR will propagate. To make it easier to export simple constants alongside your component, the module is only invalidated when their value changes.
|
|
98
|
-
|
|
99
|
-
You can catch mistakes and get more detailed warning with this [eslint rule](https://github.com/ArnaudBarre/eslint-plugin-react-refresh).
|
package/dist/index.d.ts
CHANGED
|
@@ -1,68 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Plugin } from "vite";
|
|
2
|
+
import { Options } from "@vitejs/plugin-react";
|
|
3
3
|
|
|
4
4
|
//#region src/index.d.ts
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
include?: string | RegExp | Array<string | RegExp>;
|
|
8
|
-
exclude?: string | RegExp | Array<string | RegExp>;
|
|
9
|
-
/**
|
|
10
|
-
* Control where the JSX factory is imported from.
|
|
11
|
-
* https://esbuild.github.io/api/#jsx-import-source
|
|
12
|
-
* @default 'react'
|
|
13
|
-
*/
|
|
14
|
-
jsxImportSource?: string;
|
|
15
|
-
/**
|
|
16
|
-
* Note: Skipping React import with classic runtime is not supported from v4
|
|
17
|
-
* @default "automatic"
|
|
18
|
-
*/
|
|
19
|
-
jsxRuntime?: "classic" | "automatic";
|
|
20
|
-
/**
|
|
21
|
-
* Babel configuration applied in both dev and prod.
|
|
22
|
-
*/
|
|
23
|
-
babel?: BabelOptions | ((id: string, options: {
|
|
24
|
-
ssr?: boolean;
|
|
25
|
-
}) => BabelOptions);
|
|
26
|
-
/**
|
|
27
|
-
* React Fast Refresh runtime URL prefix.
|
|
28
|
-
* Useful in a module federation context to enable HMR by specifying
|
|
29
|
-
* the host application URL in the Vite config of a remote application.
|
|
30
|
-
* @example
|
|
31
|
-
* reactRefreshHost: 'http://localhost:3000'
|
|
32
|
-
*/
|
|
33
|
-
reactRefreshHost?: string;
|
|
34
|
-
/**
|
|
35
|
-
* If set, disables the recommendation to use `@vitejs/plugin-react-oxc`
|
|
36
|
-
*/
|
|
37
|
-
disableOxcRecommendation?: boolean;
|
|
38
|
-
}
|
|
39
|
-
type BabelOptions = Omit<TransformOptions, "ast" | "filename" | "root" | "sourceFileName" | "sourceMaps" | "inputSourceMap">;
|
|
40
|
-
/**
|
|
41
|
-
* The object type used by the `options` passed to plugins with
|
|
42
|
-
* an `api.reactBabel` method.
|
|
43
|
-
*/
|
|
44
|
-
interface ReactBabelOptions extends BabelOptions {
|
|
45
|
-
plugins: Extract<BabelOptions["plugins"], any[]>;
|
|
46
|
-
presets: Extract<BabelOptions["presets"], any[]>;
|
|
47
|
-
overrides: Extract<BabelOptions["overrides"], any[]>;
|
|
48
|
-
parserOpts: ParserOptions & {
|
|
49
|
-
plugins: Extract<ParserOptions["plugins"], any[]>;
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
type ReactBabelHook = (babelConfig: ReactBabelOptions, context: ReactBabelHookContext, config: ResolvedConfig) => void;
|
|
53
|
-
type ReactBabelHookContext = {
|
|
54
|
-
ssr: boolean;
|
|
55
|
-
id: string;
|
|
56
|
-
};
|
|
57
|
-
type ViteReactPluginApi = {
|
|
58
|
-
/**
|
|
59
|
-
* Manipulate the Babel options of `@vitejs/plugin-react`
|
|
60
|
-
*/
|
|
61
|
-
reactBabel?: ReactBabelHook;
|
|
62
|
-
};
|
|
63
|
-
declare function rnw(opts?: Options): Plugin[];
|
|
64
|
-
declare namespace rnw {
|
|
65
|
-
var preambleCode: string;
|
|
66
|
-
}
|
|
5
|
+
type RnwOptions = Options;
|
|
6
|
+
declare function rnw(opts?: RnwOptions): Plugin[];
|
|
67
7
|
//#endregion
|
|
68
|
-
export {
|
|
8
|
+
export { RnwOptions, rnw };
|
package/dist/index.js
CHANGED
|
@@ -1,101 +1,20 @@
|
|
|
1
|
-
import { dirname, join } from "node:path";
|
|
2
|
-
import { fileURLToPath } from "node:url";
|
|
3
|
-
import { readFileSync } from "node:fs";
|
|
4
1
|
import * as vite from "vite";
|
|
5
2
|
import { createFilter } from "vite";
|
|
6
3
|
import { esbuildFlowPlugin, flowPlugin } from "@bunchtogether/vite-plugin-flow";
|
|
7
4
|
import commonjs from "vite-plugin-commonjs";
|
|
8
|
-
import {
|
|
5
|
+
import { makeIdFiltersToMatchWithQuery } from "@rolldown/pluginutils";
|
|
6
|
+
import MagicString from "magic-string";
|
|
7
|
+
import react from "@vitejs/plugin-react";
|
|
9
8
|
|
|
10
|
-
//#region src/refresh-utils.ts
|
|
11
|
-
const runtimePublicPath = "/@react-refresh";
|
|
12
|
-
const reactCompRE = /extends\s+(?:React\.)?(?:Pure)?Component/;
|
|
13
|
-
const refreshContentRE = /\$RefreshReg\$\(/;
|
|
14
|
-
const preambleCode = `import { injectIntoGlobalHook } from "__BASE__${runtimePublicPath.slice(1)}";
|
|
15
|
-
injectIntoGlobalHook(window);
|
|
16
|
-
window.$RefreshReg$ = () => {};
|
|
17
|
-
window.$RefreshSig$ = () => (type) => type;`;
|
|
18
|
-
const getPreambleCode = (base) => preambleCode.replace("__BASE__", base);
|
|
19
|
-
const avoidSourceMapOption = Symbol();
|
|
20
|
-
function addRefreshWrapper(code, map, pluginName, id, reactRefreshHost = "") {
|
|
21
|
-
const hasRefresh = refreshContentRE.test(code);
|
|
22
|
-
const onlyReactComp = !hasRefresh && reactCompRE.test(code);
|
|
23
|
-
const normalizedMap = map === avoidSourceMapOption ? null : map;
|
|
24
|
-
if (!hasRefresh && !onlyReactComp) return {
|
|
25
|
-
code,
|
|
26
|
-
map: normalizedMap
|
|
27
|
-
};
|
|
28
|
-
const avoidSourceMap = map === avoidSourceMapOption;
|
|
29
|
-
const newMap = typeof normalizedMap === "string" ? JSON.parse(normalizedMap) : normalizedMap;
|
|
30
|
-
let newCode = code;
|
|
31
|
-
if (hasRefresh) {
|
|
32
|
-
const refreshHead = removeLineBreaksIfNeeded(`let prevRefreshReg;
|
|
33
|
-
let prevRefreshSig;
|
|
34
|
-
|
|
35
|
-
if (import.meta.hot && !inWebWorker) {
|
|
36
|
-
if (!window.$RefreshReg$) {
|
|
37
|
-
throw new Error(
|
|
38
|
-
"${pluginName} can't detect preamble. Something is wrong."
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
prevRefreshReg = window.$RefreshReg$;
|
|
43
|
-
prevRefreshSig = window.$RefreshSig$;
|
|
44
|
-
window.$RefreshReg$ = RefreshRuntime.getRefreshReg(${JSON.stringify(id)});
|
|
45
|
-
window.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
`, avoidSourceMap);
|
|
49
|
-
newCode = `${refreshHead}${newCode}
|
|
50
|
-
|
|
51
|
-
if (import.meta.hot && !inWebWorker) {
|
|
52
|
-
window.$RefreshReg$ = prevRefreshReg;
|
|
53
|
-
window.$RefreshSig$ = prevRefreshSig;
|
|
54
|
-
}
|
|
55
|
-
`;
|
|
56
|
-
if (newMap) newMap.mappings = ";".repeat(16) + newMap.mappings;
|
|
57
|
-
}
|
|
58
|
-
const sharedHead = removeLineBreaksIfNeeded(`import * as RefreshRuntime from "${reactRefreshHost}${runtimePublicPath}";
|
|
59
|
-
const inWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope;
|
|
60
|
-
|
|
61
|
-
`, avoidSourceMap);
|
|
62
|
-
newCode = `${sharedHead}${newCode}
|
|
63
|
-
|
|
64
|
-
if (import.meta.hot && !inWebWorker) {
|
|
65
|
-
RefreshRuntime.__hmr_import(import.meta.url).then((currentExports) => {
|
|
66
|
-
RefreshRuntime.registerExportsForReactRefresh(${JSON.stringify(id)}, currentExports);
|
|
67
|
-
import.meta.hot.accept((nextExports) => {
|
|
68
|
-
if (!nextExports) return;
|
|
69
|
-
const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate(${JSON.stringify(id)}, currentExports, nextExports);
|
|
70
|
-
if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage);
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
`;
|
|
75
|
-
if (newMap) newMap.mappings = ";;;" + newMap.mappings;
|
|
76
|
-
return {
|
|
77
|
-
code: newCode,
|
|
78
|
-
map: newMap
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
function removeLineBreaksIfNeeded(code, enabled) {
|
|
82
|
-
return enabled ? code.replace(/\n/g, "") : code;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
//#endregion
|
|
86
9
|
//#region src/transforms.ts
|
|
87
10
|
/**
|
|
88
|
-
* Code transformation utilities for fixing React Native package compatibility issues
|
|
89
|
-
*/
|
|
90
|
-
/**
|
|
91
11
|
* Analyzes require statements in code and maps them to module imports.
|
|
92
12
|
* Handles patterns like: varName = require('path').prop or require('path').default
|
|
93
13
|
*/
|
|
94
14
|
function analyzeRequireStatements(originalCode, exportedVars) {
|
|
95
15
|
const importMap = /* @__PURE__ */ new Map();
|
|
96
16
|
for (const varName of exportedVars) {
|
|
97
|
-
const
|
|
98
|
-
const requireMatch = requirePattern.exec(originalCode);
|
|
17
|
+
const requireMatch = new RegExp(`${varName}\\s*=\\s*[\\s\\S]*?require\\(['"]([^'"]+)['"]\\)(?:\\.([\\w]+))?`, "g").exec(originalCode);
|
|
99
18
|
if (requireMatch) {
|
|
100
19
|
const [, modulePath, prop] = requireMatch;
|
|
101
20
|
const key = `${modulePath}:${prop || "default"}`;
|
|
@@ -109,11 +28,6 @@ function analyzeRequireStatements(originalCode, exportedVars) {
|
|
|
109
28
|
* Removes try/catch blocks that contain require statements and export let declarations.
|
|
110
29
|
* This cleans up the problematic CommonJS patterns.
|
|
111
30
|
*/
|
|
112
|
-
function removeTryCatchRequireBlocks(code) {
|
|
113
|
-
let transformed = code.replace(/try\s*\{[^{}]*?require\([^)]+\)[^{}]*?\}\s*catch[^{}]*?\{[^{}]*?\}/gs, "");
|
|
114
|
-
transformed = transformed.replace(/export let \w+;/g, "");
|
|
115
|
-
return transformed;
|
|
116
|
-
}
|
|
117
31
|
/**
|
|
118
32
|
* Generates direct export statements from the import map.
|
|
119
33
|
* Creates modern ESM exports like: export { default as varName } from 'module';
|
|
@@ -130,38 +44,60 @@ function generateDirectExports(importMap) {
|
|
|
130
44
|
/**
|
|
131
45
|
* Transforms React Native Reanimated webUtils files to fix problematic
|
|
132
46
|
* export let + try/catch + require patterns by converting them to proper ESM.
|
|
133
|
-
*
|
|
47
|
+
*
|
|
134
48
|
* This transformation handles the incompatible module patterns in React Native Reanimated
|
|
135
49
|
* that cause build errors in Vite due to mixing CommonJS require() with ESM exports.
|
|
136
50
|
*/
|
|
137
|
-
function
|
|
138
|
-
if (!isProduction || !id.includes("node_modules/react-native-reanimated") || !id.includes("ReanimatedModule/js-reanimated/webUtils") || !
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
51
|
+
function transformReanimatedWebUtilsWithMap(code, id, isProduction, opts) {
|
|
52
|
+
if (!isProduction || !id.includes("node_modules/react-native-reanimated") || !id.includes("ReanimatedModule/js-reanimated/webUtils") || !code.includes("export let") || !code.includes("try") || !code.includes("require")) return {
|
|
53
|
+
code,
|
|
54
|
+
map: null,
|
|
55
|
+
changed: false
|
|
56
|
+
};
|
|
57
|
+
const exportedVars = Array.from(code.matchAll(/export let (\w+);/g)).map((match) => match[1]);
|
|
58
|
+
if (exportedVars.length === 0) return {
|
|
59
|
+
code,
|
|
60
|
+
map: null,
|
|
61
|
+
changed: false
|
|
62
|
+
};
|
|
63
|
+
const importMap = analyzeRequireStatements(code, exportedVars);
|
|
64
|
+
const ms = new MagicString(code);
|
|
65
|
+
let changed = false;
|
|
66
|
+
for (const m of code.matchAll(/try\s*\{[^{}]*?require\([^)]+\)[^{}]*?\}\s*catch[^{}]*?\{[^{}]*?\}/gs)) {
|
|
67
|
+
const start = m.index;
|
|
68
|
+
const end = start + m[0].length;
|
|
69
|
+
ms.remove(start, end);
|
|
70
|
+
changed = true;
|
|
71
|
+
}
|
|
72
|
+
for (const m of code.matchAll(/export let \w+;/g)) {
|
|
73
|
+
const start = m.index;
|
|
74
|
+
const end = start + m[0].length;
|
|
75
|
+
ms.remove(start, end);
|
|
76
|
+
changed = true;
|
|
77
|
+
}
|
|
144
78
|
const exports = generateDirectExports(importMap);
|
|
145
|
-
if (exports)
|
|
146
|
-
|
|
79
|
+
if (exports) {
|
|
80
|
+
ms.append(`\n${exports}`);
|
|
81
|
+
changed = true;
|
|
82
|
+
}
|
|
83
|
+
if (!changed) return {
|
|
84
|
+
code,
|
|
85
|
+
map: null,
|
|
86
|
+
changed: false
|
|
87
|
+
};
|
|
88
|
+
return {
|
|
89
|
+
code: ms.toString(),
|
|
90
|
+
map: ms.generateMap({
|
|
91
|
+
source: (opts === null || opts === void 0 ? void 0 : opts.source) ?? id.split("?")[0],
|
|
92
|
+
includeContent: true,
|
|
93
|
+
hires: true
|
|
94
|
+
}),
|
|
95
|
+
changed: true
|
|
96
|
+
};
|
|
147
97
|
}
|
|
148
98
|
|
|
149
99
|
//#endregion
|
|
150
100
|
//#region src/index.ts
|
|
151
|
-
const silenceUseClientWarning = (userConfig) => ({ rollupOptions: { onwarn(warning, defaultHandler) {
|
|
152
|
-
var _userConfig$build;
|
|
153
|
-
if (warning.code === "MODULE_LEVEL_DIRECTIVE" && (warning.message.includes("use client") || warning.message.includes("use server"))) return;
|
|
154
|
-
if (warning.code === "SOURCEMAP_ERROR" && warning.message.includes("resolve original location") && warning.pos === 0) return;
|
|
155
|
-
if ((_userConfig$build = userConfig.build) === null || _userConfig$build === void 0 || (_userConfig$build = _userConfig$build.rollupOptions) === null || _userConfig$build === void 0 ? void 0 : _userConfig$build.onwarn) userConfig.build.rollupOptions.onwarn(warning, defaultHandler);
|
|
156
|
-
else defaultHandler(warning);
|
|
157
|
-
} } });
|
|
158
|
-
const _dirname = dirname(fileURLToPath(import.meta.url));
|
|
159
|
-
const refreshRuntimePath = join(_dirname, "refresh-runtime.js");
|
|
160
|
-
let babel;
|
|
161
|
-
async function loadBabel() {
|
|
162
|
-
if (!babel) babel = await import("@babel/core");
|
|
163
|
-
return babel;
|
|
164
|
-
}
|
|
165
101
|
const extensions = [
|
|
166
102
|
".web.js",
|
|
167
103
|
".web.ts",
|
|
@@ -178,45 +114,17 @@ const extensions = [
|
|
|
178
114
|
];
|
|
179
115
|
const defaultIncludeRE = /\.[tj]sx?$/;
|
|
180
116
|
const defaultExcludeRE = /\/node_modules\/(?!react-native|@react-native|expo|@expo)/;
|
|
181
|
-
const tsRE = /\.tsx?$/;
|
|
182
|
-
const getInitialOptions = (opts) => {
|
|
183
|
-
if (opts.jsxRuntime === "classic") if ("rolldownVersion" in vite) return { oxc: { jsx: {
|
|
184
|
-
runtime: "classic",
|
|
185
|
-
development: false
|
|
186
|
-
} } };
|
|
187
|
-
else return { esbuild: { jsx: "transform" } };
|
|
188
|
-
else return {
|
|
189
|
-
esbuild: {
|
|
190
|
-
jsx: "automatic",
|
|
191
|
-
jsxImportSource: opts.jsxImportSource
|
|
192
|
-
},
|
|
193
|
-
optimizeDeps: "rolldownVersion" in vite ? { rollupOptions: { jsx: { mode: "automatic" } } } : { esbuildOptions: { jsx: "automatic" } }
|
|
194
|
-
};
|
|
195
|
-
};
|
|
196
117
|
function rnw(opts = {}) {
|
|
197
|
-
var _opts$babel;
|
|
198
118
|
const include = opts.include ?? defaultIncludeRE;
|
|
199
119
|
const exclude = opts.exclude ?? defaultExcludeRE;
|
|
200
120
|
const filter = createFilter(include, exclude);
|
|
201
|
-
const jsxImportSource = opts.jsxImportSource ?? "react";
|
|
202
|
-
const jsxImportRuntime = `${jsxImportSource}/jsx-runtime`;
|
|
203
|
-
const jsxImportDevRuntime = `${jsxImportSource}/jsx-dev-runtime`;
|
|
204
|
-
let runningInVite = false;
|
|
205
121
|
let isProduction = true;
|
|
206
|
-
|
|
207
|
-
let skipFastRefresh = true;
|
|
208
|
-
let runPluginOverrides;
|
|
209
|
-
let staticBabelOptions;
|
|
210
|
-
const importReactRE = /\bimport\s+(?:\*\s+as\s+)?React\b/;
|
|
211
|
-
const viteBabel = {
|
|
122
|
+
const rnwPlugin = {
|
|
212
123
|
name: "vite:react-native-web-babel",
|
|
213
124
|
enforce: "pre",
|
|
214
|
-
config(_userConfig,
|
|
215
|
-
|
|
216
|
-
const development = env.mode === "development";
|
|
217
|
-
const initialOptions = getInitialOptions(opts);
|
|
125
|
+
config(_userConfig, { mode }) {
|
|
126
|
+
const development = mode === "development";
|
|
218
127
|
return {
|
|
219
|
-
...initialOptions,
|
|
220
128
|
define: {
|
|
221
129
|
global: "window",
|
|
222
130
|
DEV: JSON.stringify(development),
|
|
@@ -224,26 +132,25 @@ function rnw(opts = {}) {
|
|
|
224
132
|
_frameTimestamp: void 0,
|
|
225
133
|
_WORKLET: false,
|
|
226
134
|
__DEV__: JSON.stringify(development),
|
|
227
|
-
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV ||
|
|
135
|
+
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || mode),
|
|
228
136
|
EXPO_OS: JSON.stringify("web"),
|
|
229
137
|
"process.env.EXPO_OS": JSON.stringify("web"),
|
|
230
138
|
"global.Error": "Error"
|
|
231
139
|
},
|
|
232
|
-
optimizeDeps: {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
},
|
|
140
|
+
optimizeDeps: { esbuildOptions: {
|
|
141
|
+
resolveExtensions: extensions,
|
|
142
|
+
loader: {
|
|
143
|
+
".js": "jsx",
|
|
144
|
+
".mjs": "jsx"
|
|
145
|
+
},
|
|
146
|
+
plugins: [esbuildFlowPlugin(/* @__PURE__ */ new RegExp(/\.(flow|jsx?)$/), (_path) => "jsx")]
|
|
147
|
+
} },
|
|
241
148
|
build: { rollupOptions: {
|
|
242
149
|
treeshake: "safest",
|
|
243
150
|
plugins: [{
|
|
244
|
-
name: "
|
|
245
|
-
async transform(
|
|
246
|
-
if (id.includes("react-native-css-interop")) return { moduleSideEffects: "no-treeshake" };
|
|
151
|
+
name: "treeshake-fix",
|
|
152
|
+
async transform(_code, id) {
|
|
153
|
+
if (id.includes("react-native-css-interop") || id.includes("react-native-css") || id.includes("expo-modules-core")) return { moduleSideEffects: "no-treeshake" };
|
|
247
154
|
}
|
|
248
155
|
}]
|
|
249
156
|
} },
|
|
@@ -254,128 +161,23 @@ function rnw(opts = {}) {
|
|
|
254
161
|
};
|
|
255
162
|
},
|
|
256
163
|
configResolved(config) {
|
|
257
|
-
runningInVite = true;
|
|
258
|
-
projectRoot = config.root;
|
|
259
164
|
isProduction = config.isProduction;
|
|
260
|
-
skipFastRefresh = isProduction || config.command === "build" || config.server.hmr === false;
|
|
261
|
-
if ("jsxPure" in opts) config.logger.warnOnce("[@vitejs/plugin-react] jsxPure was removed. You can configure esbuild.jsxSideEffects directly.");
|
|
262
|
-
const hooks = config.plugins.map((plugin) => {
|
|
263
|
-
var _plugin$api;
|
|
264
|
-
return (_plugin$api = plugin.api) === null || _plugin$api === void 0 ? void 0 : _plugin$api.reactBabel;
|
|
265
|
-
}).filter(defined);
|
|
266
|
-
if (hooks.length > 0) runPluginOverrides = (babelOptions, context) => {
|
|
267
|
-
hooks.forEach((hook) => hook(babelOptions, context, config));
|
|
268
|
-
};
|
|
269
|
-
else if (typeof opts.babel !== "function") staticBabelOptions = createBabelOptions(opts.babel);
|
|
270
|
-
},
|
|
271
|
-
options(options) {
|
|
272
|
-
if (!runningInVite) {
|
|
273
|
-
options.jsx = {
|
|
274
|
-
mode: opts.jsxRuntime,
|
|
275
|
-
importSource: opts.jsxImportSource
|
|
276
|
-
};
|
|
277
|
-
return options;
|
|
278
|
-
}
|
|
279
165
|
},
|
|
280
166
|
transform: {
|
|
281
167
|
filter: { id: {
|
|
282
168
|
include: makeIdFiltersToMatchWithQuery(include),
|
|
283
|
-
exclude:
|
|
169
|
+
exclude: makeIdFiltersToMatchWithQuery(exclude)
|
|
284
170
|
} },
|
|
285
171
|
async handler(code, id, options) {
|
|
286
172
|
const [filepath] = id.split("?");
|
|
287
|
-
if (!
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
ssr
|
|
295
|
-
});
|
|
296
|
-
return newBabelOptions;
|
|
297
|
-
})();
|
|
298
|
-
const plugins = [...babelOptions.plugins];
|
|
299
|
-
const isJSX = filepath.endsWith("x");
|
|
300
|
-
const useFastRefresh = !skipFastRefresh && !ssr && (isJSX || (opts.jsxRuntime === "classic" ? importReactRE.test(code) : code.includes(jsxImportDevRuntime) || code.includes(jsxImportRuntime)));
|
|
301
|
-
if (useFastRefresh) plugins.push([await loadPlugin("react-refresh/babel"), { skipEnvCheck: true }]);
|
|
302
|
-
if (opts.jsxRuntime === "classic" && isJSX) {
|
|
303
|
-
if (!isProduction) plugins.push(await loadPlugin("@babel/plugin-transform-react-jsx-self"), await loadPlugin("@babel/plugin-transform-react-jsx-source"));
|
|
304
|
-
}
|
|
305
|
-
const parserPlugins = [...babelOptions.parserOpts.plugins];
|
|
306
|
-
if (!filepath.endsWith(".ts")) parserPlugins.push("jsx");
|
|
307
|
-
if (tsRE.test(filepath)) parserPlugins.push("typescript");
|
|
308
|
-
const babel$1 = await loadBabel();
|
|
309
|
-
let toTransform = code;
|
|
310
|
-
toTransform = transformReanimatedWebUtils(toTransform, code, id, isProduction);
|
|
311
|
-
const result = await babel$1.transformAsync(toTransform, {
|
|
312
|
-
...babelOptions,
|
|
313
|
-
root: projectRoot,
|
|
314
|
-
filename: id,
|
|
315
|
-
sourceFileName: filepath,
|
|
316
|
-
retainLines: getReactCompilerPlugin(plugins) != null ? false : !isProduction && isJSX && opts.jsxRuntime !== "classic",
|
|
317
|
-
parserOpts: {
|
|
318
|
-
...babelOptions.parserOpts,
|
|
319
|
-
sourceType: "module",
|
|
320
|
-
allowAwaitOutsideFunction: true,
|
|
321
|
-
plugins: parserPlugins
|
|
322
|
-
},
|
|
323
|
-
generatorOpts: {
|
|
324
|
-
...babelOptions.generatorOpts,
|
|
325
|
-
importAttributesKeyword: "with",
|
|
326
|
-
decoratorsBeforeExport: true
|
|
327
|
-
},
|
|
328
|
-
plugins,
|
|
329
|
-
sourceMaps: true
|
|
330
|
-
});
|
|
331
|
-
if (result) {
|
|
332
|
-
if (!useFastRefresh) return {
|
|
333
|
-
code: result.code,
|
|
334
|
-
map: result.map
|
|
335
|
-
};
|
|
336
|
-
return addRefreshWrapper(result.code, result.map, "@vitejs/plugin-react", id, opts.reactRefreshHost);
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
};
|
|
341
|
-
const dependencies = [
|
|
342
|
-
"react",
|
|
343
|
-
"react-dom",
|
|
344
|
-
jsxImportDevRuntime,
|
|
345
|
-
jsxImportRuntime
|
|
346
|
-
];
|
|
347
|
-
const staticBabelPlugins = typeof opts.babel === "object" ? ((_opts$babel = opts.babel) === null || _opts$babel === void 0 ? void 0 : _opts$babel.plugins) ?? [] : [];
|
|
348
|
-
const reactCompilerPlugin = getReactCompilerPlugin(staticBabelPlugins);
|
|
349
|
-
if (reactCompilerPlugin != null) {
|
|
350
|
-
const reactCompilerRuntimeModule = getReactCompilerRuntimeModule(reactCompilerPlugin);
|
|
351
|
-
dependencies.push(reactCompilerRuntimeModule);
|
|
352
|
-
}
|
|
353
|
-
const viteReactRefresh = {
|
|
354
|
-
name: "vite:react-native-web-refresh",
|
|
355
|
-
enforce: "pre",
|
|
356
|
-
config: (userConfig) => ({
|
|
357
|
-
build: silenceUseClientWarning(userConfig),
|
|
358
|
-
optimizeDeps: { include: dependencies },
|
|
359
|
-
resolve: { dedupe: ["react", "react-dom"] }
|
|
360
|
-
}),
|
|
361
|
-
resolveId: {
|
|
362
|
-
filter: { id: exactRegex(runtimePublicPath) },
|
|
363
|
-
handler(id) {
|
|
364
|
-
if (id === runtimePublicPath) return id;
|
|
365
|
-
}
|
|
366
|
-
},
|
|
367
|
-
load: {
|
|
368
|
-
filter: { id: exactRegex(runtimePublicPath) },
|
|
369
|
-
handler(id) {
|
|
370
|
-
if (id === runtimePublicPath) return readFileSync(refreshRuntimePath, "utf-8").replace(/__README_URL__/g, "https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react");
|
|
173
|
+
if (!filter(filepath)) return;
|
|
174
|
+
const transformResult = transformReanimatedWebUtilsWithMap(code, id, isProduction, { source: filepath });
|
|
175
|
+
if (!transformResult.changed) return null;
|
|
176
|
+
return {
|
|
177
|
+
code: transformResult.code,
|
|
178
|
+
map: transformResult.map
|
|
179
|
+
};
|
|
371
180
|
}
|
|
372
|
-
},
|
|
373
|
-
transformIndexHtml(_, config) {
|
|
374
|
-
if (!skipFastRefresh) return [{
|
|
375
|
-
tag: "script",
|
|
376
|
-
attrs: { type: "module" },
|
|
377
|
-
children: getPreambleCode(config.server.config.base)
|
|
378
|
-
}];
|
|
379
181
|
}
|
|
380
182
|
};
|
|
381
183
|
return [
|
|
@@ -383,66 +185,21 @@ function rnw(opts = {}) {
|
|
|
383
185
|
{
|
|
384
186
|
name: "treat-js-files-as-jsx",
|
|
385
187
|
async transform(code, id) {
|
|
386
|
-
if (
|
|
387
|
-
return vite.transformWithEsbuild(code, id, {
|
|
188
|
+
if (id.match(/\.js$/) || id.match(/\.mjs$/)) return vite.transformWithEsbuild(code, id, {
|
|
388
189
|
loader: "jsx",
|
|
389
190
|
jsx: "automatic"
|
|
390
191
|
});
|
|
192
|
+
return null;
|
|
391
193
|
}
|
|
392
194
|
},
|
|
393
195
|
commonjs(),
|
|
394
|
-
|
|
395
|
-
|
|
196
|
+
rnwPlugin,
|
|
197
|
+
react({
|
|
198
|
+
...opts,
|
|
199
|
+
exclude
|
|
200
|
+
})
|
|
396
201
|
];
|
|
397
202
|
}
|
|
398
|
-
rnw.preambleCode = preambleCode;
|
|
399
|
-
const loadedPlugin = /* @__PURE__ */ new Map();
|
|
400
|
-
function loadPlugin(path) {
|
|
401
|
-
const cached = loadedPlugin.get(path);
|
|
402
|
-
if (cached) return cached;
|
|
403
|
-
const promise = import(path).then((module) => {
|
|
404
|
-
const value = module.default || module;
|
|
405
|
-
loadedPlugin.set(path, value);
|
|
406
|
-
return value;
|
|
407
|
-
});
|
|
408
|
-
loadedPlugin.set(path, promise);
|
|
409
|
-
return promise;
|
|
410
|
-
}
|
|
411
|
-
function createBabelOptions(rawOptions) {
|
|
412
|
-
var _babelOptions$parserO;
|
|
413
|
-
const babelOptions = {
|
|
414
|
-
babelrc: false,
|
|
415
|
-
configFile: false,
|
|
416
|
-
...rawOptions
|
|
417
|
-
};
|
|
418
|
-
babelOptions.plugins || (babelOptions.plugins = []);
|
|
419
|
-
babelOptions.presets || (babelOptions.presets = []);
|
|
420
|
-
babelOptions.overrides || (babelOptions.overrides = []);
|
|
421
|
-
babelOptions.parserOpts || (babelOptions.parserOpts = {});
|
|
422
|
-
(_babelOptions$parserO = babelOptions.parserOpts).plugins || (_babelOptions$parserO.plugins = []);
|
|
423
|
-
return babelOptions;
|
|
424
|
-
}
|
|
425
|
-
function defined(value) {
|
|
426
|
-
return value !== void 0;
|
|
427
|
-
}
|
|
428
|
-
function getReactCompilerPlugin(plugins) {
|
|
429
|
-
return plugins.find((p) => p === "babel-plugin-react-compiler" || Array.isArray(p) && p[0] === "babel-plugin-react-compiler");
|
|
430
|
-
}
|
|
431
|
-
function getReactCompilerRuntimeModule(plugin) {
|
|
432
|
-
let moduleName = "react/compiler-runtime";
|
|
433
|
-
if (Array.isArray(plugin)) {
|
|
434
|
-
var _plugin$, _plugin$2, _plugin$3;
|
|
435
|
-
if (((_plugin$ = plugin[1]) === null || _plugin$ === void 0 ? void 0 : _plugin$.target) === "17" || ((_plugin$2 = plugin[1]) === null || _plugin$2 === void 0 ? void 0 : _plugin$2.target) === "18") moduleName = "react-compiler-runtime";
|
|
436
|
-
else if (typeof ((_plugin$3 = plugin[1]) === null || _plugin$3 === void 0 ? void 0 : _plugin$3.runtimeModule) === "string") {
|
|
437
|
-
var _plugin$4;
|
|
438
|
-
moduleName = (_plugin$4 = plugin[1]) === null || _plugin$4 === void 0 ? void 0 : _plugin$4.runtimeModule;
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
return moduleName;
|
|
442
|
-
}
|
|
443
|
-
function ensureArray(value) {
|
|
444
|
-
return Array.isArray(value) ? value : [value];
|
|
445
|
-
}
|
|
446
203
|
|
|
447
204
|
//#endregion
|
|
448
|
-
export { rnw
|
|
205
|
+
export { rnw };
|
package/package.json
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.0.
|
|
2
|
+
"version": "0.0.8-1",
|
|
3
3
|
"name": "vite-plugin-rnw",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"main": "./dist/index.cjs",
|
|
6
|
-
"module": "./dist/index.js",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
5
|
"author": "Daniel Williams",
|
|
9
6
|
"description": "Vite plugin for React Native Web",
|
|
10
7
|
"keywords": [
|
|
@@ -19,10 +16,7 @@
|
|
|
19
16
|
"README.md"
|
|
20
17
|
],
|
|
21
18
|
"exports": {
|
|
22
|
-
".":
|
|
23
|
-
"import": "./dist/index.js",
|
|
24
|
-
"require": "./dist/index.cjs"
|
|
25
|
-
}
|
|
19
|
+
".": "./dist/index.js"
|
|
26
20
|
},
|
|
27
21
|
"repository": {
|
|
28
22
|
"type": "git",
|
|
@@ -43,12 +37,7 @@
|
|
|
43
37
|
},
|
|
44
38
|
"devDependencies": {
|
|
45
39
|
"@types/node": "^22",
|
|
46
|
-
"
|
|
47
|
-
"react": "^19.1.0",
|
|
48
|
-
"react-dom": "^19.1.0",
|
|
49
|
-
"rolldown": "1.0.0-beta.24",
|
|
50
|
-
"tsdown": "^0.12.9",
|
|
51
|
-
"vite": "^7.0.4"
|
|
40
|
+
"tsdown": "^0.15.12"
|
|
52
41
|
},
|
|
53
42
|
"peerDependencies": {
|
|
54
43
|
"react-native-web": "*",
|
|
@@ -56,15 +45,10 @@
|
|
|
56
45
|
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
|
|
57
46
|
},
|
|
58
47
|
"dependencies": {
|
|
59
|
-
"@babel/core": "^7.28.0",
|
|
60
|
-
"@babel/plugin-transform-flow-strip-types": "^7.27.1",
|
|
61
|
-
"@babel/plugin-transform-modules-commonjs": "^7.27.1",
|
|
62
|
-
"@babel/plugin-transform-react-jsx-self": "^7.27.1",
|
|
63
|
-
"@babel/plugin-transform-react-jsx-source": "^7.27.1",
|
|
64
48
|
"@bunchtogether/vite-plugin-flow": "^1.0.2",
|
|
65
|
-
"@rolldown/pluginutils": "1.0.0-beta.
|
|
66
|
-
"@
|
|
67
|
-
"
|
|
49
|
+
"@rolldown/pluginutils": "1.0.0-beta.46",
|
|
50
|
+
"@vitejs/plugin-react": "^5.1.0",
|
|
51
|
+
"magic-string": "^0.30.11",
|
|
68
52
|
"vite-plugin-commonjs": "^0.10.4"
|
|
69
53
|
}
|
|
70
54
|
}
|