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/dist/index.cjs CHANGED
@@ -1,29 +1,21 @@
1
1
  'use strict';
2
2
 
3
- var path = require('path');
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 path__default = /*#__PURE__*/_interopDefault(path);
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
- function uniqueStrings(values) {
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
- function reactNative() {
40
- const safeAreaId = "virtual:rn-safe-area-context";
41
- const resolvedSafeAreaId = "\0" + safeAreaId;
42
- const screensId = "virtual:rn-screens";
43
- const resolvedScreensId = "\0" + screensId;
44
- const pluginDir = path__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))));
45
- 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)));
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: "react-native",
48
- enforce: "pre",
49
- config(userConfig, env) {
50
- const mode = env.mode;
51
- const isProd = mode === "production";
52
- const projectRoot = userConfig.root ? path__default.default.resolve(userConfig.root) : process.cwd();
53
- const routerDomPackageJson = require2.resolve("react-native-router-dom/package.json", { paths: [projectRoot, pluginDir] });
54
- const routerDomDir = path__default.default.dirname(routerDomPackageJson);
55
- const routerDomSourceEntry = path__default.default.join(routerDomDir, "src/index.ts");
56
- const routerDomDistEntry = path__default.default.join(routerDomDir, "dist/index.mjs");
57
- const routerDomEntry = fs__default.default.existsSync(routerDomSourceEntry) ? routerDomSourceEntry : routerDomDistEntry;
58
- const userAlias = userConfig.resolve?.alias;
59
- const userAliasArray = Array.isArray(userAlias) ? userAlias : userAlias && typeof userAlias === "object" ? Object.entries(userAlias).map(([find, replacement]) => ({ find, replacement })) : [];
60
- const userResolveExtensions = Array.isArray(userConfig.resolve?.extensions) ? userConfig.resolve?.extensions : null;
61
- const userOptimizeDepsExclude = Array.isArray(userConfig.optimizeDeps?.exclude) ? userConfig.optimizeDeps?.exclude : [];
62
- const userOptimizeDepsInclude = Array.isArray(userConfig.optimizeDeps?.include) ? userConfig.optimizeDeps?.include : [];
63
- const config = {
64
- resolve: {
65
- alias: [
66
- ...userAliasArray,
67
- { find: /^react-native$/, replacement: "react-native-web" },
68
- { find: /^react-native-router-dom$/, replacement: routerDomEntry }
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
- return config;
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
- resolveId(source) {
107
- if (source === "react-native-safe-area-context") return resolvedSafeAreaId;
108
- if (source === "react-native-screens") return resolvedScreensId;
109
- return null;
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
- load(id) {
112
- if (id === resolvedSafeAreaId) {
113
- return `
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
- if (id === resolvedScreensId) {
152
- return `
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 };