UNPKG

one

Version:

One is a new React Framework that makes Vite serve both native and web.

382 lines (381 loc) 17.7 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf, __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: !0 }); }, __copyProps = (to, from, except, desc) => { if (from && typeof from == "object" || typeof from == "function") for (let key of __getOwnPropNames(from)) !__hasOwnProp.call(to, key) && key !== except && __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: !0 }) : target, mod )), __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: !0 }), mod); var one_exports = {}; __export(one_exports, { one: () => one }); module.exports = __toCommonJS(one_exports); var import_compiler = require("@vxrn/compiler"), import_resolve = require("@vxrn/resolve"), import_vite_plugin_metro = require("@vxrn/vite-plugin-metro"), import_node_events = __toESM(require("node:events"), 1), import_node_path = __toESM(require("node:path"), 1), import_vite_tsconfig_paths = __toESM(require("vite-tsconfig-paths"), 1), import_vxrn = require("vxrn"), import_vite_plugin = __toESM(require("vxrn/vite-plugin"), 1), import_constants = require("../constants"), import_getViteMetroPluginOptions = require("../metro-config/getViteMetroPluginOptions"), import_polyfills_server = require("../polyfills-server"), import_getRouterRootFromOneOptions = require("../utils/getRouterRootFromOneOptions"), import_ensureTsConfig = require("./ensureTsConfig"), import_loadConfig = require("./loadConfig"), import_clientTreeShakePlugin = require("./plugins/clientTreeShakePlugin"), import_devtoolsPlugin = require("./plugins/devtoolsPlugin"), import_fileSystemRouterPlugin = require("./plugins/fileSystemRouterPlugin"), import_fixDependenciesPlugin = require("./plugins/fixDependenciesPlugin"), import_generateFileSystemRouteTypesPlugin = require("./plugins/generateFileSystemRouteTypesPlugin"), import_imageDataPlugin = require("./plugins/imageDataPlugin"), import_sourceInspectorPlugin = require("./plugins/sourceInspectorPlugin"), import_SSRCSSPlugin = require("./plugins/SSRCSSPlugin"), import_virtualEntryConstants = require("./plugins/virtualEntryConstants"), import_virtualEntryPlugin = require("./plugins/virtualEntryPlugin"), import_environmentGuardPlugin = require("./plugins/environmentGuardPlugin"); import_node_events.default.setMaxListeners(1e3); globalThis.__vxrnEnableNativeEnv = !0; function one(options = {}) { const routerRoot = (0, import_getRouterRootFromOneOptions.getRouterRootFromOneOptions)(options), metroOptions = (() => { if (options.native?.bundler !== "metro" && !process.env.ONE_METRO_MODE) return null; process.env.ONE_METRO_MODE && console.info("ONE_METRO_MODE environment variable is set, enabling Metro mode"); const routerRoot2 = (0, import_getRouterRootFromOneOptions.getRouterRootFromOneOptions)(options), defaultMetroOptions = (0, import_getViteMetroPluginOptions.getViteMetroPluginOptions)({ projectRoot: process.cwd(), // TODO: hard-coded process.cwd(), we should make this optional since the plugin can have a default to vite's `config.root`. relativeRouterRoot: routerRoot2, ignoredRouteFiles: options.router?.ignoredRouteFiles, userDefaultConfigOverrides: options.native?.bundlerOptions?.defaultConfigOverrides, setupFile: options.setupFile }), userMetroOptions = options.native?.bundlerOptions, babelConfig = { ...defaultMetroOptions?.babelConfig, ...userMetroOptions?.babelConfig }; return { ...defaultMetroOptions, ...userMetroOptions, defaultConfigOverrides: defaultMetroOptions?.defaultConfigOverrides, // defaultConfigOverrides is merged by getViteMetroPluginOptions, so we need to set it here again. argv: { ...defaultMetroOptions?.argv, ...userMetroOptions?.argv }, babelConfig: { ...babelConfig, plugins: [ ...babelConfig.plugins || [], ...options.react?.compiler === !0 || options.react?.compiler === "native" ? ["babel-plugin-react-compiler"] : [] ] }, mainModuleName: "one/metro-entry", // So users won't need to write `"main": "one/metro-entry"` in their `package.json` like ordinary Expo apps. // allow env var to enable lazy startup startup: process.env.ONE_METRO_LAZY ? "lazy" : userMetroOptions?.startup }; })(), vxrnPlugins = []; if (!process.env.IS_VXRN_CLI) console.warn("Experimental: running VxRN as a Vite plugin. This is not yet stable."), vxrnPlugins.push( (0, import_vite_plugin.default)({ metro: metroOptions }) ); else if (!globalThis.__oneOptions) return (0, import_loadConfig.setOneOptions)(options), globalThis.__vxrnPluginConfig__ = options, globalThis.__vxrnMetroOptions__ = metroOptions, []; options.config?.ensureTSConfig !== !1 && (0, import_ensureTsConfig.ensureTSConfig)(); const vxrnOptions = (0, import_vxrn.getOptionsFilled)(), root = vxrnOptions?.root || process.cwd(), compiler = options.react?.compiler; compiler && (0, import_compiler.configureVXRNCompilerPlugin)({ enableCompiler: ( // pass through object config, regex, or function directly typeof compiler == "object" || typeof compiler == "function" ? compiler : compiler === "native" ? ["ios", "android"] : compiler === "web" ? ["ssr", "client"] : !0 ) }); const autoDepsOptions = options.ssr?.autoDepsOptimization, devAndProdPlugins = [ { name: "one:config", __get: options }, { name: "one:env-prefix", config(userConfig) { if (!userConfig.envPrefix) return { envPrefix: ["VITE_", "EXPO_PUBLIC_"] }; } }, (0, import_environmentGuardPlugin.environmentGuardPlugin)(options.environmentGuards), (0, import_imageDataPlugin.imageDataPlugin)(), { name: "one-define-client-env", async config(userConfig) { return { define: { ...options.skipEnv ? {} : (await (0, import_vxrn.loadEnv)( vxrnOptions?.mode ?? userConfig?.mode ?? "development", process.cwd(), userConfig?.envPrefix )).clientEnvDefine, ...process.env.ONE_DEBUG_ROUTER && { "process.env.ONE_DEBUG_ROUTER": JSON.stringify( process.env.ONE_DEBUG_ROUTER ) } } }; } }, ...autoDepsOptions === !1 ? [] : [ (0, import_vxrn.autoDepOptimizePlugin)({ onScannedDeps({ hasReanimated, hasNativewind }) { (0, import_compiler.configureVXRNCompilerPlugin)({ enableReanimated: hasReanimated, enableNativeCSS: options.native?.css ?? hasNativewind, enableNativewind: hasNativewind }); }, root, include: /node_modules/, ...autoDepsOptions === !0 ? {} : autoDepsOptions }) ], ...options.config?.tsConfigPaths === !1 ? [] : [ (() => { const pathsConfig = options.config?.tsConfigPaths, tsPathsPlugin = (0, import_vite_tsconfig_paths.default)({ projectDiscovery: "eager", ignoreConfigErrors: !0, skip: (dir) => (dir.split("/").pop() || "").startsWith("."), ...pathsConfig && typeof pathsConfig == "object" ? pathsConfig : {} }); return { ...tsPathsPlugin, // let vite aliases (e.g. react-native → react-native-web) resolve first enforce: void 0, // parallel viteBuild() calls share this plugin, so the second // build's buildStart can fire before configResolved initializes // tsconfigResolvers — swallow the error since buildStart only // resets caches which isn't needed for parallel builds buildStart() { try { return tsPathsPlugin.buildStart?.call(this); } catch { } } }; })() ], { name: "one-aliases", enforce: "pre", config() { let tslibLitePath = ""; try { tslibLitePath = (0, import_resolve.resolvePath)("@vxrn/tslib-lite", process.cwd()); } catch (err) { console.info("Can't find tslib-lite, falling back to tslib"), process.env.DEBUG && console.error(err); } return { resolve: { alias: { // testing getting transition between routes working // 'use-sync-external-store/with-selector': resolvePath( // 'use-sync-external-store/shim/with-selector' // ), ...tslibLitePath && { tslib: tslibLitePath } } } }; } }, { name: "one:init-config", config() { const setupFileDefines = (() => { if (!options.setupFile) return {}; let setupFiles; return typeof options.setupFile == "string" ? setupFiles = { client: options.setupFile, server: options.setupFile, ios: options.setupFile, android: options.setupFile } : "native" in options.setupFile ? setupFiles = { client: options.setupFile.client, server: options.setupFile.server, ios: options.setupFile.native, android: options.setupFile.native } : setupFiles = options.setupFile, { ...setupFiles.client && { "process.env.ONE_SETUP_FILE_CLIENT": JSON.stringify(setupFiles.client) }, ...setupFiles.server && { "process.env.ONE_SETUP_FILE_SERVER": JSON.stringify(setupFiles.server) }, ...setupFiles.ios && { "process.env.ONE_SETUP_FILE_IOS": JSON.stringify(setupFiles.ios) }, ...setupFiles.android && { "process.env.ONE_SETUP_FILE_ANDROID": JSON.stringify(setupFiles.android) } }; })(); return { // Platform env defined at root level for client (workaround for Vite bug with environment.client.define) define: { ...(0, import_vite_plugin_metro.getPlatformEnvDefine)("client"), ...setupFileDefines, ...options.web?.defaultRenderMode && { "process.env.ONE_DEFAULT_RENDER_MODE": JSON.stringify( options.web.defaultRenderMode ), "import.meta.env.ONE_DEFAULT_RENDER_MODE": JSON.stringify( options.web.defaultRenderMode ) }, ...process.env.NODE_ENV !== "production" && vxrnOptions && { "process.env.ONE_SERVER_URL": JSON.stringify(vxrnOptions.server.url), "import.meta.env.ONE_SERVER_URL": JSON.stringify(vxrnOptions.server.url) }, ...options.web?.linkPrefetch && { "process.env.ONE_LINK_PREFETCH": JSON.stringify(options.web.linkPrefetch) }, ...options.web?.skewProtection !== void 0 && { "process.env.ONE_SKEW_PROTECTION": JSON.stringify( options.web.skewProtection === !0 ? "true" : options.web.skewProtection === !1 ? "false" : options.web.skewProtection // 'proactive' ) } }, environments: { ssr: { define: (0, import_vite_plugin_metro.getPlatformEnvDefine)("ssr") }, ios: { define: (0, import_vite_plugin_metro.getPlatformEnvDefine)("ios") }, android: { define: (0, import_vite_plugin_metro.getPlatformEnvDefine)("android") } }, ssr: { // ensure server-only/client-only go through vite so our environmentGuardPlugin can handle them noExternal: ["server-only", "client-only"] } }; } }, { name: "one:tamagui", config() { return { define: { // safe to set because it only affects web in tamagui, and one is always react 19 "process.env.TAMAGUI_REACT_19": '"1"' }, environments: { ssr: { define: { "process.env.TAMAGUI_IS_SERVER": '"1"', "process.env.TAMAGUI_KEEP_THEMES": '"1"' } }, ios: { define: { "process.env.TAMAGUI_KEEP_THEMES": '"1"' } }, android: { define: { "process.env.TAMAGUI_KEEP_THEMES": '"1"' } } } }; } }, { name: "route-module-hmr-fix", hotUpdate({ server, modules, file }) { const envName = this.environment?.name, fileRelativePath = import_node_path.default.relative(server.config.root, file), isAppFile = fileRelativePath.split(import_node_path.default.sep)[0] === "app"; if (envName === "ssr" && isAppFile) return []; let hasRouteUpdate = !1; const result = modules.map((m) => { const { id } = m; if (!id) return m; const relativePath = import_node_path.default.relative(server.config.root, id); return relativePath.split(import_node_path.default.sep)[0] === "app" && (m.acceptedHmrExports = /* @__PURE__ */ new Set(), (relativePath === import_node_path.default.join("app", "_layout.tsx") || /^app[\\/]\([^)]+\)[\\/]_layout\.tsx$/.test(relativePath)) && (hasRouteUpdate = !0)), m; }); return hasRouteUpdate && server.hot.send({ type: "custom", event: "one:route-update", data: { file: fileRelativePath } }), result; } }, // Plugins may transform the source code and add imports of `react/jsx-dev-runtime`, which won't be discovered by Vite's initial `scanImports` since the implementation is using ESbuild where such plugins are not executed. // Thus, if the project has a valid `react/jsx-dev-runtime` import, we tell Vite to optimize it, so Vite won't only discover it on the next page load and trigger a full reload. { name: "one:optimize-dev-deps", config(_, env) { if (env.mode === "development") return { optimizeDeps: { include: ["react/jsx-dev-runtime", "react/compiler-runtime"] } }; } }, { name: "one:remove-server-from-client", enforce: "pre", transform(code, id) { if (this.environment.name === "client" && id.includes("one-server-only")) return code.replace( 'import { AsyncLocalStorage } from "node:async_hooks"', "class AsyncLocalStorage {}" ); } } ], nativeWebDevAndProdPlugsin = [(0, import_clientTreeShakePlugin.clientTreeShakePlugin)()]; globalThis.__vxrnAddNativePlugins = nativeWebDevAndProdPlugsin, globalThis.__vxrnAddWebPluginsProd = devAndProdPlugins; const flags = { experimentalPreventLayoutRemounting: options.router?.experimental?.preventLayoutRemounting }; return [ ...vxrnPlugins, ...devAndProdPlugins, ...nativeWebDevAndProdPlugsin, /** * This is really the meat of one, where it handles requests: */ (0, import_fileSystemRouterPlugin.createFileSystemRouterPlugin)(options), (0, import_generateFileSystemRouteTypesPlugin.generateFileSystemRouteTypesPlugin)(options), (0, import_fixDependenciesPlugin.fixDependenciesPlugin)(options.deps), (0, import_virtualEntryPlugin.createVirtualEntry)({ ...options, flags, root: routerRoot }), { name: "one-define-environment", config() { return { define: { ...options.native?.key && { "process.env.ONE_APP_NAME": JSON.stringify(options.native.key), "import.meta.env.ONE_APP_NAME": JSON.stringify(options.native.key) }, "process.env.ONE_CACHE_KEY": JSON.stringify(import_constants.CACHE_KEY), "import.meta.env.ONE_CACHE_KEY": JSON.stringify(import_constants.CACHE_KEY) } }; } }, (0, import_SSRCSSPlugin.SSRCSSPlugin)({ entries: [import_virtualEntryConstants.virtualEntryId] }), // devtools (always includes refresh preamble for HMR, optionally includes UI) ...(() => { const devtools = options.devtools ?? !0, includeUI = devtools !== !1, inspector = devtools === !0 || devtools !== !1 && (devtools.inspector ?? !0); return [ // always include devtools plugin for refresh preamble (required for HMR) (0, import_devtoolsPlugin.createDevtoolsPlugin)({ includeUI }), ...inspector ? (0, import_sourceInspectorPlugin.sourceInspectorPlugin)() : [] ]; })() ]; } //# sourceMappingURL=one.js.map