Vite

665 阅读5分钟

本文原创:lideguang

图片 1.png 某乎有一个问题“2021前端会有什么新的变化?”,其中 Vue 的作者尤雨溪给出的答案:“会有很多人抛弃 Webpack 开始用 Vite”。下面来看一下为什要抛弃 Webpack、使用 Vite。

Vite

图片 2.png

Vite 是一种新型的前端构建工具,最初是配合 Vue 3.0 使用,后面适配了常见的前端项目,提供了 Vue、react、preact 等模板。官网首页列举了 Vite 的特性:快速的启动、热重载、支持常见资源类型、支持多页/ 类库 开发、通用、类型化API。

在进入 Vite 实操前,我们来看下 被 Vite 革命 的 Webpack。

Webpack 对比 Vite

图片 3.png

Webpack 一直以来和前端工程化紧密联系在一起,优化前端开发体验。这张图是描述 Webpack 功能最直观的一张图,从入口进入,寻找各种依赖资源,经由 Webpack 打包,生成静态资源提供网页展示。

但是使用 Webpack 有一个绕不过去的问题,就是伴随着项目体积增大、代码增长而来的性能问题:项目启动的速度、加载的性能、打包的速度、热重载的及时性等。

图片 4.png

以 Webpack 为代表的模块打包工具,开发时启动本地服务器会从项目入口依次抓取依赖关系,对整个项目文件进行打包,这就造成了启动服务慢; 开发过程中也 HMR 热更新也存在同样问题,Webpack 的热更新服务会以当前修改文件为入口,重新 build,所有依赖也会被重新加载一次,导致热更新也就快不起来。

图片 5.png

Vite 让浏览器接管了打包程序的部分工作,仅启动一台静态资源服务器。资源在这里被分为了两类:

  • 依赖
    • 依赖为外部组件库,多为纯js,开发中不需要变动;
    • 这部分使用 esbuild 进行预编译,将组件库的代码从原本的 commonjs 或者 umd 转换为 esm;
  • 源码
    • 项目代码等;
    • 加载时处理;

Vite 服务 只需要在浏览器请求源码时,进行转换并按需提供源码,只有当前页面依赖使用的资源才会处理,实现了真按需加载;同样在热更新时,也仅编译变更部分的文件,同时结合浏览器的缓存机制,使用 协商缓存,进一步提升重载的速度;

通过这种设计思路,Vite 解决了 打包工具 启动慢、更新慢的问题;

Vite Demo

下面我们通过一个例子来感受下 Vite 的速度,按照下方的命令提示,我们可以使用 Vite 搭建一个 vue 3.0 的项目

提示:这里 node 版本要求 >= 12.0.0

图片 6.png

启动项目后,控制台可以看到两个 warn :

warn.png

Snipaste_2021-03-28_19-27-14.png

这里解释一下:script setup 是 vue 在 RFC 里提交的一份 REF 语法糖的提案,主要作用是:

  • 自动暴露顶级变量,减少代码冗余度
  • 通过 ref: 语法让 ref 更高效

这个提案也在社区引起来不小的争议,看下代码中,哪里用到了 setup,这两个组件中使用了,将这里的变量暴露出来,使得 template 可以直接使用,如果大家存在洁癖的话,可以找到代码中的 script setup 进行改写,避免warn 提示。

这样我们就创建了一个 vue 3 的项目,通过这部分模板生成的代码,我们也可以看到一些 vue 3 不同于 vue2 的部分特性:

├── index.html
├── package.json
├── public
│   └── favicon.ico
├── src
│   ├── App.vue
│   ├── assets
│   │   └── logo.png
│   ├── components
│   │   └── HelloWorld.vue
│   └── main.js
└── Vite.config.js

先从入口文件看:

// src/main.js
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

vue 3 不再使用 new vue。在之前版本中,使用 new vue 全局会共享一个全局配置,比如做测试、或者三方监控引入时,很容易相互污染覆盖,且无法直接还原。vue 3 增加了 createAPP 这个 api,调用 createApp 会返回一个应用实例,全局范围影响 Vue 行为的 api 都会迁移到应用实例中,避免污染覆盖。当然,如果需要多实例共享的 全局配置,可以通过 工厂函数包装的形式来实现:

import { createApp } from 'vue'
import Foo from './Foo.vue'
import Bar from './Bar.vue'

const createMyApp = options => {
  const app = createApp(options)
  app.directive('focus' /* ... */)

  return app
}

createMyApp(Foo).mount('#foo')
createMyApp(Bar).mount('#bar')

再看HelloWorld.vue:

// src/components/HelloWorld.vue
<template>
  <h1>{{ msg }}</h1>

  <p>
    <a href="https://Vitejs.dev/guide/features.html" target="_blank">Vite Documentation</a> |
    <a href="https://v3.vuejs.org/" target="_blank">Vue 3 Documentation</a>
  </p>

  <button @click="state.count++">count is: {{ state.count }}</button>
  <p>
    Edit
    <code>components/HelloWorld.vue</code> to test hot module replacement.
  </p>
</template>

组件模板中允许组件有多个根元素,同时 attrs包含classstyle2.0classstyle不属于attrs 包含 class 和 style,2.0 中 class style 不属于 attrs,会应用到组件跟元素,现在可以允许加到任意元素位置,逻辑更加清晰。

支持 JSON、SASS、TS、组件库

Vite 支持 json,并在内部配置了CSS预处理器。对于 JSON 文件可直接引入,css 预处理器只需要安装对应的loader文件,即可。

// JSON 支持
// import the entire object
import json from './example.json'
// import a root field as named exports - helps with treeshaking!
import { field } from './example.json'
# sass 支持
# Vite 内置了对 css 预处理器的支持
npm install sass --save-dev

Vite 默认支持了 ts,而且 vue 3 不同于 vue 2 中依靠 flow 进行类型管理,使用了 ts 进行开发,对 ts 的支持更优雅;

其次看下如何支持 UI 库的使用,vue 在取消 new Vue 后,有了应用实例,UI库的挂载也是要挂载到应用实例上。由于 use 全局 API 在 Vue 3 中不再使用,此方法将停止工作并停止调用 Vue.use() 现在将触发警告。于是,开发者必须在应用程序实例上显式指定使用此插件:

import { createApp } from 'vue'

import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/lib/theme-chalk/index.css'

const app = createApp(App)
app.use(ElementPlus)

app.mount('#app')

最后

Vite 作为工具服务里的一名新同学,浏览器是否支持原生的 ESM 动态导入、崩溃、周边待完善等问题也确实存在。不过在体验下来,Vite 给人呢的感觉是速度真的很快,规避很多复杂配置,真正实现了开箱即用,同时能够和 Roolup 共享插件接口,后续的生态会变得很丰富,快收下尤大的这份礼物吧。

参考:

Vue3 官网文档:v3.cn.vuejs.org/guide/migra…introduction.html

Vite 2 官网:cn.Vitejs.dev/

Vite 2 release note :zhuanlan.zhihu.com/p/351147547

技术胖(Vite 1.x) :jspang.com/detailed?id…

杨村长(备战2021:Vite2项目最佳实践): juejin.cn/post/692491…

Vite2插件开发指南:zhuanlan.zhihu.com/p/351529474