构建工具->vite

101 阅读3分钟

最近一周都在维护公司的老旧项目,在这些老旧项目之中,发现不仅代码冗余需要花费非常多的时间和精力,就连webpack打包启动服务,热更新也需要等待很长时间,迟钝的反馈让人十分难受。决定用市面上构建速度比较快的vite重新构建一下老旧项目,并记录下vite(构建工具)相关的一些知识点,注意事项。

前期准备

本记录中的代码都运行在以下的框架中:

  1. 利用vite创建一个vue3+ts的基础框架。
  2. 配置了一个webpack.config.js对比vite打包。
  3. 在根目录下创建了一个A.js。

什么是构建工具

// A.js
export default 11
// index.html
<script type="module">
import a from './A.js'
import _ from 'lodash'
import './src/main.ts'
</script>
// main.ts
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
createApp(App).mount('#app')

上面的代码如果不采用第三方构建工具加载index.html到浏览器中,会报错,理由如下:

  1. import a from './A.js' 没有问题,浏览器支持esm
  2. import _ from 'lodash' 有问题, esm可以加载 但是不是正确的路径,lodash在node_modules中
  3. import './src/main.ts'有问题,浏览器不认识ts,里面的vue也不认识

如果利用构建工具vite加载上面的代码,便不会有问题,理由如下:

  1. vite可以处理模块加载的问题,不仅是node_modules中的包,esm,commonjs都可以处理
  2. vite可以处理ts,vue,甚至react等文件

简而言之,构建工具就是集成了很多功能的一个工具,比如webpack,vite等,常见的功能如下:

  1. 统一模块化支持esm,commonjs,node_module的引用等
  2. less,sass,babel,vue,react,ts等支持
  3. 一些资源文件的支持json,png等
  4. 充当开发服务器
  5. 生产环境构建
  6. 运行在node.js环境中,解析代码为浏览器中可以运行的代码

vite和webpack的对比

// main.ts
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
const a = require('../A.js').a

createApp(App).mount('#app')
  1. vite是基于esm的,代码只支持esm规范,更加关注浏览器端的体验 所以利用vite启动的时候上面的代码main.ts会报错,不认识require
  2. webpack 支持浏览器端也支持服务端的编译 代码支持esm也支持commonjs,所以上面的代码webpack不会报错
  3. vite远远比webpack启动开发服务器快,这是因为webpack一开始就会去分析所有依赖,项目越大,分析越慢。
    而Vite不会,只会分析首屏的依赖。

vite的依赖预构建和源码加载

esm在浏览器中加载的方式:

// main.ts
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import a from '../A.js'

console.log(a)
createApp(App).mount('#app')

加载A.js,App.vue,vue.js的方式都是http请求的方式。

依赖预构建的作用

  1. vite的依赖预构建是为了兼容项目依赖的一些不同规范,比如一些依赖是commonJS的规范,或者AMD的规范,这就需要统一为esm的规范
  2. 由于项目的依赖又会去依赖其他的包,这样预构建统一为esm之后,会出现很多的http请求,所以esbuild预构建的第二个作用是重写依赖,直接项目依赖的其他包重写到项目依赖中。
// main.ts
import { createApp } from 'vue'
import _ from 'lodash-es'
import './style.css'
import App from './App.vue'
import a from '../A.js'

console.log(_)
console.log(a)
createApp(App).mount('#app')
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  optimizeDeps: {
    exclude: ['lodash-es'] // lodash-es不采取依赖预构建
  }
})

Snipaste_2022-11-29_21-36-58.png 上面的图就展示了如果不采取依赖预构建将会出现非常多的http请求,全是获取lodash-es的包的请求。

源码加载

vite首先以esm的方式,向浏览器提供源码,这样减少了打包程序的部分。vite只需要在浏览器请求源码的时候对源码进行转换,动态导入源码。
比如下面的main.ts

// main.ts
import { createApp } from 'vue'
import _ from 'lodash-es'
import './style.css'
import App from './App.vue'
import a from '../A.js'

console.log(_)
console.log(a)
createApp(App).mount('#app')

会被转化为

import {createApp} from "/node_modules/.vite/deps/vue.js?v=db6c9304";
import _ from "/node_modules/.vite/deps/lodash-es.js?v=db6c9304";
import "/src/style.css";
import App from "/src/App.vue";
import a from "/A.js";
console.log(_);
console.log(a);
createApp(App).mount("#app");