前言:
在浏览器支持 ES 模块之前,JavaScript 并没有提供原生机制让开发者以模块化的方式进行开发。这也正是我们对 “打包” 这个概念熟悉的原因:使用工具抓取、处理并将我们的源码模块串联成可以在浏览器中运行的文件。
打包构建工具演变:
webpack、Rollup 和 Parcel 等,然后到vite,它们极大地改善了前端开发者的开发体验。
需求衍生:
由于JavaScript 代码量也呈指数级增长,包含数千个模块的大型项目相当普遍。
启动开发服务器通常需要很长时间,有时候长达6/7分钟之久,即使使用模块热替换(HMR),文件修改后的效果也需要几秒钟才能在浏览器中刷新出来,极大影响开发体验,需要升级工具。
选择vite理由:
- 原生 ESM 开发服务器,Vite 还通过原生 ESM 导入提供了许多主要用于打包场景的增强功能。
- Vite 通过在一开始将应用中的模块区分为 依赖 和 源码 两类,改进了开发服务器启动时间,Vite 将会使用 esbuild 预构建依赖。esbuild 使用 Go 编写,并且比以 JavaScript (node.js)编写的打包器(webpack)预构建依赖快 10-100 倍。
- Vite 以 原生 ESM 方式提供源码。这实际上是让浏览器接管了打包程序的部分工作:Vite 只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入代码,即只在当前屏幕上实际使用时才会被处理。
- Vite利用 HTTP 头让浏览器进行文件请求时,启用协商缓存来缓存源码模块,而依赖模块请求则进行强缓存,因此一旦被缓存它们将不需要再次请求,大大提高加载速度。
- Vite 附带了一套构建优化的构建命令,开箱即用。
- 支持自定义后端集成。
- Vite 还提供了强大的扩展性,可通过其 插件 API 和 JavaScript API 进行扩展,并提供完整的类型支持。
配置 Vite:
当以命令行方式运行 vite 时,Vite 会自动解析项目根目录下名为 vite.config.js 的配置文件(也支持其他 JS 和 TS 扩展名)。
/**vite.config.js或vite.config.ts**/
//最基础的配置
export default {// 配置选项
}
/**vite.config.js或vite.config.ts**/
//配置智能提示
/** @type {import('vite').UserConfig} */
//defineConfig工具函数,这样不用jsdoc注解也可以获取类型提示
import { defineConfig } from 'vite'
export default defineConfig({// ...
})/**
情景配置:
如果配置文件需要基于(dev/serve 或 build)命令或者不同的 模式 来决定选项,
亦或者是一个 SSR 构建(ssrBuild),则可以选择导出这样一个函数:
**/
export default defineConfig(({ command, mode, ssrBuild }) => {if (command === 'serve') {return {// dev 独有配置}} else {// command === 'build'return {// build 独有配置}}
})/**
异步配置:
如果配置需要调用一个异步函数,也可以转而导出一个异步函数。
这个异步函数也可以通过 defineConfig 传递,以便获得更好的智能提示:
**/
export default defineConfig(async ({ command, mode }) => {const data = await asyncFunction()return {// vite 配置}
})/**
在配置中使用环境变量:
环境变量通常可以从 process.env 获得。
注意 Vite 默认是不加载 .env 文件的,因为这些文件需要在执行完Vite配置后才能确定加载哪一个,
举个例子,root 和 envDir 选项会影响加载行为。
不过当你的确需要时,你可以使用 Vite 导出的 loadEnv 函数来加载指定的 .env 文件。
**/
import { defineConfig, loadEnv } from 'vite'export default defineConfig(({ command, mode }) => {// 根据当前工作目录中的 `mode` 加载 .env 文件// 设置第三个参数为 '' 来加载所有环境变量,而不管是否有 `VITE_` 前缀。const env = loadEnv(mode, process.cwd(), '')return {// vite 配置define: {__APP_ENV__: JSON.stringify(env.APP_ENV),},}
})//共享配置及常用配置,不需要的可以不添加属性,将启用默认配置:
import { defineConfig } from 'vite'
import { viteMockServe } from 'vite-plugin-mock'
const localEnabled = process.env.USE_MOCK || false;
const prodEnabled = process.env.USE_CHUNK_MOCK || false;
export default defineConfig(({ command, mode }) => {return {root: process.cwd(), //默认process.cwd()。tips:项目根目录(index.html 文件所在的位置)。可以是一个绝对路径,或者一个相对于该配置文件本身的相对路径。base: '/', //默认/。合法值:[1.绝对 URL 路径名,例如 /foo/,2.完整的 URL,例如 https://foo.com/,3.空字符串或 ./(用于嵌入形式的开发)]mode: '', //'development' 用于开发,'production' 用于构建define: 'XXX', //Record<string, any>定义全局常量替换方式,其中每项在开发环境下会被定义在全局,而在构建时被静态替换//plugins: 需要用到的插件数组。Falsy 虚值的插件将被忽略,插件数组将被扁平化(flatten)plugins: [ vue(), // vue原生插件viteMockServe({ //引入mock插件配置,tips:mock,模拟真实数据以测试软件功能mockPath: "./src/server/mock", //mock配置数据文件路径localEnabled: localEnabled, // 开发打包开关 true时打开mock false关闭mockprodEnabled: prodEnabled, //prodEnabled, // 生产打包开关// 这样可以控制关闭mock的时候不让mock打包到最终代码内injectCode: `import { setupProdMockServer } from './mockProdServer';setupProdMockServer();`,logger: false, // 是否在控制台显示请求日志supportTs:false // 打开后,可以读取 ts 文件模块 打开后将无法监视 .js 文件})], publicDir: 'public' //作为静态资源服务的文件夹,该值可以是文件系统的绝对路径,也可以是相对于项目根目录的相对路径,设定为 false 关闭此项功能cacheDir: "node_modules/.vite", //默认:node_modules/.vite,存储缓存文件的目录,此目录下会存储预打包的依赖项或 vite 生成的某些缓存文件。此选项的值可以是文件的绝对路径,也可以是以项目根目录为基准的相对路径。当没有检测到 package.json 时,则默认为 .vite。resolve: {alias: [{ find: '@', replacement: resolve(__dirname, 'src') }],// 配置别名,dedupe: '', // 如果你在你的应用程序中有相同依赖的副本(比如 monorepos),请使用此选项强制 Vite 始终将列出的依赖项解析为同一副本(从项目根目录)。conditions: [], //情景导出 package.json 配置中的exports字段mainFields: '', //默认['module', 'jsnext:main', 'jsnext'],如果一个入口点从 exports 成功解析,resolve.mainFields 将被忽略browserField: ''//已废弃extensions: [], //默认['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json'],导入时想要省略的扩展名列表。注意,不 建议忽略自定义导入类型的扩展名(例如:.vue),因为它会影响 IDE 和类型支持。preserveSymlinks: false, //启用此选项会使 Vite 通过原始文件路径(即不跟随符号链接的路径)而不是真正的文件路径(即跟随符号链接后的路径)确定文件身份。},css: {modules: '', // 配置 css modules 的行为preprocessorOptions:{scss: {additionalData:`$injectedColor:orange;` //指定传递给 css 预处理器的选项},less: {math: 'parens-division', //指定传递给 less 预处理器的选项},styl: { //指定传递给 styl/stylus 预处理器的选项define: {$specialColor: new stylus.nodes.RGBA(51, 197, 255, 1),},},},json: {namedExports: true,//是否支持从 .json 文件中进行按名导入stringify: false, //若设置为 true 导入的json会被转为 export default JSON.parse("..") 会比转译成对象字面量性能更好 },//继承自 esbuild 转换选项,最常见的用例是自定义 JSXesbuild: {jsxFactory: "h",jsxFragment: "Fragment",jsxInject:`import Vue from 'vue'`},assetsInclude: ['**/*.gltf'], //静态资源处理logLevel: 'info', //选项:'info' | 'warn' | 'error' | 'silent',调整控制台输出的级别,默认为 'info'/**自定义 logger 记录消息:import { createLogger, defineConfig } from 'vite'const logger = createLogger()const loggerWarn = logger.warnlogger.warn = (msg, options) => {// 忽略空 CSS 文件的警告if (msg.includes('vite:css') && msg.includes(' is empty')) returnloggerWarn(msg, options)}**/customLogger:logger,//自定义 logger 记录消息clearScreen: true, //设为 false 可以避免 Vite 清屏而错过在终端中打印某些关键信息。envDir: 'root'//默认root, //用于加载 .env 文件的目录。可以是一个绝对路径,也可以是相对于项目根的路径。envPrefix: 'VITE_',//默认VITE_,以 envPrefix 开头的环境变量会通过 import.meta.env 暴露在你的客户端源码中appType: 'spa',//默认spa,选项['spa' | 'mpa' | 'custom'], tips: SPA-单页应用, MPA-多页应用,custom- SSR和自定义HTML处理的框架//server:本地运行配置,以及反向代理配置server: {host: "localhost",https: false,//是否启用 http 2cors: true,//为开发服务器配置 CORS , 默认启用并允许任何源open: true,//服务启动时自动在浏览器中打开应用port: "9000",strictPort: false, //设为true时端口被占用则直接退出,不会尝试下一个可用端口force: true,//是否强制依赖预构建hmr: false,//禁用或配置 HMR 连接// 传递给 chockidar 的文件系统监视器选项watch: {ignored:["!**/node_modules/your-package-name/**"]},// 反向代理配置proxy: { '/api': {target: "https://xxxx.com/",changeOrigin: true,rewrite: (path) => path.replace(/^\/api/, '')}}},//打包配置build: {target: "modules", //浏览器兼容性 "esnext"|"modules"outDir: "dist", // 指定输出路径assetsDir: "assets", // 生成静态资源的存放路径assetsInlineLimit: 4096, // 小于此阈值的导入或引用资源将内联为 base64 编码,以避免额外的 http 请求。设置为 0 可以完全禁用此项cssCodeSplit: true, // 启用/禁用 CSS 代码拆分sourcemap: false, // 构建后是否生成 source map 文件rollupOptions: {}, // 自定义底层的 Rollup 打包配置commonjsOptions: {}, // @rollup/plugin-commonjs 插件的选项lib: {}, //构建的库manifest: false, // 当设置为 true,构建后将会生成 manifest.json 文件,设置为 false 可以禁用最小化混淆,,或是用来指定使用哪种混淆器minify: "terser", // boolean | 'terser' | 'esbuild',terser 构建后文件体积更小terserOptions: {}, // 传递给 Terser 的更多 minify 选项。write: true, // 设置为 false 来禁用将构建后的文件写入磁盘emptyOutDir: true, // 默认情况下,若 outDir 在 root 目录下,则 Vite 会在构建时清空该目录。brotliSize: true, // 启用/禁用 brotli 压缩大小报告chunkSizeWarningLimit: 500 // chunk 大小警告的限制ssr: {// 列出的是要为 SSR 强制外部化的依赖,类型:string[]external: [], // 列出的是防止被 SSR 外部化依赖项。类型:string | RegExp | (string | RegExp)[] | truenoExternal: []}
})