diff --git a/docs/config/shared-options.md b/docs/config/shared-options.md index e7708d80c517cf..2e825609b96862 100644 --- a/docs/config/shared-options.md +++ b/docs/config/shared-options.md @@ -154,20 +154,10 @@ Export keys ending with "/" is deprecated by Node and may not work well. Please ## resolve.mainFields - **Type:** `string[]` -- **Default:** `['module', 'jsnext:main', 'jsnext']` +- **Default:** `['browser', 'module', 'jsnext:main', 'jsnext']` List of fields in `package.json` to try when resolving a package's entry point. Note this takes lower precedence than conditional exports resolved from the `exports` field: if an entry point is successfully resolved from `exports`, the main field will be ignored. -## resolve.browserField - -- **Type:** `boolean` -- **Default:** `true` -- **Deprecated** - -Whether to enable resolving to `browser` field. - -In future, `resolve.mainFields`'s default value will be `['browser', 'module', 'jsnext:main', 'jsnext']` and this option will be removed. - ## resolve.extensions - **Type:** `string[]` diff --git a/docs/guide/migration.md b/docs/guide/migration.md index 99e39a4e37fa81..667cbe3fbff6b0 100644 --- a/docs/guide/migration.md +++ b/docs/guide/migration.md @@ -135,6 +135,8 @@ Also there are other breaking changes which only affect few users. - In the past, Vite responded to requests outside the base path without `Accept: text/html`, as if they were requested with the base path. Vite no longer does that and responds with 404 instead. - [[#14723] fix(resolve)!: remove special .mjs handling](https://github.com/vitejs/vite/pull/14723) - In the past, when a library `"exports"` field maps to an `.mjs` file, Vite will still try to match the `"browser"` and `"module"` fields to fix compatibility with certain libraries. This behavior is now removed to align with the exports resolution algorithm. +- [[#14733] feat(resolve)!: remove `resolve.browserField`](https://github.com/vitejs/vite/pull/14733) + - `resolve.browserField` has been deprecated since Vite 3 in favour of an updated default of `['browser', 'module', 'jsnext:main', 'jsnext']` for `resolve.mainFields`. ## Migration from v3 diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index 7c2c5c5dff9732..e923e9c348ec10 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -530,7 +530,6 @@ export async function resolveConfig( const resolveOptions: ResolvedConfig['resolve'] = { mainFields: config.resolve?.mainFields ?? DEFAULT_MAIN_FIELDS, - browserField: config.resolve?.browserField ?? true, conditions: config.resolve?.conditions ?? [], extensions: config.resolve?.extensions ?? DEFAULT_EXTENSIONS, dedupe: config.resolve?.dedupe ?? [], @@ -538,6 +537,20 @@ export async function resolveConfig( alias: resolvedAlias, } + if ( + // @ts-expect-error removed field + config.resolve?.browserField === false && + resolveOptions.mainFields.includes('browser') + ) { + logger.warn( + colors.yellow( + `\`resolve.browserField\` is set to false, but the option is removed in favour of ` + + `the 'browser' string in \`resolve.mainFields\`. You may want to update \`resolve.mainFields\` ` + + `to remove the 'browser' string and preserve the previous browser behaviour.`, + ), + ) + } + // load .env files const envDir = config.envDir ? normalizePath(path.resolve(resolvedRoot, config.envDir)) @@ -1060,7 +1073,6 @@ async function bundleConfigFile( preferRelative: false, tryIndex: true, mainFields: [], - browserField: false, conditions: [], overrideConditions: ['node'], dedupe: [], diff --git a/packages/vite/src/node/constants.ts b/packages/vite/src/node/constants.ts index 414d1b6430918f..5d8d0d10ca7839 100644 --- a/packages/vite/src/node/constants.ts +++ b/packages/vite/src/node/constants.ts @@ -9,6 +9,7 @@ const { version } = JSON.parse( export const VERSION = version as string export const DEFAULT_MAIN_FIELDS = [ + 'browser', 'module', 'jsnext:main', // moment still uses this... 'jsnext', diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index 556a85101b3db7..67b8d079e724ea 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -71,14 +71,9 @@ const debug = createDebugger('vite:resolve-details', { export interface ResolveOptions { /** - * @default ['module', 'jsnext:main', 'jsnext'] + * @default ['browser', 'module', 'jsnext:main', 'jsnext'] */ mainFields?: string[] - /** - * @deprecated In future, `mainFields` should be used instead. - * @default true - */ - browserField?: boolean conditions?: string[] /** * @default ['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json'] @@ -283,7 +278,7 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin { if ( targetWeb && - options.browserField && + options.mainFields.includes('browser') && (res = tryResolveBrowserMapping(fsPath, importer, options, true)) ) { return res @@ -367,7 +362,7 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin { if ( targetWeb && - options.browserField && + options.mainFields.includes('browser') && (res = tryResolveBrowserMapping( id, importer, @@ -988,7 +983,7 @@ export function resolvePackageEntry( } // handle edge case with browser and module field semantics - if (!entryPoint && targetWeb && options.browserField) { + if (!entryPoint && targetWeb && options.mainFields.includes('browser')) { // check browser field // https://github.com/defunctzombie/package-browser-field-spec const browserEntry = @@ -1059,7 +1054,11 @@ export function resolvePackageEntry( } else { // resolve object browser field in package.json const { browser: browserField } = data - if (targetWeb && options.browserField && isObject(browserField)) { + if ( + targetWeb && + options.mainFields.includes('browser') && + isObject(browserField) + ) { entry = mapWithBrowserField(entry, browserField) || entry } } @@ -1181,7 +1180,11 @@ function resolveDeepImport( `${path.join(dir, 'package.json')}.`, ) } - } else if (targetWeb && options.browserField && isObject(browserField)) { + } else if ( + targetWeb && + options.mainFields.includes('browser') && + isObject(browserField) + ) { // resolve without postfix (see #7098) const { file, postfix } = splitFileAndPostfix(relativeId) const mapped = mapWithBrowserField(file, browserField) diff --git a/packages/vite/src/node/ssr/ssrModuleLoader.ts b/packages/vite/src/node/ssr/ssrModuleLoader.ts index 65a357b127656f..6ad10fe85d0eb1 100644 --- a/packages/vite/src/node/ssr/ssrModuleLoader.ts +++ b/packages/vite/src/node/ssr/ssrModuleLoader.ts @@ -137,7 +137,6 @@ async function instantiateModule( const resolveOptions: NodeImportResolveOptions = { mainFields: ['main'], - browserField: true, conditions: [], overrideConditions: [...overrideConditions, 'production', 'development'], extensions: ['.js', '.cjs', '.json'], diff --git a/playground/resolve/vite.config.js b/playground/resolve/vite.config.js index b27df23e734eeb..c016401a85ffb2 100644 --- a/playground/resolve/vite.config.js +++ b/playground/resolve/vite.config.js @@ -27,7 +27,7 @@ const generatedContentImports = [ export default defineConfig({ resolve: { extensions: ['.mjs', '.js', '.es', '.ts'], - mainFields: ['custom', 'module'], + mainFields: ['browser', 'custom', 'module'], conditions: ['custom'], }, define: {