登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  前端

Vite resolve.conditions 怎么选择 browser 和 development 条件导出

来源:17golang原创

时间:2026-11-05 16:01:23 431浏览 收藏

我在接入一个同时提供浏览器实现和调试实现的依赖时,最容易误判的不是 Vite 配置语法,而是把“平台条件”和“运行模式条件”混成了一件事。开发服务器拿到的文件可能带调试信息,生产构建则应拿到更轻的实现;如果只盯着 browser,就很难解释两次解析为什么不同。

官方地址:https://vite.dev/config/shared-options

先记住结论:浏览器项目通常保留 Vite 的客户端默认条件,再让 development|production 随模式替换。只有确实要支持额外条件时,才扩展列表;不要用一个自定义字符串去代替包本身声明的 import、browser 或 default。

为什么开发环境和生产构建会拿到不同文件

一个依赖可以在 package.json 的 exports 中声明多层条件。Vite 当前客户端默认值包含 module、browser 和特殊值 development|production;它会根据 process.env.NODE_ENV 把最后一个值替换成 development 或 production。import、require、default 在满足条件时也会参与解析。

{
  "exports": {
    ".": {
      "browser": {
        "development": "./dist/browser-dev.js",
        "production": "./dist/browser-prod.js"
      },
      "default": "./dist/universal.js"
    }
  }
}

这个结构先表达“浏览器平台”,再表达“开发或生产模式”。条件对象的键顺序有意义,越具体的分支越应该放在前面;default 是兜底,不要把它放到会提前命中的位置。图中用静态关系把五类条件和最终出口拆开,便于看出 browser 并不会自动等于 development。

Vite 条件匹配结构说明图,展示 browser、development、production 与 exports 入口的关系
图1:条件匹配结构说明图,展示平台条件、模式条件与 default 回退之间的关系,不是构建截图。

先判断问题到底出在平台还是模式

我通常先把现象分成两类。若浏览器构建误拿了 Node 依赖,优先看 browser 分支和是否存在 default;若开发和生产只差调试开关、错误信息或日志,则看 development 与 production 的嵌套关系。

第二个判断是入口形式。Vite 的 resolve.conditions 是参与 Conditional Exports 的允许条件,不是把任意字符串写进 exports 就能让包自动切换。包必须先声明相同的条件名;否则配置加了也没有匹配对象。

import { defineConfig } from 'vite'

export default defineConfig(({ mode }) => ({
  // 用 mode 记录当前构建意图,条件选择仍由 Vite 处理
  define: {
    __BUILD_MODE__: JSON.stringify(mode),
  },
  resolve: {
    // 自定义条件要与依赖的 exports 键完全一致
    conditions: ['module', 'browser', 'development|production'],
  },
}))

这里没有额外条件,所以显式写出客户端默认值只是为了让配置意图清楚。真正需要扩展时,再把例如 worker 之类的包作者条件加进去,并确认它不会让同一个依赖在不同入口之间漂移。

resolve.conditions 应该怎么写

如果你的目标只是普通浏览器应用,优先采用默认行为,不要为了“保险”写一串重复条件。若项目确实有额外出口,可以把默认客户端条件和自定义条件放在同一份配置里:

import { defineConfig } from 'vite'

export default defineConfig({
  resolve: {
    // 保留客户端解析基础,再追加包作者明确声明的条件
    conditions: [
      'module',
      'browser',
      'development|production',
      'worker',
    ],
  },
})

这里的关键不是数组越长越好,而是每个条件都能在依赖的 exports 中找到对应分支。Node 文档还强调了嵌套条件和对象键顺序:先写更具体的组合,再写通用的 default。因此,条件命名和顺序应由包作者与消费方共同约定。

Vite resolve.conditions 配置边界说明图,展示默认条件、自定义条件与 package exports 的静态关系
图2:配置边界说明图,展示 resolve.conditions 到 package exports 的静态关系,不是运行结果截图。

几个容易把判断带偏的边界

  • 不要把 browser 当成 mainFields。 resolve.mainFields 是查找 package.json 顶层字段的另一套机制;如果 exports 已经成功解析,它优先级更高。
  • 不要省略 default。 包面向未知 JavaScript 环境时,通用回退能减少环境伪装带来的兼容问题。
  • 留意 SSR。 客户端条件与 SSR 的目标不同,服务端构建不应机械复制浏览器条件;先看该构建的 resolve 配置和依赖出口。
  • 检查 NODE_ENV 来源。 Vite 文档规定特殊值会根据 process.env.NODE_ENV 替换,不要把“执行了 vite build”简单等同于所有自定义脚本都已设置同样环境变量。

最后用一张表收口

现象优先查看处理方向
浏览器拿到 Node 实现browser、default确认包声明了浏览器分支,并保留通用回退
开发和生产入口不同development|production检查 NODE_ENV 与嵌套条件顺序
新增条件完全不生效条件名、exports 键顺序让配置字符串与包声明逐字一致

所以,Vite 的 resolve.conditions 更像一张“允许参与匹配的条件清单”,不是切换文件的开关面板。先按平台、模式、模块形式拆分问题,再决定是否扩展配置,通常比不断增加条件更快找到真正的入口。

相关问题

只配置 browser,为什么开发和生产仍然不同?

因为模式条件可能仍然参与匹配;browser 只说明平台,不能替代 development 与 production 的分支。

自定义条件可以随便命名吗?

可以使用包作者和工具链约定的字符串,但消费方配置必须与 exports 中的键完全一致,并明确它的优先级与回退路径。

default 应该放在哪里?

在同一条件对象中通常放在更具体分支之后,作为未知环境仍能使用的通用入口。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>