vite构建工具
文章目录
- 1. 什么是构建工具
- 2. webpack的缺点在哪?
- 3. 区分vite脚手架和vite
- 5. vite预加载
- 5.1 包的加载
- 5.2. vite依赖预构建
- 7. vite配置文件处理
- 8. vite环境变量和模式
- 8.1 环境变量
- 8.2 模式
1. 什么是构建工具
在开发项目中,我们可能会使用到vue
、react
等框架,less
、sass
等预处理工具,以及其他的一些提升开发效率的工具。
但浏览器只认html
、css
、javascript
三件套,其他的工具语言都必须通过编译 / 转译或者打包处理成浏览器理解的格式。
下面是一些工具语言需要的处理:
less
/sass
/ … —> less-loader / sass-loader编译工具;typescript
—> 使用tsc转换成javascript;vue
/react
—> vue-compiler / react-copiler 将.vue文件或者.jsx文件转换成render函数;语法降级
—> babel:将es新语法转换成旧版浏览器可以理解的语法体积优化
—> uglifyjs:将代码压缩成体积更小性能更高的问价;- …
使用一种工具就需要做相应的处理,这很麻烦。而构建工具会将这些工作全部揽下,极大地提高了开发效率。
那构建工具具体承担了哪些工作呢?
- 模块化开发支持:支持从node_modules中直接引入代码 + 多种模块化支持;
- 处理代码的兼容性:例如babel语法降级,less、ts语法转换(❗️注意:这里的语法转换不是构建工具做的,构建工具只是将处理这些语法的工具集成起来了);
- 提高项目性能:压缩文件,提高性能;
- 优化开发体验
- 构建工自动监听文件变化,文件变化,那么构建工具也会调用相应的集成工具处理,然后重新打包运行(和这个过程也叫做热更新—>无需刷新整个页面就可以更新)
- 开发服务器:跨域的问题,用react-cli create-react-element vue-cli
解决跨域的问题
市面上主流构建工具:
- webpack
- vite
- …
2. webpack的缺点在哪?
webpack
允许我们这么写:
const lodash = require("lodash") // commonJS
import Vue from 'vue' // es moudule
webpack
的编译原理:
- 通过AST抽象语法树分析的工具,分析出所写js文件的的导入和导出操作
- 构建工具运行在服务端
因为webpack
支持多种模块化,所以在打包时必须要先统一模块化代码,所以意味着需要读取所有的导入导出,而在项目越来越大时,webpack
的弊端也就越明显。
开发阶段:
比较方面 | vite | webpack |
---|---|---|
启动速度 | ⚡️快 | 🐢慢 |
模块热更新(HMR) | 快且颗粒度小,更新只影响更新模块 | 慢,编译时间长 |
原因 | 利用原生es module,模块按需加载 | 支持多模块化使用,编译时需要获取所有导入导出,统一模块化 |
注:vite
不需要打包,直接用浏览器加载原始模块文件(借助ES Module 和exbuild
的预编译)
构建阶段:
比较方面 | vite | webpack |
---|---|---|
构建速度 | ⚡️快(esbuild 编译快) | 🐢慢(依赖于JS编写的打包器) |
打包结果体积 | 通常更小,Tree-shaking 更彻底 | 体积更大 |
支持静态资源优化 | 默认支持 | 需要配置插件 |
vite
构建使用 rollup
,且使用esbuild
做预编译
vite
更快、更现代、更贴近浏览器原生特性,适合大多数现代 Web 项目;webpack
功能更强大但配置繁琐,适合对构建过程精细控制的大型项目。
3. 区分vite脚手架和vite
创建项目时,输入npm craete vue@latest
- 会全局安装一个东西:
create-vite
(vite的脚手架); - 并且直接运行
create-vite
bin目录下的一个执行配置
我们可能存在一个误区:
使用npm craete vue@latest
构建项目是vite在做的事情!
但是其实跟 vue-cli
类似,webpack
是内置在其中的;vite
内置在vite-craete
中
5. vite预加载
5.1 包的加载
在没有使用vite的情况下,我们使用es module
规范去引入一个工具包,那么在运行时就会报错,因为原生js不接受非绝对路径文件或者非相对路径文件的引入。
(因为这些包都是由浏览器发送请求获取得到,都是在客户端进行的,使用es module
引入依赖可能会涉及到很多文件的引入,会非常消耗浏览器性能,所以浏览器不会自动在node_modules中寻找依赖。也是原生es module
不敢支持node_modules的原因之一)
而在使用了vite
之后,对于非绝对路径文件或者非相对路径文件的引入,vite
会尝试开启路径补全。
在使用了vite
的项目中,public
文件夹以外使用commonJS
语法规范,这些依赖的引入会在服务端进行,这样就大大优化了浏览器性能。
寻找依赖的过程是从当前文件向上层文件寻找的过程,直到寻找到根目录或者找到目标依赖位置。
5.2. vite依赖预构建
项目开发中,我们会下载很多的工具包,这些工具包可能会使用不同的模块化规范,比如
- commonJS
- lodash
- express
- es module
- axios(ESM版本)
- uuid
- vue@3
在运行或打包项目时总是要先统一规范,这是就需要使用到依赖预构建
:
首先vite
会先找到依赖,接着通过esbuild
处理,将不同规范的工具包通通转换成es module
规范,放在node_modules/.vite/deps
路径下。
以上方面说明了vite
预构建的几个优点:
- 统一工具包的规范,方便项目构建和运行;
- 对路径的处理可以直接使用
.vite/deps
,方便路径重写; - 解决了网络多包传递的问题(也是上面我们所说的消耗浏览器性能的一个地方)
当然,不想进行依赖预构建的话,vite
也给我们提供了关闭预构建的方式:
vite.config.js:
export default {optimizeDeps: {exclude: ["lodash-es"], // 告诉vite排除对lodash-es的依赖}
}
7. vite配置文件处理
import { defineConfig } from "vite"
import BaseViteConfig from "./vite.base.config"
import DevViteConfig from "./vite.dev.config"
import ProdViteConfig from "./vite.prod.config"const EnvViteConfig = {// 生产环境"build": ({ ...BaseViteConfig, ...ProdViteConfig }),// 开发环境"serve": () => Object.assign({}, BaseViteConfig, DevViteConfig),
}export default defineConfig((command) => {// command: build | serve 只有这两种命令return EnvViteConfig[command]
})
8. vite环境变量和模式
8.1 环境变量
环境变量:会根据当前代码环境产生值的变化的变量就叫做环境变量。
代码环境:
- 开发环境
- 测试环境
- 预发布环境
- 灰度环境
- 生产环境
vite
在一个特殊对象import.meta.env
上暴露环境变量。下面是这个对象的几个内置变量:
import.meta.env.MODE
:{string} 应用运行时的模式;import.meta.env.BASE_URL
:{string} 部署应用时的基本URL(BASE_URL也可以替换成其他的名称,主要看自己怎么定义变量名称);- import.meta.env.PROD:{boolean} 应用是否运行在生产环境;
- import.meta.env.DEV:{boolean} 应用是否运行在开发环境;
- import.meta.env.SSR:{boolean} 应用是否运行在server上;
vite
中的环境变量是怎样进行处理的呢?
vite
中集成了第三方库dotenv
,它会自动读取.env
中的环境变量,并将其注入到process
对象下。
这些变量在生产环境时都将被静态替换,因此,在引用它们时请使用完全静态的字符串。动态的 key 将无法生效。例如,动态 key 取值 import.meta.env[key] 是无效的。
补充知识:为什么
vite.config.js
中可以书写esmodule规范?
因为vite在读取vite.config.js
文件时,率先使用node去解析文件语法,如果发现时esmodule
语法就会直接将esmodule
语法替换成commonJS
规范。
8.2 模式
vite
使用dotenv
从你的环境目录中的下列文件加载额外的环境变量:
.env
# 所有情况下都会加载.env.local
# 所有情况下都会加载,但会被 git 忽略.env.[mode]
# 只在指定模式下加载.env.[mode].local
# 只在指定模式下加载,但会被 git 忽略
这些文件在启动项目时加载,中间修改需要重启服务。
执行npm run dev
运行在development
(开发)模式,npm run build
运行在production
(生产)模式,相应的,也会执行对应模式下的.env
文件。