one
Version:
One is a new React Framework that makes Vite serve both native and web.
415 lines (414 loc) • 18.8 kB
JavaScript
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_node_events = __toESM(require("node:events"), 1), import_node_path = __toESM(require("node:path"), 1), import_compiler = require("@vxrn/compiler"), import_resolve = require("@vxrn/resolve"), import_vite_plugin_barrel = require("vite-plugin-barrel"), 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_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_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.
};
})(), 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)();
let tsConfigPathsPlugin = null;
const vxrnOptions = (0, import_vxrn.getOptionsFilled)(), root = vxrnOptions?.root || process.cwd(), barrelOption = options.optimization?.barrel, compiler = options.react?.compiler;
compiler && (0, import_compiler.configureVXRNCompilerPlugin)({
enableCompiler: compiler === "native" ? ["ios", "android"] : compiler === "web" ? ["ssr", "client"] : !0
});
const autoDepsOptions = options.ssr?.autoDepsOptimization, devAndProdPlugins = [
{
name: "one:config",
__get: options
},
barrelOption ? (0, import_vite_plugin_barrel.barrel)({
packages: Array.isArray(barrelOption) ? barrelOption : ["@tamagui/lucide-icons"]
}) : null,
(0, import_imageDataPlugin.imageDataPlugin)(),
{
name: "one-define-client-env",
async config(userConfig) {
const { clientEnvDefine } = await (0, import_vxrn.loadEnv)(
vxrnOptions?.mode ?? userConfig?.mode ?? "development",
process.cwd(),
userConfig?.envPrefix
);
return {
define: {
...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
})
],
// proxy because you cant add a plugin inside a plugin
new Proxy(
{
name: "one:tsconfig-paths",
config(configIncoming) {
const pathsConfig = options.config?.tsConfigPaths;
if (pathsConfig === !1 || configIncoming.plugins?.flat().some((p) => p && p.name === "vite-tsconfig-paths"))
return;
tsConfigPathsPlugin = (0, import_vite_tsconfig_paths.default)({
skip: (dir) => (dir.split("/").pop() || "").startsWith("."),
...pathsConfig && typeof pathsConfig == "object" ? pathsConfig : {}
});
},
configResolved() {
},
resolveId() {
}
},
{
get(target, key, thisArg) {
if (key === "config" || key === "name")
return Reflect.get(target, key, thisArg);
if (tsConfigPathsPlugin)
return Reflect.get(tsConfigPathsPlugin, key, thisArg);
}
}
),
{
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
}
}
// [
// {
// find: /tslib/,
// replacement: resolvePath('@vxrn/tslib-lite'),
// },
// // not working but would save ~30Kb stat
// // {
// // find: /@react-navigation\/core.*\/getStateFromPath/,
// // replacement: join(forkPath, 'fork', 'getStateFromPath.mjs'),
// // },
// // {
// // find: /@react-navigation\/core.*\/getPathFromState/,
// // replacement: join(forkPath, 'fork', 'getPathFromState.mjs'),
// // },
// ],
}
};
}
},
{
name: "one:init-config",
config() {
return {
define: {
// we define this not in environment.client because there must be a bug in vite
// it doesnt define the import.meta.env at all if you do that
"process.env.TAMAGUI_ENVIRONMENT": '"client"',
"process.env.VITE_ENVIRONMENT": '"client"',
"import.meta.env.VITE_ENVIRONMENT": '"client"',
"process.env.VITE_PLATFORM": '"web"',
"import.meta.env.VITE_PLATFORM": '"web"',
"process.env.EXPO_OS": '"web"',
"import.meta.env.EXPO_OS": '"web"',
...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
)
},
...(() => {
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
)
}
};
})(),
...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)
}
},
environments: {
// we define client vars not in environment.client because there must be a bug in vite
// it doesnt define the import.meta.env at all if you do that
// client: {
// define: {
// },
// },
ssr: {
define: {
"process.env.TAMAGUI_ENVIRONMENT": '"ssr"',
"process.env.VITE_ENVIRONMENT": '"ssr"',
// Note that we are also setting `process.env.VITE_ENVIRONMENT = 'ssr'` for this current process. See `setServerGlobals()` and `setupServerGlobals.ts`.
"import.meta.env.VITE_ENVIRONMENT": '"ssr"',
"process.env.VITE_PLATFORM": '"web"',
"import.meta.env.VITE_PLATFORM": '"web"',
"process.env.EXPO_OS": '"web"',
"import.meta.env.EXPO_OS": '"web"'
}
},
ios: {
define: {
"process.env.TAMAGUI_ENVIRONMENT": '"ios"',
"process.env.VITE_ENVIRONMENT": '"ios"',
"import.meta.env.VITE_ENVIRONMENT": '"ios"',
"process.env.VITE_PLATFORM": '"native"',
"import.meta.env.VITE_PLATFORM": '"native"',
"process.env.EXPO_OS": '"ios"',
"import.meta.env.EXPO_OS": '"ios"'
}
},
android: {
define: {
"process.env.TAMAGUI_ENVIRONMENT": '"android"',
"process.env.VITE_ENVIRONMENT": '"android"',
"import.meta.env.VITE_ENVIRONMENT": '"android"',
"process.env.VITE_PLATFORM": '"native"',
"import.meta.env.VITE_PLATFORM": '"native"',
"process.env.EXPO_OS": '"android"',
"import.meta.env.EXPO_OS": '"android"'
}
}
}
};
}
},
{
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)()
//
// reactScanPlugin
];
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]
}),
// Source inspector - show source file location on hover with Shift+Ctrl/Cmd
...(() => {
const devtools = options.devtools ?? !0;
return devtools === !1 ? [] : devtools === !0 || (devtools.inspector ?? !0) ? (0, import_sourceInspectorPlugin.sourceInspectorPlugin)() : [];
})()
];
}
//# sourceMappingURL=one.js.map