diff --git a/src/options.ts b/src/options.ts index 4af740d5db..02769fd985 100644 --- a/src/options.ts +++ b/src/options.ts @@ -366,6 +366,12 @@ export async function loadOptions( // Resolve plugin paths options.plugins = options.plugins.map((p) => resolvePath(p, options)); + // Export conditions + options.exportConditions = _resolveExportConditions( + options.exportConditions, + { dev: options.dev, node: options.node } + ); + // Add open-api endpoint if (options.dev && options.experimental.openAPI) { options.handlers.push({ @@ -458,3 +464,43 @@ export function normalizeRouteRules( } return normalizedRules; } + +function _resolveExportConditions( + conditions: string[] = [], + opts: { dev: boolean; node: boolean } +) { + const resolvedConditions: string[] = []; + + // 1. Add dev or production + resolvedConditions.push(opts.dev ? "development" : "production"); + + // 2. Add user specified conditions + resolvedConditions.push(...conditions); + + // 3. Add runtime conditions (node or web) + if (opts.node) { + resolvedConditions.push("node"); + } else { + // https://runtime-keys.proposal.wintercg.org/ + resolvedConditions.push( + "wintercg", + "worker", + "web", + "browser", + "workerd", + "edge-light", + "lagon", + "netlify", + "edge-routine", + "deno" + ); + } + + // 4. Add default conditions + resolvedConditions.push("import", "module", "default"); + + // Dedup with preserving order + return resolvedConditions.filter( + (c, i) => resolvedConditions.indexOf(c) === i + ); +} diff --git a/src/presets/bun.ts b/src/presets/bun.ts index ef4c982ace..4ff86a35ad 100644 --- a/src/presets/bun.ts +++ b/src/presets/bun.ts @@ -4,14 +4,8 @@ import { defineNitroPreset } from "../preset"; export const bun = defineNitroPreset({ extends: "node-server", entry: "#internal/nitro/entries/bun", - externals: { - traceInclude: ["ofetch", "uncrypto", "node-fetch-native"].map((id) => - resolvePathSync(id, { - url: import.meta.url, - conditions: ["bun"], - }) - ), - }, + // https://bun.sh/docs/runtime/modules#resolution + exportConditions: ["bun", "worker", "module", "node", "default", "browser"], commands: { preview: "bun run ./server/index.mjs", }, diff --git a/src/presets/cloudflare-module.ts b/src/presets/cloudflare-module.ts index 827b829d58..1b08a834ed 100644 --- a/src/presets/cloudflare-module.ts +++ b/src/presets/cloudflare-module.ts @@ -6,6 +6,7 @@ import type { Nitro } from "../types"; export const cloudflareModule = defineNitroPreset({ extends: "base-worker", entry: "#internal/nitro/entries/cloudflare-module", + exportConditions: ["workerd"], commands: { preview: "npx wrangler dev ./server/index.mjs --site ./public --local", deploy: "npx wrangler deploy", diff --git a/src/presets/cloudflare-pages.ts b/src/presets/cloudflare-pages.ts index 7e9660f8f8..0f435c2d32 100644 --- a/src/presets/cloudflare-pages.ts +++ b/src/presets/cloudflare-pages.ts @@ -8,6 +8,7 @@ import type { Nitro } from "../types"; export const cloudflarePages = defineNitroPreset({ extends: "cloudflare", entry: "#internal/nitro/entries/cloudflare-pages", + exportConditions: ["workerd"], commands: { preview: "npx wrangler pages dev ./", deploy: "npx wrangler pages deploy ./", diff --git a/src/presets/cloudflare.ts b/src/presets/cloudflare.ts index 56c9f53013..37f226339f 100644 --- a/src/presets/cloudflare.ts +++ b/src/presets/cloudflare.ts @@ -6,6 +6,7 @@ import type { Nitro } from "../types"; export const cloudflare = defineNitroPreset({ extends: "base-worker", entry: "#internal/nitro/entries/cloudflare", + exportConditions: ["workerd"], commands: { preview: "npx wrangler dev ./server/index.mjs --site ./public --local", deploy: "npx wrangler deploy", diff --git a/src/presets/deno-deploy.ts b/src/presets/deno-deploy.ts index e8a3a13073..6e7fb31543 100644 --- a/src/presets/deno-deploy.ts +++ b/src/presets/deno-deploy.ts @@ -2,6 +2,7 @@ import { defineNitroPreset } from "../preset"; export const denoDeploy = defineNitroPreset({ entry: "#internal/nitro/entries/deno-deploy", + exportConditions: ["deno"], node: false, noExternals: true, serveStatic: "deno", diff --git a/src/presets/deno-server.ts b/src/presets/deno-server.ts index 5a4d3d0c75..f4a07293c9 100644 --- a/src/presets/deno-server.ts +++ b/src/presets/deno-server.ts @@ -10,6 +10,7 @@ import { ImportMetaRe } from "../rollup/plugins/import-meta"; export const denoServer = defineNitroPreset({ extends: "node-server", entry: "#internal/nitro/entries/deno-server", + exportConditions: ["deno"], commands: { preview: "deno task --config ./deno.json start", }, diff --git a/src/presets/lagon.ts b/src/presets/lagon.ts index 4f1b7d4516..aa677845fb 100644 --- a/src/presets/lagon.ts +++ b/src/presets/lagon.ts @@ -18,6 +18,7 @@ export interface LagonFunctionConfig { export const lagon = defineNitroPreset({ extends: "base-worker", entry: "#internal/nitro/entries/lagon", + exportConditions: ["lagon"], commands: { preview: "npm run dev --prefix ./", deploy: "npm run deploy --prefix ./", diff --git a/src/presets/netlify.ts b/src/presets/netlify.ts index 1241b153f5..fde9142323 100644 --- a/src/presets/netlify.ts +++ b/src/presets/netlify.ts @@ -53,6 +53,7 @@ export const netlifyBuilder = defineNitroPreset({ export const netlifyEdge = defineNitroPreset({ extends: "base-worker", entry: "#internal/nitro/entries/netlify-edge", + exportConditions: ["netlify"], output: { serverDir: "{{ rootDir }}/.netlify/edge-functions/server", publicDir: "{{ rootDir }}/dist", diff --git a/src/presets/vercel.ts b/src/presets/vercel.ts index 60a5b72f51..7f278e7ce9 100644 --- a/src/presets/vercel.ts +++ b/src/presets/vercel.ts @@ -81,6 +81,7 @@ export const vercel = defineNitroPreset({ export const vercelEdge = defineNitroPreset({ extends: "base-worker", entry: "#internal/nitro/entries/vercel-edge", + exportConditions: ["edge-light"], output: { dir: "{{ rootDir }}/.vercel/output", serverDir: "{{ output.dir }}/functions/__nitro.func", diff --git a/src/rollup/config.ts b/src/rollup/config.ts index 12a473dae0..56fa571809 100644 --- a/src/rollup/config.ts +++ b/src/rollup/config.ts @@ -6,11 +6,11 @@ import { defu } from "defu"; // import terser from "@rollup/plugin-terser"; // TODO: Investigate jiti issue import type { RollupWasmOptions } from "@rollup/plugin-wasm"; import commonjs from "@rollup/plugin-commonjs"; -import { nodeResolve } from "@rollup/plugin-node-resolve"; import alias from "@rollup/plugin-alias"; import json from "@rollup/plugin-json"; import wasmPlugin from "@rollup/plugin-wasm"; import inject from "@rollup/plugin-inject"; +import { nodeResolve } from "@rollup/plugin-node-resolve"; import { isWindows } from "std-env"; import { visualizer } from "rollup-plugin-visualizer"; import * as unenv from "unenv"; @@ -404,13 +404,7 @@ export const plugins = [ processCwd: nitro.options.rootDir, exportsOnly: true, }, - exportConditions: [ - "default", - nitro.options.dev ? "development" : "production", - "module", - "node", - "import", - ], + exportConditions: nitro.options.exportConditions, }) ) ); @@ -425,13 +419,7 @@ export const plugins = [ modulePaths: nitro.options.nodeModulesDirs, // 'module' is intentionally not supported because of externals mainFields: ["main"], - exportConditions: [ - "default", - nitro.options.dev ? "development" : "production", - "module", - "node", - "import", - ], + exportConditions: nitro.options.exportConditions, }) ); diff --git a/src/rollup/plugins/externals.ts b/src/rollup/plugins/externals.ts index 033bad9cab..9be6b601e3 100644 --- a/src/rollup/plugins/externals.ts +++ b/src/rollup/plugins/externals.ts @@ -181,10 +181,10 @@ export function externals(opts: NodeExternalsOptions): Plugin { } // Trace used files using nft - const _fileTrace = await nodeFileTrace( - [...trackedExternals], - opts.traceOptions - ); + const _fileTrace = await nodeFileTrace([...trackedExternals], { + conditions: opts.exportConditions, + ...opts.traceOptions, + }); // Read package.json with cache const packageJSONCache = new Map(); // pkgDir => contents diff --git a/src/types/nitro.ts b/src/types/nitro.ts index 8239b4bbfa..abbca85246 100644 --- a/src/types/nitro.ts +++ b/src/types/nitro.ts @@ -267,6 +267,7 @@ export interface NitroOptions extends PresetOptions { analyze: false | PluginVisualizerOptions; replace: Record string)>; commonJS?: RollupCommonJSOptions; + exportConditions?: string[]; // Advanced typescript: {