打包工具之Vite | 青训营笔记

289 阅读5分钟

这是我参与第四届青训营笔记创作活动的第十四天

Vite意在提供开箱即用的配置,同时它的插件API和JavaScriptAPI 带来了高度的可扩展性,并有完整的类型支持。那让我们一起学习一下吧。

为什么需要构建工具

首先我们先讨论一下“为什么需要构建工具”这个话题。先讲一下前端工程的痛点,前端工程的核心要素是资源,比如js,ts,jsx,css,scss,less,png,jpeg,webp等等,在这种情况下,我们会遇到一些关于模块化、资源编译、产物质量以及开发效率的问题,而这就是前端构建工具的意义所在。具体如下图:

image.png

vite是什么

他是新一代前端构建工具,由两大组成部分:No-bundle 开发服务,源文件无需打包;生产环境基于 Rollup 的 Bundler。

核心特征:

1.高性能,dev 启动速度和热更新速度非常快!

2.简单易用,开发者体验好

vite的优势

基于原生ESM 的开发服务优势

vite无需打包项目源代码,是天然的按需加载,可以利用文件级的浏览器缓存。如图所示

image.png

基于Esbuild的编译性能优化

这是几种工具的编译性能统计图:

image.png

相信里面的Esbuild编译性能格外引人瞩目,它是基于 Golang 开发的前端工具,同时具备如下能力:

1.打包器 Bundler

2.编译器 Transformer

3.压缩器 Minifier

性能极高,在 Vite 中被深度使用 !!

内置的WEB构建能力

Vite 开箱即用的功能等价于webpack、webpack-dev-server、css-loader、style-loader、less-loader、sass-loader、postcss-loader、file-loader、MiniCssExtractPlugin、HTMLWebpackPlugin...

我们可以大致看一下webpack和vite做到同种配置的区别

  • webpack.config.ts image.png

  • vite.config.ts image.png


使用vite

项目初始化

//提前安装pnpm
npm i -g pnpm
//初始化命令
pnpm create vite
//安装依赖
pnmp install
//启动项目
npm run dev

输入初始化参数 image.png 启定后截图 image.png 启动完成后,打开浏览器访问对应地址即可

使用Sass/Scss & CSS Modules

假如目录结构是这样的

image.png

第一步:安装 Sass

pnpm i sass -d

第二步:使用模块

index.tsx

import styles from './index.module.scss';
// 使用 CSS Modules 模块化方案,防止 className 命名冲突
export function Header() {
    return <p className={styles.header}>This is Header</p >
};

index.module.scss

.header {
    color: red;
}

第三步:引入APP.tsx

import { Header } from "./components/Header";
function App() { 
    return(<div><Header /></div>);
    }
export default App;

使用静态资源

假如目录结构是这样的

image.png

以svg为例: App.tsx

import { Header } from "./components/Header"; 
import logourl from './logo.svg';
function App() {
   return (
        <div>
            <Header />
            <img src={logourl} alt="" />
        </div>);
}
export default App;

处理常见的图片格式,vite也内置了对于JSON、Worker、WASM的加载支持

使用HMR

无需额外配置,自动开启

生产环境Tree Shaking

无需额外配置,自动开启。

不过要注意的点是 image.png

vite整体架构

image.png

vite有几个关键技术:

依赖预打包

image.png 那为什么要进行预打包呢?原因是为避免 node_modules 过多的文件请求以及将 CommonJS 格式转换为 ESM 格式

实现原理是服务启动前扫描代码中用到的依赖,然后用 Esbuild 对依赖代码进行预打包,最后改写 import 语句,指定依赖为预构建产物路径

单文件编译

用Esbuild编译TS/JSX

image.png

优势是编译速度提升 10-100 x,但是也有局限性,它不支持类型检查,也不支持语法降级到 ES5。

代码压缩

image.png

Esbuild作为默认压缩工具,替换传统的Terser,Uglify.js等压缩工具

压缩性能对比如图所示

image.png

插件机制

image.png

开发阶段会模拟Rollup插件机制,生产环境是使用Rollup。

插件兼容性具体可查阅:vite-rollup-plugins.patak.dev/

vite进阶

可以深入双引擎esbuild和rollup.js,先了解基本使用,动手尝试各项常用配置,然后再学习其插件开发,学习过程中可以参考他们两个的官方文档。

为什么需要插件机制呢?其实在webpack中也有讲过?也就是它可以抽离核心逻辑且易于拓展。

先看一下各个阶段的钩子组成

image.png

通过图中的Hook,我们可以在不同的构建阶段插入自定义的逻辑。比如这个示例:

const fileRegex = /\.(my-file-ext)$/

export default function myPlugin() {
return {
    name:'transform-file'

    transform(src, id){
        if (fileRegex.test(id)) {
        return {
            code: compileFileToJS(src),
            map: null // 如果可行将提供 source map
            }
        }
    }
}

然后就可以配置文件引入插件啦!

// vite.config.js
import plugin from './myPlugin'

export default defineConfig({
    plugins: [plugin()]
})

代码分割

image.png

拆包前无法进行并发操作,且缓存复用率低。

js编译工具(Babel)

Babel原理 image.png

它出现的原因是:

  • js语法标准繁多,浏览器支持程度不一
  • 开发者需要用到高级语法

参考资料:

babel官方站点

babel插件手册

语法安全降级

以Promise语法为例,IE11没有支持

image.png

会出现这种报错 image.png

如何在构建产物中避免这类问题?vite的上层解决方案是用@vitejs/plugin-legacy,底层原理是 借助 Babel 进行语法自动降级,提前注入 Polyfill 实现,如 core-js、regenerator-runtime。

参考资料:

@babel/preset-env文档

Vite官方降级插件文档

服务端渲染(SSR)

一种常见的渲染模式,用于提升首屏性能和SEO优化

image.png

Vite 社区生态

1、 Github 40k+ star (可参考 webpack 61.3 Krollup 21.8 k),并且目前还在持续维护

2、官方提供插件:

@vitejs/plugin-vue,提供 Vue 3 支持

@vitejs/plugin-vue-jsx,提供 Vue 3 JSX 支持@vitejs/plugin-react,提供 React 支持

@vitejs/plugin-legacy,提供低版本浏览器降级支持

3、海量社区插件github.com/vitejs/awes…

4、众多框架内置:Nuxt、SvelteKit、Astro、Vitepress

至此,关于Vite的就介绍到这里,因为刚接触就没法很细致的讲,最后的最后,谢谢大家这么厉害还来看我,如果发现问题或者需要补充的点麻烦大家通过评论告诉我。博取众长,共同进步!