vite-plugin-react-native 0.0.3 → 1.0.0
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 +128 -57
- package/dist/index.cjs +426 -89
- package/dist/index.d.cts +80 -2
- package/dist/index.d.ts +80 -2
- package/dist/index.js +410 -89
- package/package.json +6 -3
package/dist/index.cjs
CHANGED
|
@@ -1,29 +1,21 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var path2 = require('path');
|
|
4
4
|
var fs = require('fs');
|
|
5
5
|
var module$1 = require('module');
|
|
6
6
|
var url = require('url');
|
|
7
|
+
var vite = require('vite');
|
|
8
|
+
var flowRemoveTypes = require('flow-remove-types');
|
|
7
9
|
|
|
8
10
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
9
11
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
12
|
|
|
11
|
-
var
|
|
13
|
+
var path2__default = /*#__PURE__*/_interopDefault(path2);
|
|
12
14
|
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
15
|
+
var flowRemoveTypes__default = /*#__PURE__*/_interopDefault(flowRemoveTypes);
|
|
13
16
|
|
|
14
|
-
// index.ts
|
|
15
|
-
|
|
16
|
-
const out = [];
|
|
17
|
-
const seen = /* @__PURE__ */ new Set();
|
|
18
|
-
for (const v of values) {
|
|
19
|
-
if (!v) continue;
|
|
20
|
-
if (seen.has(v)) continue;
|
|
21
|
-
seen.add(v);
|
|
22
|
-
out.push(v);
|
|
23
|
-
}
|
|
24
|
-
return out;
|
|
25
|
-
}
|
|
26
|
-
var webResolveExtensions = [
|
|
17
|
+
// src/index.ts
|
|
18
|
+
var RESOLVE_EXTENSIONS = [
|
|
27
19
|
".web.mjs",
|
|
28
20
|
".web.js",
|
|
29
21
|
".web.ts",
|
|
@@ -36,81 +28,290 @@ var webResolveExtensions = [
|
|
|
36
28
|
".jsx",
|
|
37
29
|
".json"
|
|
38
30
|
];
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
31
|
+
var MODULE_TYPES = { ".js": "jsx", ".mjs": "jsx", ".cjs": "jsx", ".flow": "jsx" };
|
|
32
|
+
var TREESHAKE_SAFE_PRESET = {
|
|
33
|
+
annotations: true,
|
|
34
|
+
invalidImportSideEffects: true,
|
|
35
|
+
manualPureFunctions: [],
|
|
36
|
+
moduleSideEffects: true,
|
|
37
|
+
propertyReadSideEffects: "always",
|
|
38
|
+
unknownGlobalSideEffects: true,
|
|
39
|
+
propertyWriteSideEffects: "always"
|
|
40
|
+
};
|
|
41
|
+
var CORE_OPTIMIZE_DEPS_INCLUDE = [
|
|
42
|
+
"react",
|
|
43
|
+
"react-dom",
|
|
44
|
+
"react/jsx-runtime",
|
|
45
|
+
"react/jsx-dev-runtime",
|
|
46
|
+
"react-native-web"
|
|
47
|
+
];
|
|
48
|
+
var OPTIONAL_OPTIMIZE_DEPS_INCLUDE = [
|
|
49
|
+
"hoist-non-react-statics",
|
|
50
|
+
"invariant",
|
|
51
|
+
"react-native-reanimated",
|
|
52
|
+
"react-native-css-interop",
|
|
53
|
+
"react-native-i18njs",
|
|
54
|
+
"@react-native/normalize-colors",
|
|
55
|
+
"inline-style-prefixer",
|
|
56
|
+
"inline-style-prefixer/lib/plugins/crossFade",
|
|
57
|
+
"css-in-js-utils"
|
|
58
|
+
];
|
|
59
|
+
function uniqueStrings(values) {
|
|
60
|
+
const seen = /* @__PURE__ */ new Set();
|
|
61
|
+
const out = [];
|
|
62
|
+
for (const v of values) {
|
|
63
|
+
if (!v || seen.has(v)) continue;
|
|
64
|
+
seen.add(v);
|
|
65
|
+
out.push(v);
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
function getViteMajorVersion(projectRoot, require2) {
|
|
70
|
+
try {
|
|
71
|
+
const pkgPath = require2.resolve("vite/package.json", {
|
|
72
|
+
paths: [projectRoot]
|
|
73
|
+
});
|
|
74
|
+
const pkg = JSON.parse(fs__default.default.readFileSync(pkgPath, "utf-8"));
|
|
75
|
+
const v = String(pkg.version ?? "0");
|
|
76
|
+
const major = Number(v.split(".")[0]);
|
|
77
|
+
return Number.isFinite(major) ? major : 0;
|
|
78
|
+
} catch {
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function getInstalledOptimizeDepsInclude(projectRoot, routerDomEntry) {
|
|
83
|
+
const pkgPath = path2__default.default.join(projectRoot, "package.json");
|
|
84
|
+
let deps = {};
|
|
85
|
+
try {
|
|
86
|
+
const pkg = JSON.parse(fs__default.default.readFileSync(pkgPath, "utf-8"));
|
|
87
|
+
deps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
|
|
88
|
+
} catch {
|
|
89
|
+
return [...CORE_OPTIMIZE_DEPS_INCLUDE];
|
|
90
|
+
}
|
|
91
|
+
const installed = OPTIONAL_OPTIMIZE_DEPS_INCLUDE.filter((entry) => {
|
|
92
|
+
const pkgName = entry.split("/")[0];
|
|
93
|
+
return pkgName in deps;
|
|
94
|
+
});
|
|
95
|
+
const list = [...CORE_OPTIMIZE_DEPS_INCLUDE, ...installed];
|
|
96
|
+
if (routerDomEntry && "react-native-router-dom" in deps) {
|
|
97
|
+
list.push("react-native-router-dom");
|
|
98
|
+
}
|
|
99
|
+
return list;
|
|
100
|
+
}
|
|
101
|
+
var DOCTOR_PATTERN = /return\s*<react-native-css-interop-jsx-pragma-check\s*\/>\s*===\s*true\s*;/g;
|
|
102
|
+
function flowRemoveTypesPlugin() {
|
|
46
103
|
return {
|
|
47
|
-
name: "
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
dedupe: ["react", "react-dom"],
|
|
71
|
-
extensions: userResolveExtensions ? void 0 : webResolveExtensions
|
|
72
|
-
},
|
|
73
|
-
build: {
|
|
74
|
-
commonjsOptions: {
|
|
75
|
-
esmExternals: true,
|
|
76
|
-
requireReturnsDefault: "auto",
|
|
77
|
-
transformMixedEsModules: true
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
define: {
|
|
81
|
-
__DEV__: JSON.stringify(!isProd),
|
|
82
|
-
"process.env.NODE_ENV": JSON.stringify(mode),
|
|
83
|
-
global: "globalThis"
|
|
84
|
-
},
|
|
85
|
-
optimizeDeps: {
|
|
86
|
-
include: uniqueStrings([
|
|
87
|
-
...userOptimizeDepsInclude,
|
|
88
|
-
"react",
|
|
89
|
-
"react-dom",
|
|
90
|
-
"react/jsx-runtime",
|
|
91
|
-
"react/jsx-dev-runtime",
|
|
92
|
-
"hoist-non-react-statics",
|
|
93
|
-
"invariant"
|
|
94
|
-
]),
|
|
95
|
-
exclude: uniqueStrings([
|
|
96
|
-
...userOptimizeDepsExclude,
|
|
97
|
-
"react-native",
|
|
98
|
-
"react-native-gesture-handler",
|
|
99
|
-
"react-native-safe-area-context",
|
|
100
|
-
"react-native-screens"
|
|
101
|
-
])
|
|
104
|
+
name: "flow-remove-types",
|
|
105
|
+
transform: {
|
|
106
|
+
filter: { code: /@flow/ },
|
|
107
|
+
handler(code) {
|
|
108
|
+
return { code: flowRemoveTypes__default.default(code).toString() };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function stripFlowTypes(code) {
|
|
114
|
+
try {
|
|
115
|
+
return flowRemoveTypes__default.default(code).toString();
|
|
116
|
+
} catch {
|
|
117
|
+
return code;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function treeshakeFixPlugin() {
|
|
121
|
+
return {
|
|
122
|
+
name: "treeshake-fix",
|
|
123
|
+
transform: {
|
|
124
|
+
handler(_code, id) {
|
|
125
|
+
if (id.includes("react-native-css-interop") || id.includes("react-native-css") || id.includes("expo-modules-core")) {
|
|
126
|
+
return { moduleSideEffects: "no-treeshake" };
|
|
102
127
|
}
|
|
103
|
-
|
|
104
|
-
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function transformCssInteropDoctorCheck(code, id) {
|
|
134
|
+
if (!id.includes("node_modules/react-native-css-interop") || !id.includes("dist/doctor.js")) {
|
|
135
|
+
return { code, map: null, changed: false };
|
|
136
|
+
}
|
|
137
|
+
const re = new RegExp(DOCTOR_PATTERN.source, "g");
|
|
138
|
+
if (!re.test(code)) return { code, map: null, changed: false };
|
|
139
|
+
re.lastIndex = 0;
|
|
140
|
+
return { code: code.replace(re, "return true;"), map: null, changed: true };
|
|
141
|
+
}
|
|
142
|
+
function analyzeReanimatedRequires(code, exportedVars) {
|
|
143
|
+
const importMap = /* @__PURE__ */ new Map();
|
|
144
|
+
for (const varName of exportedVars) {
|
|
145
|
+
const re = new RegExp(
|
|
146
|
+
`${varName}\\s*=\\s*[\\s\\S]*?require\\(['"]([^'"]+)['"]\\)(?:\\.([\\w]+))?`,
|
|
147
|
+
"g"
|
|
148
|
+
);
|
|
149
|
+
const m = re.exec(code);
|
|
150
|
+
if (m) {
|
|
151
|
+
const [, modulePath, prop] = m;
|
|
152
|
+
const key = `${modulePath}:${prop || "default"}`;
|
|
153
|
+
if (!importMap.has(key)) importMap.set(key, []);
|
|
154
|
+
importMap.get(key).push(varName);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return importMap;
|
|
158
|
+
}
|
|
159
|
+
function generateReanimatedExports(importMap) {
|
|
160
|
+
let out = "";
|
|
161
|
+
for (const [key, vars] of importMap) {
|
|
162
|
+
const [modulePath, prop] = key.split(":");
|
|
163
|
+
for (const v of vars) {
|
|
164
|
+
out += prop === "default" ? `export { default as ${v} } from '${modulePath}';
|
|
165
|
+
` : `export { ${prop} as ${v} } from '${modulePath}';
|
|
166
|
+
`;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return out;
|
|
170
|
+
}
|
|
171
|
+
var REANIMATED_TRY_CATCH_RE = /try\s*\{[^{}]*?require\([^)]+\)[^{}]*?\}\s*catch[^{}]*?\{[^{}]*?\}/gs;
|
|
172
|
+
function transformReanimatedWebUtils(code, id, isProduction) {
|
|
173
|
+
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")) {
|
|
174
|
+
return { code, map: null, changed: false };
|
|
175
|
+
}
|
|
176
|
+
const exportLetMatches = [...code.matchAll(/export let (\w+);/g)];
|
|
177
|
+
const exportedVars = exportLetMatches.map((m) => m[1]);
|
|
178
|
+
if (!exportedVars.length) return { code, map: null, changed: false };
|
|
179
|
+
const importMap = analyzeReanimatedRequires(code, exportedVars);
|
|
180
|
+
let result = code.replace(REANIMATED_TRY_CATCH_RE, "\n").replace(/export let \w+;/g, "");
|
|
181
|
+
const exports$1 = generateReanimatedExports(importMap);
|
|
182
|
+
if (!exports$1) return { code, map: null, changed: false };
|
|
183
|
+
result = result.trimEnd() + "\n\n" + exports$1;
|
|
184
|
+
return { code: result, map: null, changed: true };
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// src/config.ts
|
|
188
|
+
function normalizeUserAlias(alias) {
|
|
189
|
+
if (Array.isArray(alias)) return alias;
|
|
190
|
+
if (alias && typeof alias === "object") {
|
|
191
|
+
return Object.entries(alias).map(([find, replacement]) => ({ find, replacement: String(replacement) }));
|
|
192
|
+
}
|
|
193
|
+
return [];
|
|
194
|
+
}
|
|
195
|
+
function buildResolveAlias(options) {
|
|
196
|
+
const { userAliasArray, routerDomEntry } = options;
|
|
197
|
+
const alias = [...userAliasArray];
|
|
198
|
+
if (routerDomEntry) {
|
|
199
|
+
alias.push({ find: /^react-native-router-dom$/, replacement: routerDomEntry });
|
|
200
|
+
}
|
|
201
|
+
alias.push(
|
|
202
|
+
{ find: /^react-native\/(?!Libraries\/Core\/Devtools\/openURLInBrowser$)(.*)$/, replacement: "react-native-web/$1" },
|
|
203
|
+
{ find: "inline-style-prefixer/lib/createPrefixer", replacement: "inline-style-prefixer/es/createPrefixer" },
|
|
204
|
+
{ find: /^inline-style-prefixer\/lib\/plugins\/(.*)$/, replacement: "inline-style-prefixer/es/plugins/$1" },
|
|
205
|
+
{ find: /^css-in-js-utils\/lib\/(.*)$/, replacement: "css-in-js-utils/es/$1" },
|
|
206
|
+
{ find: "react-native/Libraries/EventEmitter/RCTDeviceEventEmitter", replacement: "react-native-web/dist/vendor/react-native/NativeEventEmitter/RCTDeviceEventEmitter" },
|
|
207
|
+
{ find: "react-native/Libraries/vendor/emitter/EventEmitter", replacement: "react-native-web/dist/vendor/react-native/emitter/EventEmitter" },
|
|
208
|
+
{ find: "react-native/Libraries/EventEmitter/NativeEventEmitter", replacement: "react-native-web/dist/vendor/react-native/NativeEventEmitter" }
|
|
209
|
+
);
|
|
210
|
+
return alias;
|
|
211
|
+
}
|
|
212
|
+
function buildViteConfig(ctx) {
|
|
213
|
+
const { mode, userConfig, resolveExtensions, useRolldown, installedInclude, routerDomEntry } = ctx;
|
|
214
|
+
const isProd = mode === "production";
|
|
215
|
+
const userAliasArray = normalizeUserAlias(userConfig.resolve?.alias ?? []);
|
|
216
|
+
const alias = buildResolveAlias({ userAliasArray, routerDomEntry });
|
|
217
|
+
const od = userConfig.optimizeDeps;
|
|
218
|
+
const userOptimizeDepsExclude = Array.isArray(od?.exclude) ? od.exclude : [];
|
|
219
|
+
const userOptimizeDepsInclude = Array.isArray(od?.include) ? od.include : [];
|
|
220
|
+
const userEsbuildOptions = od?.esbuildOptions && typeof od.esbuildOptions === "object" ? od.esbuildOptions : {};
|
|
221
|
+
const userRolldownOptions = od?.rolldownOptions && typeof od.rolldownOptions === "object" ? od.rolldownOptions : void 0;
|
|
222
|
+
const rolldownPlugins = [flowRemoveTypesPlugin(), treeshakeFixPlugin()];
|
|
223
|
+
return {
|
|
224
|
+
resolve: {
|
|
225
|
+
alias,
|
|
226
|
+
dedupe: ["react", "react-dom"],
|
|
227
|
+
extensions: Array.isArray(userConfig.resolve?.extensions) ? void 0 : [...resolveExtensions]
|
|
105
228
|
},
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
229
|
+
build: useRolldown ? {
|
|
230
|
+
rolldownOptions: {
|
|
231
|
+
resolve: { extensions: [...resolveExtensions] },
|
|
232
|
+
shimMissingExports: true,
|
|
233
|
+
treeshake: TREESHAKE_SAFE_PRESET,
|
|
234
|
+
moduleTypes: MODULE_TYPES,
|
|
235
|
+
plugins: rolldownPlugins
|
|
236
|
+
}
|
|
237
|
+
} : {
|
|
238
|
+
commonjsOptions: {
|
|
239
|
+
esmExternals: true,
|
|
240
|
+
requireReturnsDefault: "auto",
|
|
241
|
+
transformMixedEsModules: true
|
|
242
|
+
}
|
|
110
243
|
},
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
244
|
+
define: {
|
|
245
|
+
__DEV__: JSON.stringify(!isProd),
|
|
246
|
+
"process.env.NODE_ENV": JSON.stringify(mode),
|
|
247
|
+
"process.env.EXPO_OS": JSON.stringify("web"),
|
|
248
|
+
global: "globalThis",
|
|
249
|
+
_WORKLET: false,
|
|
250
|
+
EXPO_OS: JSON.stringify("web")
|
|
251
|
+
},
|
|
252
|
+
optimizeDeps: {
|
|
253
|
+
...useRolldown ? {
|
|
254
|
+
rolldownOptions: {
|
|
255
|
+
...userRolldownOptions,
|
|
256
|
+
resolve: {
|
|
257
|
+
...userRolldownOptions?.resolve,
|
|
258
|
+
extensions: [...resolveExtensions]
|
|
259
|
+
},
|
|
260
|
+
shimMissingExports: true,
|
|
261
|
+
treeshake: TREESHAKE_SAFE_PRESET,
|
|
262
|
+
moduleTypes: MODULE_TYPES,
|
|
263
|
+
plugins: [
|
|
264
|
+
...rolldownPlugins,
|
|
265
|
+
...userRolldownOptions?.plugins ?? []
|
|
266
|
+
]
|
|
267
|
+
}
|
|
268
|
+
} : {
|
|
269
|
+
esbuildOptions: {
|
|
270
|
+
...userEsbuildOptions,
|
|
271
|
+
resolveExtensions: "resolveExtensions" in userEsbuildOptions ? userEsbuildOptions.resolveExtensions : resolveExtensions,
|
|
272
|
+
loader: {
|
|
273
|
+
..."loader" in userEsbuildOptions ? userEsbuildOptions.loader : {},
|
|
274
|
+
".js": "jsx"
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
include: uniqueStrings([...userOptimizeDepsInclude, ...installedInclude]),
|
|
279
|
+
exclude: uniqueStrings([
|
|
280
|
+
...userOptimizeDepsExclude,
|
|
281
|
+
"react-native",
|
|
282
|
+
"react-native-gesture-handler",
|
|
283
|
+
"react-native-safe-area-context",
|
|
284
|
+
"react-native-screens",
|
|
285
|
+
"@react-native/new-app-screen"
|
|
286
|
+
])
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// src/virtuals.ts
|
|
292
|
+
var VIRTUAL_RN_WEB = "virtual:rn-web";
|
|
293
|
+
var VIRTUAL_OPEN_URL_IN_BROWSER = "virtual:rn-openURLInBrowser";
|
|
294
|
+
var VIRTUAL_SAFE_AREA = "virtual:rn-safe-area-context";
|
|
295
|
+
var VIRTUAL_SCREENS = "virtual:rn-screens";
|
|
296
|
+
var VIRTUAL_GESTURE_HANDLER = "virtual:rn-gesture-handler";
|
|
297
|
+
var RESOLVED_RN_WEB = "\0" + VIRTUAL_RN_WEB;
|
|
298
|
+
var RESOLVED_OPEN_URL_IN_BROWSER = "\0" + VIRTUAL_OPEN_URL_IN_BROWSER;
|
|
299
|
+
var RESOLVED_SAFE_AREA = "\0" + VIRTUAL_SAFE_AREA;
|
|
300
|
+
var RESOLVED_SCREENS = "\0" + VIRTUAL_SCREENS;
|
|
301
|
+
var RESOLVED_GESTURE_HANDLER = "\0" + VIRTUAL_GESTURE_HANDLER;
|
|
302
|
+
var RN_LIBRARIES_OPEN_URL = "react-native/Libraries/Core/Devtools/openURLInBrowser";
|
|
303
|
+
function getVirtualModuleContent(id) {
|
|
304
|
+
if (id === RESOLVED_RN_WEB) {
|
|
305
|
+
return [
|
|
306
|
+
"export * from 'react-native-web';",
|
|
307
|
+
"export const ReactNativeVersion = { major: 0, minor: 84, patch: 1, prerelease: null, getVersionString() { return this.major + '.' + this.minor + '.' + this.patch + (this.prerelease ? '-' + this.prerelease : ''); } };"
|
|
308
|
+
].join("\n");
|
|
309
|
+
}
|
|
310
|
+
if (id === RESOLVED_OPEN_URL_IN_BROWSER) {
|
|
311
|
+
return "export default function openURLInBrowser(url) { if (typeof window !== 'undefined' && url) window.open(url, '_blank'); }\n";
|
|
312
|
+
}
|
|
313
|
+
if (id === RESOLVED_SAFE_AREA) {
|
|
314
|
+
return `
|
|
114
315
|
import * as React from 'react';
|
|
115
316
|
import { View } from 'react-native';
|
|
116
317
|
export const SafeAreaInsetsContext = React.createContext(null);
|
|
@@ -147,9 +348,9 @@ export function SafeAreaView(props) {
|
|
|
147
348
|
return React.createElement(View, props);
|
|
148
349
|
}
|
|
149
350
|
`;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
351
|
+
}
|
|
352
|
+
if (id === RESOLVED_SCREENS) {
|
|
353
|
+
return `
|
|
153
354
|
import * as React from 'react';
|
|
154
355
|
import { View } from 'react-native';
|
|
155
356
|
export function enableScreens() {}
|
|
@@ -172,10 +373,146 @@ export function ScreenContainer(props) {
|
|
|
172
373
|
return React.createElement(View, { ...rest, style: withFlex1Style(style) });
|
|
173
374
|
}
|
|
174
375
|
`;
|
|
376
|
+
}
|
|
377
|
+
if (id === RESOLVED_GESTURE_HANDLER) {
|
|
378
|
+
return `
|
|
379
|
+
import * as React from 'react';
|
|
380
|
+
import { View } from 'react-native';
|
|
381
|
+
|
|
382
|
+
export function GestureHandlerRootView(props) {
|
|
383
|
+
return React.createElement(View, props);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
export const Gesture = {
|
|
387
|
+
Tap: () => null,
|
|
388
|
+
Pan: () => null,
|
|
389
|
+
Pinch: () => null,
|
|
390
|
+
LongPress: () => null,
|
|
391
|
+
Fling: () => null,
|
|
392
|
+
Native: () => null,
|
|
393
|
+
Manual: () => null,
|
|
394
|
+
Race: () => null,
|
|
395
|
+
Simultaneous: () => null,
|
|
396
|
+
Exclusive: () => null,
|
|
397
|
+
};
|
|
398
|
+
export function GestureDetector(props) {
|
|
399
|
+
return React.createElement(View, props);
|
|
400
|
+
}
|
|
401
|
+
export default { GestureHandlerRootView, Gesture, GestureDetector };
|
|
402
|
+
`;
|
|
403
|
+
}
|
|
404
|
+
return null;
|
|
405
|
+
}
|
|
406
|
+
function resolveVirtualId(source) {
|
|
407
|
+
if (source === "react-native") return RESOLVED_RN_WEB;
|
|
408
|
+
if (source === RN_LIBRARIES_OPEN_URL) return RESOLVED_OPEN_URL_IN_BROWSER;
|
|
409
|
+
if (source === "react-native-safe-area-context") return RESOLVED_SAFE_AREA;
|
|
410
|
+
if (source === "react-native-screens") return RESOLVED_SCREENS;
|
|
411
|
+
if (source === "react-native-gesture-handler") return RESOLVED_GESTURE_HANDLER;
|
|
412
|
+
return null;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// src/index.ts
|
|
416
|
+
function replaceRequireAssetsWithImports(code) {
|
|
417
|
+
const re = /require\s*\(\s*['"](\.\/assets\/[^'"]+)['"]\s*\)/g;
|
|
418
|
+
const matches = [...code.matchAll(re)];
|
|
419
|
+
if (!matches.length) return code;
|
|
420
|
+
const seen = /* @__PURE__ */ new Map();
|
|
421
|
+
const imports = [];
|
|
422
|
+
let i = 0;
|
|
423
|
+
for (const m of matches) {
|
|
424
|
+
const p = m[1];
|
|
425
|
+
if (seen.has(p)) continue;
|
|
426
|
+
const name = `__rn_asset_${i++}`;
|
|
427
|
+
seen.set(p, name);
|
|
428
|
+
imports.push(`import ${name} from '${p}';`);
|
|
429
|
+
}
|
|
430
|
+
let out = code.replace(re, (_, p) => seen.get(p) ?? _);
|
|
431
|
+
const at = Math.max(0, out.search(/\n?import\s+/));
|
|
432
|
+
return out.slice(0, at) + imports.join("\n") + "\n" + out.slice(at);
|
|
433
|
+
}
|
|
434
|
+
function reactNative() {
|
|
435
|
+
const pluginDir = path2__default.default.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))));
|
|
436
|
+
const require2 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
|
|
437
|
+
let buildMode = "development";
|
|
438
|
+
return {
|
|
439
|
+
name: "react-native",
|
|
440
|
+
enforce: "pre",
|
|
441
|
+
config(userConfig, env) {
|
|
442
|
+
buildMode = env.mode ?? "development";
|
|
443
|
+
const projectRoot = userConfig.root ? path2__default.default.resolve(userConfig.root) : process.cwd();
|
|
444
|
+
let routerDomEntry = null;
|
|
445
|
+
try {
|
|
446
|
+
const routerDomPkg = require2.resolve("react-native-router-dom/package.json", { paths: [projectRoot, pluginDir] });
|
|
447
|
+
const routerDomDir = path2__default.default.dirname(routerDomPkg);
|
|
448
|
+
routerDomEntry = fs__default.default.existsSync(path2__default.default.join(routerDomDir, "src/index.ts")) ? path2__default.default.join(routerDomDir, "src/index.ts") : path2__default.default.join(routerDomDir, "dist/index.mjs");
|
|
449
|
+
} catch {
|
|
450
|
+
}
|
|
451
|
+
const useRolldown = getViteMajorVersion(projectRoot, require2) >= 8;
|
|
452
|
+
const resolveExtensions = userConfig.resolve?.extensions ?? [...RESOLVE_EXTENSIONS];
|
|
453
|
+
const installedInclude = getInstalledOptimizeDepsInclude(projectRoot, routerDomEntry);
|
|
454
|
+
const partial = buildViteConfig({
|
|
455
|
+
mode: buildMode,
|
|
456
|
+
userConfig,
|
|
457
|
+
resolveExtensions,
|
|
458
|
+
useRolldown,
|
|
459
|
+
installedInclude,
|
|
460
|
+
routerDomEntry
|
|
461
|
+
});
|
|
462
|
+
return partial;
|
|
463
|
+
},
|
|
464
|
+
resolveId(source) {
|
|
465
|
+
const resolved = resolveVirtualId(source);
|
|
466
|
+
return resolved ?? null;
|
|
467
|
+
},
|
|
468
|
+
load(id) {
|
|
469
|
+
const content = getVirtualModuleContent(id);
|
|
470
|
+
return content ?? null;
|
|
471
|
+
},
|
|
472
|
+
async transform(code, id) {
|
|
473
|
+
const idPath = id.split("?")[0];
|
|
474
|
+
const isNodeModulesJs = id.includes("node_modules") && /\.(js|jsx|mjs|cjs)$/.test(idPath);
|
|
475
|
+
const hasFlow = /@flow/.test(code);
|
|
476
|
+
const isReactNativePkg = /node_modules[/\\]@react-native[/\\]/.test(id) || /node_modules[/\\]react-native[/\\]/.test(id);
|
|
477
|
+
let resultCode = code;
|
|
478
|
+
if (isNodeModulesJs && (hasFlow || isReactNativePkg)) {
|
|
479
|
+
resultCode = stripFlowTypes(resultCode);
|
|
480
|
+
}
|
|
481
|
+
if (id.includes("node_modules/@react-native") && /require\s*\(\s*['"]\.\/assets\//.test(resultCode)) {
|
|
482
|
+
resultCode = replaceRequireAssetsWithImports(resultCode);
|
|
483
|
+
}
|
|
484
|
+
const cssInterop = transformCssInteropDoctorCheck(resultCode, id);
|
|
485
|
+
if (cssInterop.changed) resultCode = cssInterop.code;
|
|
486
|
+
const reanimated = transformReanimatedWebUtils(resultCode, id, buildMode === "production");
|
|
487
|
+
if (reanimated.changed) resultCode = reanimated.code;
|
|
488
|
+
if (id.includes("node_modules/@react-native") && /\.js$/.test(idPath) && /<[A-Za-z]/.test(resultCode)) {
|
|
489
|
+
const result = await vite.transformWithEsbuild(resultCode, idPath, {
|
|
490
|
+
loader: "jsx",
|
|
491
|
+
jsx: "automatic"
|
|
492
|
+
});
|
|
493
|
+
return { code: result.code, map: result.map ?? null };
|
|
494
|
+
}
|
|
495
|
+
if (resultCode !== code || cssInterop.changed || reanimated.changed) {
|
|
496
|
+
return { code: resultCode, map: null };
|
|
175
497
|
}
|
|
176
498
|
return null;
|
|
177
499
|
}
|
|
178
500
|
};
|
|
179
501
|
}
|
|
180
502
|
|
|
503
|
+
exports.CORE_OPTIMIZE_DEPS_INCLUDE = CORE_OPTIMIZE_DEPS_INCLUDE;
|
|
504
|
+
exports.MODULE_TYPES = MODULE_TYPES;
|
|
505
|
+
exports.OPTIONAL_OPTIMIZE_DEPS_INCLUDE = OPTIONAL_OPTIMIZE_DEPS_INCLUDE;
|
|
506
|
+
exports.RESOLVE_EXTENSIONS = RESOLVE_EXTENSIONS;
|
|
507
|
+
exports.TREESHAKE_SAFE_PRESET = TREESHAKE_SAFE_PRESET;
|
|
508
|
+
exports.buildResolveAlias = buildResolveAlias;
|
|
509
|
+
exports.flowRemoveTypesPlugin = flowRemoveTypesPlugin;
|
|
510
|
+
exports.getInstalledOptimizeDepsInclude = getInstalledOptimizeDepsInclude;
|
|
511
|
+
exports.getViteMajorVersion = getViteMajorVersion;
|
|
512
|
+
exports.normalizeUserAlias = normalizeUserAlias;
|
|
181
513
|
exports.reactNative = reactNative;
|
|
514
|
+
exports.stripFlowTypes = stripFlowTypes;
|
|
515
|
+
exports.transformCssInteropDoctorCheck = transformCssInteropDoctorCheck;
|
|
516
|
+
exports.transformReanimatedWebUtils = transformReanimatedWebUtils;
|
|
517
|
+
exports.treeshakeFixPlugin = treeshakeFixPlugin;
|
|
518
|
+
exports.uniqueStrings = uniqueStrings;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,83 @@
|
|
|
1
|
-
import { Plugin } from 'vite';
|
|
1
|
+
import { AliasOptions, Plugin } from 'vite';
|
|
2
|
+
|
|
3
|
+
declare function flowRemoveTypesPlugin(): {
|
|
4
|
+
name: string;
|
|
5
|
+
transform: {
|
|
6
|
+
filter: {
|
|
7
|
+
code: RegExp;
|
|
8
|
+
};
|
|
9
|
+
handler: (code: string) => {
|
|
10
|
+
code: string;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
declare function stripFlowTypes(code: string): string;
|
|
15
|
+
declare function treeshakeFixPlugin(): {
|
|
16
|
+
name: string;
|
|
17
|
+
transform: {
|
|
18
|
+
handler: (_code: string, id: string) => {
|
|
19
|
+
moduleSideEffects: string;
|
|
20
|
+
} | null;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
declare function transformCssInteropDoctorCheck(code: string, id: string): {
|
|
24
|
+
code: string;
|
|
25
|
+
map: null;
|
|
26
|
+
changed: boolean;
|
|
27
|
+
};
|
|
28
|
+
declare function transformReanimatedWebUtils(code: string, id: string, isProduction: boolean): {
|
|
29
|
+
code: string;
|
|
30
|
+
map: null;
|
|
31
|
+
changed: boolean;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/** Vite 配置:别名、define、build、optimizeDeps */
|
|
35
|
+
|
|
36
|
+
type AliasEntry = {
|
|
37
|
+
find: string | RegExp;
|
|
38
|
+
replacement: string;
|
|
39
|
+
};
|
|
40
|
+
declare function normalizeUserAlias(alias: AliasOptions): AliasEntry[];
|
|
41
|
+
declare function buildResolveAlias(options: {
|
|
42
|
+
userAliasArray: AliasEntry[];
|
|
43
|
+
routerDomEntry: string | null;
|
|
44
|
+
}): AliasEntry[];
|
|
45
|
+
|
|
46
|
+
/** 常量与工具:扩展名、optimizeDeps 列表、去重、Vite 版本、动态 include */
|
|
47
|
+
declare const RESOLVE_EXTENSIONS: readonly [".web.mjs", ".web.js", ".web.ts", ".web.tsx", ".web.jsx", ".mjs", ".js", ".ts", ".tsx", ".jsx", ".json"];
|
|
48
|
+
declare const MODULE_TYPES: {
|
|
49
|
+
readonly '.js': "jsx";
|
|
50
|
+
readonly '.mjs': "jsx";
|
|
51
|
+
readonly '.cjs': "jsx";
|
|
52
|
+
readonly '.flow': "jsx";
|
|
53
|
+
};
|
|
54
|
+
declare const TREESHAKE_SAFE_PRESET: {
|
|
55
|
+
annotations: boolean;
|
|
56
|
+
invalidImportSideEffects: boolean;
|
|
57
|
+
manualPureFunctions: string[];
|
|
58
|
+
moduleSideEffects: boolean;
|
|
59
|
+
propertyReadSideEffects: "always";
|
|
60
|
+
unknownGlobalSideEffects: boolean;
|
|
61
|
+
propertyWriteSideEffects: "always";
|
|
62
|
+
};
|
|
63
|
+
declare const CORE_OPTIMIZE_DEPS_INCLUDE: readonly ["react", "react-dom", "react/jsx-runtime", "react/jsx-dev-runtime", "react-native-web"];
|
|
64
|
+
declare const OPTIONAL_OPTIMIZE_DEPS_INCLUDE: readonly ["hoist-non-react-statics", "invariant", "react-native-reanimated", "react-native-css-interop", "react-native-i18njs", "@react-native/normalize-colors", "inline-style-prefixer", "inline-style-prefixer/lib/plugins/crossFade", "css-in-js-utils"];
|
|
65
|
+
type RequireLike = {
|
|
66
|
+
resolve: (id: string, options?: {
|
|
67
|
+
paths?: string[];
|
|
68
|
+
}) => string;
|
|
69
|
+
};
|
|
70
|
+
declare function uniqueStrings(values: Array<string | undefined>): string[];
|
|
71
|
+
/** 从项目解析的 Vite 主版本号,用于判断是否使用 rolldownOptions(Vite 8+) */
|
|
72
|
+
declare function getViteMajorVersion(projectRoot: string, require: RequireLike): number;
|
|
73
|
+
/**
|
|
74
|
+
* 仅包含项目已安装的依赖,避免 optimizeDeps.include 里未安装的包导致解析失败。
|
|
75
|
+
* 核心列表 + 可选列表中在 package.json 里出现的项。
|
|
76
|
+
*/
|
|
77
|
+
declare function getInstalledOptimizeDepsInclude(projectRoot: string, routerDomEntry: string | null): string[];
|
|
78
|
+
|
|
79
|
+
/** Vite 插件:React Native Web 兼容(别名、虚拟模块、Flow、optimizeDeps) */
|
|
2
80
|
|
|
3
81
|
declare function reactNative(): Plugin;
|
|
4
82
|
|
|
5
|
-
export { reactNative };
|
|
83
|
+
export { CORE_OPTIMIZE_DEPS_INCLUDE, MODULE_TYPES, OPTIONAL_OPTIMIZE_DEPS_INCLUDE, RESOLVE_EXTENSIONS, TREESHAKE_SAFE_PRESET, buildResolveAlias, flowRemoveTypesPlugin, getInstalledOptimizeDepsInclude, getViteMajorVersion, normalizeUserAlias, reactNative, stripFlowTypes, transformCssInteropDoctorCheck, transformReanimatedWebUtils, treeshakeFixPlugin, uniqueStrings };
|