【Umi】- 配置文件的加载机制
问题
我们想在前端工程中,提供不通环境的配置,比如:开发环境、测试环境、生产环境,甚至更细的话,开发环境还可能有本地环境、Mock环境等。
通常做法是提供不通的.umirc.*.ts 文件
- .umirc.dev.ts:开发环境
- .umirc.mock.ts:Mock环境
。。。。
npm run dev 启动开发环境,这时候发现,umi 同时使用了 dev 和 mock,这是什么原因?
加载机制
在 Umi 4 中,.umirc.ts
文件是用于配置 Umi 项目的核心配置文件之一。Umi 会在项目启动时加载该文件,并根据其中的配置来初始化和运行项目。以下是 .umirc.ts 文件的加载机制和相关细节:
1. 文件加载顺序
Umi 会按照以下顺序加载配置文件:
config/config.ts
:推荐的配置文件路径,优先级高于 .umirc.ts。.umirc.ts
:如果没有config/config.ts
,则会加载该文件。- 环境变量配置文件:如
.umirc.local.ts
或.umirc.{env}.ts
(例如.umirc.dev.ts
、.umirc.prod.ts
),用于根据环境变量加载不同的配置。这个配置优先级高于umirc.ts。.umirc.local.ts
是本地配置,优先级最高
如果多个文件存在,Umi 会根据优先级合并配置,后加载的配置会覆盖前面的配置。
2. 加载时机
- 开发模式:在执行
umi dev
时,Umi 会读取 .umirc.ts 文件,以及 .umirc.dev.*.ts 文件
,并根据配置启动开发服务器。 - 构建模式:在执行
umi build
时,Umi 会读取 .umirc.ts 文件,并根据配置生成生产环境的构建文件。
3. 配置解析
.umirc.ts 文件中的配置是一个默认导出的对象,Umi 会解析该对象并应用到项目中。常见的配置项包括:
- 路由配置:
routes
,用于定义项目的路由规则。 - 插件配置:
plugins
,用于加载 Umi 插件。 - 构建配置:如
outputPath
、publicPath
等,用于控制构建输出。 - 代理配置:
proxy
,用于设置开发环境的 API 代理。 - 主题配置:
theme
,用于自定义 Ant Design 的主题。
例如:
import { defineConfig } from 'umi';export default defineConfig({routes: [{ path: '/', component: '@/pages/index' },{ path: '/about', component: '@/pages/about' },],proxy: {'/api': {target: 'http://localhost:3000',changeOrigin: true,},},theme: {'primary-color': '#1DA57A',},outputPath: 'dist',
});
4. 动态加载
Umi 支持动态加载配置文件。例如,可以通过环境变量动态加载不同的配置文件:
- 设置
NODE_ENV=development
时,Umi 会优先加载.umirc.dev.ts
。 - 设置
NODE_ENV=production
时,Umi 会优先加载.umirc.prod.ts
。
5. 热更新支持
在开发模式下(umi dev
),.umirc.ts
文件的修改会触发热更新,Umi 会自动重新加载配置并应用更改,无需手动重启开发服务器。
6. 插件扩展
Umi 的插件机制允许通过 .umirc.ts 文件加载和配置插件。例如:
export default defineConfig({plugins: ['@umijs/plugins/dist/dva','@umijs/plugins/dist/antd',],dva: {immer: true,hmr: true,},antd: {dark: false,compact: true,},
});
7. 与 config/config.ts
的关系
- 如果同时存在 .umirc.ts 和
config/config.ts
,Umi 会优先加载config/config.ts
。 - 推荐使用
config/config.ts
,因为它支持更清晰的目录结构和更好的可维护性。
在 Umi 中,配置文件的合并机制并不是简单的浅合并,而是深度合并。这意味着当多个配置文件(如 .umirc.ts、.umirc.{env}.ts
或 config/config.ts
)存在时,Umi 会递归地合并配置对象的属性,而不是直接覆盖整个对象。
8 深度合并的行为
- 基础配置:Umi 会先加载基础配置文件(如 .umirc.ts 或
config/config.ts
)。 - 环境配置:如果存在环境相关的配置文件(如
.umirc.dev.ts
或.umirc.prod.ts
),Umi 会将这些配置与基础配置进行深度合并。 - 局部覆盖:对于对象类型的配置项,环境配置中的属性会覆盖基础配置中的对应属性,而不会完全替换整个对象。
- 数组处理:对于数组类型的配置项,Umi 通常会直接覆盖,而不是合并。
示例
假设有以下配置文件:
基础配置 .umirc.ts
import { defineConfig } from 'umi';export default defineConfig({theme: {'primary-color': '#1DA57A','link-color': '#1890ff',},proxy: {'/api': {target: 'http://localhost:3000',changeOrigin: true,},},
});
环境配置 .umirc.dev.ts
import { defineConfig } from 'umi';export default defineConfig({theme: {'primary-color': '#ff4d4f', // 覆盖基础配置中的 primary-color},proxy: {'/api': {target: 'http://localhost:3001', // 覆盖基础配置中的 target},},
});
合并结果
在开发环境中(NODE_ENV=development
),Umi 会将两者合并,结果如下:
{theme: {'primary-color': '#ff4d4f', // 来自 .umirc.dev.ts'link-color': '#1890ff', // 来自 .umirc.ts},proxy: {'/api': {target: 'http://localhost:3001', // 来自 .umirc.dev.tschangeOrigin: true, // 来自 .umirc.ts},},
}
注意事项
- 插件配置:对于插件的配置(如
plugins
),Umi 会直接覆盖,而不会合并数组。 - 特殊处理:某些配置项(如
routes
)可能需要手动合并,因为它们的合并逻辑可能不符合预期。 - 优先级:环境配置文件的优先级高于基础配置文件。
总结
所以,我们如果想区分多个开发环境,避免深度合并或者由于加载顺序而覆盖配置,那么不要在配置文件命名中包含dev,不然umi dev 会默认寻找含有dev的配置文件