ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

uni-app Vite配置全解析:从基础到高级实战指南

uni-app Vite配置全解析:从基础到高级实战指南 1. 为什么需要为uni-app配置Vite如果你正在用uni-app开发跨端应用并且项目是基于Vue 3的那么你大概率已经接触到了Vite。官方从HBuilderX 3.6.0版本开始为vue3、vue3-vite等编译器版本提供了Vite构建支持。很多开发者从Webpack迁移过来或者新建项目时选择了Vite模板上手后发现咦怎么没有vite.config.js这个文件这正是问题的起点。uni-app为了保持其“开箱即用”和跨端统一的特性在底层对Vite进行了一层封装和预设。当你运行npm run dev:mp-weixin或npm run build:mp-weixin时uni-app内部会调用一个预设好的Vite配置。这个预设配置处理了多平台小程序、H5、App的入口、插件、编译规则等复杂逻辑让你无需关心底层细节就能直接开发。那么我们为什么还需要手动配置vite.config.js呢预设配置虽好但无法覆盖所有个性化需求。我总结了几类最常见的场景需要添加或覆盖Vite插件比如你想用unplugin-auto-import自动导入Vue API或者用vite-plugin-style-import按需引入UI库的样式这些都需要修改Vite配置。需要修改底层构建行为例如调整esbuild的配置以支持实验性语法或者修改vitejs/plugin-vue的选项来改变Vue SFC的编译方式。需要配置开发服务器代理在H5端开发时为了解决跨域问题你需要在server.proxy中配置后端API的代理规则。需要定义环境变量和模式预设配置可能只提供了基础的development和production模式你想增加一个staging预发布模式并为其定义特定的环境变量和构建行为。需要集成其他工具链比如你想在构建流程中加入Visualizer分析包体积或者集成PWA相关的插件。简单来说当uni-app的“默认套餐”无法满足你的“定制化口味”时你就需要自己动手在项目根目录创建并配置vite.config.js。这个过程就是与uni-app的构建流程进行“深度对话”的过程。2. 创建与合并理解uni-app的Vite配置机制在纯Vite项目中vite.config.js是唯一的构建配置入口。但在uni-app中情况要复杂一些。uni-app本身已经内置了一套Vite配置。当你创建一个自定义的vite.config.js时实际上并不是替换而是合并Merge。uni-app CLI在启动时会做这样几件事首先加载其内部预设的Vite配置这个配置定义了多平台编译的核心规则。然后尝试在你的项目根目录寻找vite.config.js或vite.config.ts。如果找到则使用Vite提供的工具函数如defineConfig、mergeConfig将你的自定义配置与内部预设配置进行深度合并。这个合并过程是有优先级的。对于大多数选项如plugins、resolve.alias你的自定义配置会追加或覆盖内部配置。例如你在plugins数组里添加的新插件会被追加到插件链的末尾或根据enforce属性调整顺序。而如果你重新定义了resolve.alias新的别名映射会覆盖内部预设的同名别名。理解这个机制至关重要它能避免你写出“看似正确实则无效”的配置。一个常见的误区是直接复制一个纯Vue项目的Vite配置过来结果发现小程序编译报错。这是因为你很可能覆盖了uni-app内部处理小程序特定文件如.vue文件编译为小程序组件的关键插件。那么如何安全地创建你的第一个配置文件呢我建议从一个最小化的、仅做功能验证的配置开始。在你的uni-app项目根目录与package.json同级下新建一个vite.config.js文件。初始内容可以这样写import { defineConfig } from vite import uni from dcloudio/vite-plugin-uni // https://vitejs.dev/config/ export default defineConfig({ // 你的自定义配置将在这里展开 plugins: [ // uni() 插件是必须的它由uni-app内部预设自动添加。 // 你不需要也不应该在这里手动引入它。 // 你的其他插件可以放在这里 ], })注意你不需要手动在plugins数组中引入dcloudio/vite-plugin-uni。这个核心插件已经由uni-app内部配置提供了。你的配置是在它的基础上进行扩展。接下来你可以通过一个简单的配置来验证文件是否生效。例如配置一个开发服务器选项这在H5模式下会非常直观import { defineConfig } from vite export default defineConfig({ server: { host: 0.0.0.0, // 允许局域网访问方便手机真机调试H5 port: 8080, // 指定端口号 open: true, // 启动后自动打开浏览器仅H5模式有效 // 配置代理解决H5开发跨域问题 proxy: { /api: { target: http://your-backend-api.com, changeOrigin: true, rewrite: (path) path.replace(/^\/api/, ) } } }, })保存后运行npm run dev:h5如果终端显示服务器在http://0.0.0.0:8080启动并且自动打开了浏览器说明你的自定义vite.config.js已经成功被加载并合并了。3. 核心配置项详解与实战案例掌握了配置文件的创建和合并机制后我们就可以深入几个最常用、也最容易出问题的核心配置项了。我将结合具体场景解释每个配置的作用、写法以及需要注意的坑。3.1 路径别名resolve.alias让import语句更简洁在大型项目中经常需要引用src目录下的模块如果每次都写import xxx from ‘../../../components/xxx’不仅难看而且难以维护。路径别名就是为了解决这个问题。配置方法在vite.config.js中我们通过resolve.alias来配置。import { defineConfig } from vite import path from path // 需要引入path模块 export default defineConfig({ resolve: { alias: { // 将 指向 src 目录 : path.resolve(__dirname, src), // 你也可以定义更多的别名比如组件目录 components: path.resolve(__dirname, src/components), utils: path.resolve(__dirname, src/utils), } }, })为什么需要path模块__dirname是Node.js环境下的一个全局变量表示当前文件所在的目录。path.resolve()方法会将路径或路径片段的序列解析为一个绝对路径。这样无论你的项目在什么位置被运行都能正确地指向项目根目录下的src文件夹。配置后的使用方式在Vue文件或JS文件中你可以这样引入// 之前 import HelloWorld from ../../components/HelloWorld.vue import { formatTime } from ../../utils/index.js // 之后 import HelloWorld from /components/HelloWorld.vue import { formatTime } from utils/index.js // 或者如果你配置了components import HelloWorld from components/HelloWorld.vue重要提示仅仅在vite.config.js中配置别名只对Vite构建过程开发服务器和打包生效。它不会自动让你的代码编辑器如VSCode识别这些别名并提供智能跳转和路径补全。为了让编辑器也认识你还需要在项目根目录的jsconfig.jsonVue 3 JS项目或tsconfig.jsonVue 3 TS项目中进行同样的配置。jsconfig.json示例{ compilerOptions: { baseUrl: ., paths: { /*: [./src/*], components/*: [./src/components/*] } }, exclude: [node_modules, dist, unpackage] }完成这两步配置后你才能获得完美的开发体验既能在构建时正确解析模块也能在编码时享受编辑器的智能提示。3.2 环境变量与模式define, envDir, mode环境变量是区分开发、测试、生产环境的关键。Vite通过.env文件和环境变量来管理。1. 环境文件.env在项目根目录下你可以创建以下文件.env所有模式下都会加载。.env.development仅在开发模式npm run dev:*下加载。.env.production仅在生产模式npm run build:*下加载。.env.[mode]对应特定模式。文件内容以键值的形式定义VITE_APP_TITLE我的跨端应用 VITE_API_BASE_URLhttps://dev-api.example.com2. 在Vite配置中使用环境变量你可以在vite.config.js中读取环境变量并动态调整配置。注意vite.config.js是在Node.js环境中运行的因此你使用process.env来读取。import { defineConfig, loadEnv } from vite import uni from dcloudio/vite-plugin-uni export default defineConfig(({ mode }) { // loadEnv会读取指定模式下的.env文件并合并process.env // 第三个参数‘’表示从项目根目录开始查找 const env loadEnv(mode, process.cwd(), ) console.log(当前模式, mode) console.log(API地址, env.VITE_API_BASE_URL) return { // 将环境变量注入到客户端代码中 define: { // 注意这里注入的值需要是字符串形式或者用JSON.stringify转换 __APP_VERSION__: JSON.stringify(1.0.0), // 注入环境变量这样在客户端代码中就可以使用 import.meta.env.VITE_APP_TITLE // Vite默认会处理以 VITE_ 开头的变量所以通常不需要在这里手动定义。 // 这里只是演示define的用法。 }, // 可以基于环境变量动态配置 server: { proxy: mode development ? { /api: { target: env.VITE_API_BASE_URL || http://localhost:3000, changeOrigin: true, } } : undefined } } })3. 在客户端代码中使用在Vue组件或JS文件中你可以通过import.meta.env对象访问以VITE_为前缀的环境变量。// 在setup语法糖或Composition API中 const apiBaseUrl import.meta.env.VITE_API_BASE_URL const appTitle import.meta.env.VITE_APP_TITLE console.log(应用标题${appTitle}) // 输出我的跨端应用踩坑点define配置项用于定义全局常量这些常量会在构建时被静态替换。你定义的值必须是字符串或可JSON序列化的值。如果你错误地传入了一个对象引用可能会导致替换失败或运行时错误。另外请注意区分构建时环境变量在vite.config.js中用process.env访问和客户端环境变量在浏览器/小程序中用import.meta.env访问它们是不同的。3.3 插件plugins扩展构建能力插件是Vite生态的灵魂。uni-app已经内置了许多必要的插件如编译Vue、处理小程序特定语法等。我们自定义插件主要是为了引入额外的功能。一个实战案例自动导入Vue API和组件手动导入refcomputedonMounted等Composition API很繁琐。unplugin-auto-import插件可以帮你自动导入。首先安装插件npm i -D unplugin-auto-import然后在vite.config.js中配置import { defineConfig } from vite import AutoImport from unplugin-auto-import/vite export default defineConfig({ plugins: [ // 配置自动导入 AutoImport({ imports: [ vue, uni-app, // 自动导入 uni-app 的 API如 uni.showToast, uni.request 等 // 你可以继续添加其他库比如 pinia ], dts: true, // 生成自动导入的类型声明文件如果是TypeScript项目 eslintrc: { // 生成eslint配置避免eslint报错 enabled: true, }, }), ], })配置完成后你就可以在.vue文件中直接使用Vue的API而无需手动导入script setup // 不再需要 import { ref, onMounted } from vue const count ref(0) // 直接使用 ref const double computed(() count.value * 2) // 直接使用 computed onMounted(() { // 直接使用 onMounted console.log(组件挂载了) }) /script插件会自动在文件顶部为你添加这些导入语句在构建阶段处理你的源代码不会改变。首次运行后它会在项目根目录生成一个auto-imports.d.ts文件用于TypeScript类型提示和一个.eslintrc-auto-import.json文件用于ESLint配置。你需要将这个JSON文件引入到你的ESLint配置中。另一个实用插件按需引入UI库样式以使用unocss或windicss为例但更常见的是处理类似Naive UI这样的组件库。虽然uni-app的UI库如uView通常有专门的Vite插件或Easycom组件但了解通用方法有益。这里以在H5端使用Vant为例需注意小程序兼容性npm i vant npm i -D vite-plugin-style-importimport { defineConfig } from vite import styleImport from vite-plugin-style-import export default defineConfig({ plugins: [ styleImport({ libs: [ { libraryName: vant, esModule: true, resolveStyle: (name) vant/es/${name}/style, }, ], }), ], })插件顺序很重要Vite插件的执行是有顺序的。某些插件如转换CSS的插件需要在其他插件之后执行。如果你发现插件不生效检查一下它在plugins数组中的位置。dcloudio/vite-plugin-uni作为核心插件通常应该放在最前面虽然uni-app内部已处理而你的自定义插件紧随其后。如果插件提供enforce选项如‘pre’或‘post’Vite会根据它来调整顺序。4. 多平台配置与条件编译uni-app的核心价值在于一套代码多端发布。但不同平台小程序、H5、App的构建需求差异巨大。Vite配置如何应对这种差异这里有两种主要策略。策略一在配置内部进行条件判断你可以通过process.env.UNI_PLATFORM这个uni-app注入的环境变量来获取当前的编译平台。import { defineConfig } from vite export default defineConfig(({ mode }) { const platform process.env.UNI_PLATFORM // 例如mp-weixin, h5, app-plus const config { // 公共配置 resolve: { /* ... */ }, // 平台特定配置 } if (platform h5) { // 仅H5平台需要的配置 config.server { host: 0.0.0.0, proxy: { /* ... */ } } // H5可能不需要某些小程序特定的polyfill // config.optimizeDeps.exclude [some-mp-only-polyfill] } if (platform.startsWith(mp-)) { // 所有小程序平台的公共配置 // 例如可以配置一些针对小程序体积优化的选项 config.build { ...config.build, minify: terser, terserOptions: { compress: { drop_console: mode production, // 生产环境移除console } } } } if (platform app-plus) { // App平台的特定配置可能涉及原生插件或更复杂的构建 // 注意App平台配置更为复杂可能涉及 manifest.json 和 nativeplugins } return config })这种方法将不同平台的配置集中在一个文件里通过条件分支进行管理。优点是结构集中缺点是当平台差异很大时文件会变得冗长。策略二使用多个配置文件这是一种更清晰、更模块化的方式。你可以创建vite.config.js基础公共配置。vite.config.mp.js小程序专用配置。vite.config.h5.jsH5专用配置。然后在package.json的脚本中通过--config选项指定使用的配置文件。// package.json { scripts: { dev:h5: uni -p h5 --config vite.config.h5.js, build:h5: uni build -p h5 --config vite.config.h5.js, dev:mp-weixin: uni -p mp-weixin --config vite.config.mp.js, build:mp-weixin: uni build -p mp-weixin --config vite.config.mp.js } }在vite.config.h5.js中你可以这样写// vite.config.h5.js import { defineConfig, mergeConfig } from vite import baseConfig from ./vite.config.js // 导入公共配置 export default defineConfig( mergeConfig(baseConfig, { // 合并公共配置和H5特定配置 server: { host: 0.0.0.0, port: 3000, proxy: { /api: { target: http://localhost:8080, changeOrigin: true, } } }, build: { // H5特有的构建选项比如配置base路径 assetsDir: static, } }) )在vite.config.mp.js中// vite.config.mp.js import { defineConfig, mergeConfig } from vite import baseConfig from ./vite.config.js export default defineConfig( mergeConfig(baseConfig, { build: { // 小程序特有的构建优化 minify: terser, terserOptions: { compress: { drop_console: true, drop_debugger: true, } }, // 可以配置rollup选项针对小程序包进行分块策略调整如果需要 rollupOptions: { output: { manualChunks: undefined, // 小程序通常不需要代码分割 } } }, // 可能不需要某些H5专用的插件 // plugins: [ /* 仅小程序需要的插件 */ ] }) )这种方式的优点是配置分离职责清晰便于维护。缺点是需要在package.json中为每个平台命令都加上--config参数。条件编译的注意事项除了构建配置的条件化代码本身的条件编译#ifdef H5、#ifdef MP-WEIXIN是由uni-app的编译器在更早的阶段处理的与Vite配置无关。Vite配置的条件化主要用于处理构建行为和开发服务器行为的差异。5. 高级优化与排坑指南当你熟悉了基础配置后可能会追求更极致的开发体验和构建性能。这一部分分享一些高级优化技巧和常见的“坑”及其解决方案。5.1 依赖预构建优化Vite通过optimizeDeps配置项来优化依赖预构建。这对于改善大型项目的冷启动速度非常关键。export default defineConfig({ optimizeDeps: { // 强制预构建某些包即使它们已经是ESM格式 include: [lodash-es, axios], // 排除某些包不进行预构建通常用于兼容性有问题的包 exclude: [some-broken-npm-package], // 一个实用的技巧如果你在开发时动态添加了新的依赖但Vite没有自动重新预构建可以强制刷新 // 或者直接删除 node_modules/.vite 目录重启dev服务器。 }, })一个常见问题有时引入一个较大的第三方库后H5开发服务器启动变慢或者控制台出现一堆请求。这很可能是因为这个库包含很多深层导入deep imports没有被Vite正确预构建。将其添加到include数组中通常可以解决。5.2 构建配置优化生产环境构建的配置直接影响最终包的体积和性能。export default defineConfig({ build: { // 生成静态资源的存放目录相对于dist assetsDir: static, // 小于此阈值的图片或文件将内联为 base64 URL减少HTTP请求 assetsInlineLimit: 4096, // 4kb // 代码压缩配置 minify: terser, // 或 esbuild更快但压缩率略低 terserOptions: { compress: { drop_console: true, // 生产环境移除所有console.* drop_debugger: true, pure_funcs: [console.log, console.info], // 也可以指定移除特定的console方法 } }, // Rollup打包配置 rollupOptions: { output: { // 对chunk文件命名进行优化 chunkFileNames: static/js/[name]-[hash].js, entryFileNames: static/js/[name]-[hash].js, assetFileNames: static/[ext]/[name]-[hash].[ext], // 手动分块策略对于H5项目优化首屏加载很有用 manualChunks(id) { if (id.includes(node_modules)) { // 将node_modules中的大依赖包单独分块 if (id.includes(lodash)) { return vendor-lodash } if (id.includes(axios)) { return vendor-axios } // 其余node_modules打包到vendor中 return vendor } } } }, // 构建后是否生成 sourcemap 文件 sourcemap: process.env.NODE_ENV ! production, // 生产环境不生成sourcemap }, })特别注意小程序构建上述rollupOptions.output.manualChunks配置主要适用于H5端。对于小程序平台由于其包体积限制和运行环境特殊性通常不建议进行代码分割code splitting因为小程序包需要整体上传。在小程序配置中你通常会将manualChunks设为undefined或者不配置此项让所有代码打成一个包。5.3 常见问题与解决方案问题1配置了别名但VSCode依然报错“找不到模块”。原因Vite配置的别名只对构建工具生效编辑器需要单独的配置来理解这些别名。解决确保项目根目录存在正确的jsconfig.json或tsconfig.json文件并且其中的compilerOptions.paths配置与vite.config.js中的resolve.alias保持一致。配置完成后重启VSCode或重新打开项目。问题2引入某个第三方库后H5开发正常但小程序编译报错。原因该库可能使用了小程序环境不支持的API如window、document或模块系统。解决检查库的兼容性优先寻找标明了支持小程序或uni-app的库。使用条件编译仅在H5端引入该库。// 在需要使用该库的文件中 // #ifdef H5 import SomeLib from some-browser-only-lib // #endif配置构建排除在小程序构建配置中通过build.rollupOptions.external将该库标记为外部依赖如果它确实不需要打包进小程序。// vite.config.mp.js export default defineConfig({ build: { rollupOptions: { external: [some-browser-only-lib] } } })寻找替代库这是最根本的解决方案。问题3修改了vite.config.js但开发服务器没有生效。原因Vite不会自动重启服务器来应用配置文件的变化部分配置如server.proxy是例外支持热更新。解决手动停止并重新运行开发命令npm run dev:*。问题4生产构建后H5页面的资源路径错误404。原因项目可能部署在非根路径如https://example.com/my-app/但构建时未配置base公共路径。解决在vite.config.js中根据环境变量配置base。export default defineConfig({ base: process.env.NODE_ENV production ? /my-app/ : /, // 假设部署在 /my-app/ 子目录下 })问题5使用unplugin-auto-import等插件后ESLint报错“未定义变量”。原因ESLint不知道这些变量已被自动导入。解决确保按照插件文档生成了对应的ESLint配置文件如.eslintrc-auto-import.json并在你的主ESLint配置文件中如.eslintrc.js通过extends引入它。// .eslintrc.js module.exports { extends: [ // ... 其他扩展 ./.eslintrc-auto-import.json, // 添加这一行 ], }配置Vite是一个持续学习和调优的过程。最好的建议是从简单的需求开始每次只添加一个配置项或插件并充分测试其在不同平台下的效果。多查阅Vite官方文档和uni-app官方插件源码理解其工作原理这样当你遇到问题时才能更快地定位到根源。
返回列表