什么是构建工具?
- typescript: 如果遇到ts文件我们需要使用tsc将typescript代码转换为js代码
- React/vue: 浏览器只认识html、css、js文件,想要识别,就需要安装react-compiler/vue-compiler,将我们写的jsx文件或者.vue文件转换为render函数
- less/sass/postcss/component-style: 我们需要安装less-loader\sass-loader等一系列编译工具
- 语法降级:babel-->将es的新语法转换为旧版浏览器可以接受的语法
- 体积优化: 一些代码的空格部分可以直接删除,uglify.js-->将我们的代码进行压缩变成提及更小性能更小的文件
如果没有编译工具,我们稍微改点东西,就会非常麻烦,App.tsx-->tsc-->App.jsx--->React-compiler-->js文件,有一个东西可以帮我们把tsc,react-compiler,less,babel,uglifyjs全部集成到一起,我们只需要关心代码就可以了,这个东西就叫构建工具。
构建工具所做的工作
- 模块化开发支持: 支持直接从node_modules里引入代码+多种模块化支持(esmodule+commonjs+...)
- 处理代码兼容性: 比如babel语法降级,less,ts语法转换(不是构建工具做的,构建工具将这些语法对应的处理工具集成进来自动化处理)
- 提高项目性能: 压缩文件,代码分割
- 优化开发经验:
--构建工具会帮你自动监听文件的变化,当文件变化以后自动帮你调用对应的集成工具进行重新打包,然后浏览器重新运行(整个过程叫做热更新,hot replacement)
--开发服务器:跨域的问题,用react-cli、create-react-element 、vue-cli解决跨域的问题
vite相对于webpack的优势
- 起因: 我们的项目越大--》构建工具(webpack)所要处理的js代码就越多【跟webpack的一个构建流程(工作流程)有关系,webpack支持多种模块化,他一开始必须要统一模块化代码,所以意味着他需要将所有的依赖全部读一遍】
- 造成的后果: 构建工具需要很长时间才能启动开发服务器(启动开发服务器--》把项目跑起来)
- vite是首先启动开发服务器,根据配置的入口开始按需加载,访问到哪个页面就加载对应的页面,没有访问的不加载。
// webpack支持多种模块化
const lodash = require(‘lodash‘) //commonjs规范
import Vue from 'vue'; // es6 module
// webpack编译之后
(function(modules){
function webpack_require(){};
modules[entry](webpack_require);
}, ({
'./src/index.js': (webpack_require) => {
const lodash = webpack_require('lodash');
const Vue = webpack_require('vue');
}
}))
vite的依赖预构建
vite在处理过程中,如果看到了有非绝对路径或者相对路径的引用,他会开启路径补全,找寻依赖的过程是当前目录依次向上寻找的过程,直到搜寻到根目录或者搜寻到对应依赖为止。
import _ from lodash;
// vite编译后
import __vite__cjsImport3_lodash from "/node_modules/.vite/deps/lodash.js?v=a2931a3d";
项目中可能会存在多种规范的导出,例如esmodule规范的导出module.exports,有的包它是以commonjs的导出例如axios;
依赖预构建:首先vite会找到对应的依赖,然后调用esbuild(对js语法进行处理的一个库),将其他规范的代码转换成esmodule规范,然后放到当前目录下的node_modules/.vite/deps,同时对esmodule规范的各个模块进行统一集成 他解决了三个问题:
- 不同的第三方包会有不同的导出格式(这个是vite没法约束的事情)
- 对路径的处理上可以直接使用.vite/deps,方便路径重写
- 叫做网络多包传输的性能问题(也是原生esmodule规范不敢支持node_modules的原因之一),有了依赖预构建以后无论他有多少的export和import,vite都会尽可能的将他们集成最后只生成一个或几个模块。
vite的环境变量配置
在vite中的环境变量处理:vite内置了dotenv这个第三方库,dotenv会自动读取.env文件,并解析这个文件中的对应环境变量,将其注入到proccess对象下(但是vite考虑到和其他配置的一些冲突问题,他不会直接注入到process对象下,需要我们手动调用loadEnv来确认env文件)
// 根据运行命令传入的参数 获取mode
export default defineConfig(({command, mode}) => {
console.log(process.cwd(), mode);
const env = loadEnv(mode, process.cwd(), '');
console.log('env', env);
// 此时服务端就会获取到env变量,即包含.env文件的变量数据
// 客户端可以直接在js文件中读取import.meta.env获取环境变量(命名需要使用VITE_开头才有用)
return {
plugins: [vue()],
};
})
补充一个小知识: vite.config.js是在node端运行的,node端都是commonjs规范,我们没有开commonjs规范,为什么vite.config.js可以书写成esmodule的形式?因为vite在读取vite.config.js的时候会率先node去解析文件语法,如果发现你是esmodule规范会直接将你的esmodule规范进行替换变成commonjs规范。(node端读出来是字符串,然后使用repalce替换所有的import、export全部换成module.export)