Vite知识体系

一、浅谈构建工具

1、前端工程的痛点

(1)前端项目的组成部分(核心要素--文件资源)

①逻辑代码:js、ts、jsx

②样式代码:css、scss、less

③静态资源:jpg、png、webp

(2)四个方向的归纳

①模块化:ESM、CommonJS、UMD

把项目拆分为不同的模块,然后进行分别的开发和维护【分而治之】

②资源编译:高级语法的编译

高级语法浏览器是不认识的,所以需要编译成浏览器可以识别的形式

③产物质量:代码体积、代码性能

  • 体积:线上的代码一般都比较大,容易影响性能和用户体验,需要压缩,将未使用到的模块在构建产物当中剔除掉,优化产物体积
  • 兼容性:对于需要兼容移动端的项目,大部分情况需要兼容到安卓4.4、ios9(也就是需要兼容低端的浏览器,否则容易出现使用的高级语法,浏览器无法识别,出现白屏事故) ④开发效率:热更新

2、前端构建工具的意义

(1)模块化方案

①提供模块加载方案

②兼容不同模块规范

(2)语法转译

①高级语法转译,如Sass、TypeScript

②资源加载,如图片、字体、worker

(3)产物质量

产物压缩、无用代码删除、语法降级

(4)开发效率

热更新

二、Vite概要介绍

1、Vite概览

(1)定位:新一代前端构建工具

(2)两大组成部分

①No-bundle开发服务(NodeJs的devserver),源文件无需打包 (与传统工具最大的不同)

②生产环境基于Rollup的Bundler,将所有代码进行打包

(3)核心特征

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

②简单易用,开发者体验好

2、业界案例

(1)Rollup -> Vite

  • 启动时间:2分15秒->1.7秒
  • 更新时间:23秒->1秒以内

(2)Webpack -> Vite

  • 启动时间:2分36秒->6秒
  • 热更新:13秒->1秒以内

3、当下问题

(1)开发体验问题

缓慢的启动->项目编译等待成本高

缓慢的热更新->修改代码后不能实时更新

(2)瓶颈

bundle打包带来的性能开销

JavaScript语言的性能瓶颈

4、两大行业趋势

(1)全球浏览器对原生ESM的普遍支持(目前占比92%以上)

(2)基于原生语言(Go、Rust)编写前端编译工具链

如Go语言编写的Esbuild、Rust 编写的SWC

5、浏览器原生ESM支持

(1)两大要素

  • script标签增加type="module"属性
  • ESM模块导入导出语法

(2)代码例子

浏览器在识别到import后,会发起请求,到foo.js下执行内容

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test esm</title>
</head>
<body>
    <script type="module">
        import { foo } from './foo.js'
        console.log(foo);
    </script>
</body>
</html>
javascript 复制代码
export const foo = "foo";

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

(1)无需打包项目源代码

(2)天然的按需加载

(3)可以利用文件级的浏览器缓存

当一个文件变更时,不会导致整个bundle失效,只会导致当前的请求缓存失效,达到更细密度的浏览器缓存

7、基于Esbuild的编译性能优化

(1)Esbuild:基于Golang开发的前端工具,具备如下能力

①打包器Bundler:对应webpack的工作

②编译器Transformer

③压缩器Minifier

(2)性能极高,在Vite 中被深度使用

8、内置的web构建能力

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

(2)可以看出:vite是对常见web开发的需求进行一个封装

三、Vite上手实战

1、项目初始化

(1)安装pnpm

javascript 复制代码
#提前安装 pnpm
npm i -g pnpm
#初始化命令
pnpm create vite
#安装依赖
pnpm install
#启动项目
pnpm run dev

2、使用Sass/Scss & CSS Modules

(1)安装sass

javascript 复制代码
pnpm install sass -D

(2)例子

①新建组件:文件夹下=》新建component文件夹=》新建Header文件夹=》新建index.tsx文件

②编写index.tsx文件

javascript 复制代码
import React from "react";

export function Header(){
    return <div>Header</div>
}

③在App.tsx文件引入,使用

javascript 复制代码
import { Header } from './components/Header'
// 在App()中使用
<Header></Header>

(3)叠加sass、css-module,编写样式

①Header文件夹下=》新建index.module.scss

vite会默认把.module.scss文件当作css-module

css 复制代码
.header {
  color: red;
}

②在index.tsx中引入、使用

javascript 复制代码
import React from "react";
import styles from "./index.module.scss";

export function Header() {
  return <div className={styles.header}>Header</div>;
}

③css-module作用

className的值并不是字符串,而是引入一个json字段,而这个字段变成了_header_gxlcr_1,由header+哈希值

这样的好处就是,当在其它组件用了同样的className,会出现不同组件的样式污染,使用css-module可以做到组件的样式隔离

3、使用静态资源

(1)静态资源在vite可以直接引入使用

这个路径会给vite的devserver发起svg请求,然后devserver会把文件内容返回给浏览器,进行图片的呈现

(2)除了常见的图片格式, Vite也内置了对于JSON、Worker、WASM资源的加载支持 官方文档

4、HMR

可以保存组件的局部状态

当改变index下的内容时,App下的count值会保留

5、生产环境Tree Shaking

(1)把代码中没有的内容删除

(2)优化原理

①基于ESM 的import/export语句依赖关系(依赖关系是可以静态确定的),与运行时状态无关

相对于NodeJs的规范就不能,因为require可能是运行时的结果,就无法进行一些静态分析,当需要强制删除时,可能会删掉一些不应该删掉的内容,是有风险的

因此Tree Shaking只能应用于ESM

②在构建阶段将未使用到的代码进行删除

③Tree Shaking在Vite中无需配置,默认开启

(3)代码例子

javascript 复制代码
//main.ts
import { add } from './util';
console.log(add(1,2));
javascript 复制代码
//util.ts
export const add = (a: number, b: number): number => a + b;
export const multi = (a: number, b: number): number => a * b;

在util.ts中编写了两个方法add(),multi(),在main.ts使用时,只使用了add()方法,则在最后打包的产物中不会有multi()

(4)实践操作 ①在src文件夹下=》新建util.ts文件

javascript 复制代码
export const add = (a: number, b: number): number => a + b;
export const multi = (a: number, b: number): number => a * b;

②在index.tsx文件引入,使用

javascript 复制代码
import React from "react";
import styles from "./index.module.scss";
import { add } from "../../util";
export function Header() {
  return <div className={styles.header}>Header{add(1, 2)}</div>;
}

(5)调试观察

①停止项目,查看package.json中的build,发现会先进行tsc的编译,就是进行相关类型的检查,然后编译vite build

②在vite.config.js中

在生产环境,会默认进行压缩,这边要调试,暂时将压缩的功能关闭

javascript 复制代码
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  // 关闭压缩功能
  build: {
    minify: false,
  }
})

③进行生产环境的打包

javascript 复制代码
pnpm run build

④查看打包产物dist文件夹下的文件

通过图片中的文件搜索,可以找到add被打包进去,而multi是没有的

(6)总结

Vite最直观的印象就是

①响应迅速

②开箱即用

四、Vite整体架构

1、开发环境下的依赖预打包

(1)node_modules

①非常不可控,一个依赖文件往往会有很多其它延伸的依赖文件

②代码产物的格式是不规范的,有可能是CommonJS,在浏览器上无法运行

因此vite进行依赖预打包

(2)预打包步骤

①在dev服务启动前,扫描代码中用到的依赖

②对依赖代码采用Esbuild进行预打包

③打包完,将业务中的import语句进行改写,指定依赖为预构建产物路径

javascript 复制代码
// 改写前
import React from "react";
// 改写后
import React from "/node_modules/.vite/react.js";

2、单文件编译

(1)用Esbuild编译TS/JSX

(2)Esbuild优势:编译速度提升10-100倍

(3)Esbuild局限性

①不支持类型检查

②不支持语法降级到ES5

3、代码压缩

(1)生产环境中非常重要的阶段,同时是非常耗时的阶段

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

4、插件机制

(1) 开发阶段->模拟Rollup 插件机制 生产环境->直接使用Rollup

(2)注意:并不是所有的rollup插件都能兼容vite
vite官网之插件兼容性https://vite-rollup-plugins.patak.dev/

五、Vite进阶路线

1、深入双引擎

vite底层非常依赖的两个构建引擎

(1)官方文档

Esbuildhttps://esbuild.github.io/

Rolluphttps://rollupjs.org/

(2)推荐学习顺序

①先了解基本使用,动手尝试各项常用配置

②然后学习其插件开发

2、插件开发

(1)为什么需要插件开发

①抽离核心逻辑,将devserver中server端的能力抽离出来,把构建相关的能力封装为一个个的插件,达到解耦的效果,构建和devserver逻辑是分开的,更容易维护的

②易于拓展,社区能够给vite贡献一些插件

(2)一些vite插件的钩子函数

在不同阶段,插入自定义的逻辑

(3)插件示例

①开发vite插件

②配置文件,引入插件

javascript 复制代码
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
        }
      }
    }
  }
}
javascript 复制代码
// vite.config.js
import plugin from './myPlugin'

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

(4)插件开发参考资料

vite官方开发文档

②复杂度较低的插件:json加载插件

③复杂度中等的插件:Esbuild接入插件

④复杂度较高的插件:官方React插件

先看文档,过一遍插件钩子的功能然后多学习其它插件的实现,掌握套路

3、代码分割(拆包)

(1)问题

①无法进行并发请求:以前的启动过程只产出一个bundle,即一个产物文件

②缓存复用率低:当一个文件改动,整个产物全部失效

(2)拆包

意味着改动某一个文件,不影响整个产物,达到更好的缓存复用的效果,从而提升页面加载速度,间接提升用户体验

(3)配置rollup的代码分割

构建选项

Configuration Oprions

4、JS编译工具(Babel)

(1)出现原因

①JavaScript语法标准繁多,浏览器支持程度不一

②开发者需要用到高级语法

(2)参考资料
babel官方站点https://babeljs.io/docs/
babel插件手册https://github.com/jamiebuilds/babel-handbook/blob/master/translations/zh-Hans/plugin-handbook.md

(3)Babel实现原理

Parse:将代码解析成AST(抽象语法树),每个单词都是语法树的节点

Transform:AST转换成一些低级语法的AST

Generator:生成器,将低级语法的AST转换成代码

从而达到语法降级的效果

5、语法安全降级

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

IE11没有内置Promise语法,很可能会导致代码报错,浏览器页面白屏

(2)解决方案

①上层解决方案:@vitejs/plugin-legacy

②底层原理

  • 借助Babel进行语法自动降级
  • 提前注入Polyfill实现,如core-js、regenerator-runtime

(3)参考资料
@babel/preset-env文档https://babeljs.io/docs/babel-preset-env
Vite官方降级插件文档https://github.com/vitejs/vite/tree/main/packages/plugin-legacy

6、服务端渲染(SSR)

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

(1)构建阶段

(2)代码执行阶段

(3)参考资料

Vite-SSR文档

使用Vite搭建SSR工程

7、深入了解底层标准

(1)重点特性

CS规范、ESM规范、HTTP 2.0特性

(2)参考资料

HACKShttps://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/

ESM & CJShttps://antfu.me/posts/publish-esm-and-cjs

8、社区生态

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

(2)官方提供插件

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

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

@vitejs/plugin-react,提供 React支持

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

(3)海量社区插件
github.com/vitejs/awes...https://github.com/vitejs/awesome-vite

(4)vite框架内置

Nuxt、SvelteKit、Astro、Vitepress

六、总结

1、通过本节学习,认识vite的基础原理,实现简单操作,同时建立了从基础学习到进阶学习的方向 2、本节印象最深的是生产环境Tree Shaking 在大型项目代码构建下,属于关键的一步,学习了Tree Shaking原理步骤,对项目构建也有很大帮助

相关推荐
Lysun0018 分钟前
[less] Operation on an invalid type
前端·vue·less·sass·scss
J总裁的小芒果23 分钟前
Vue3 el-table 默认选中 传入的数组
前端·javascript·elementui·typescript
二进制_博客25 分钟前
Flink学习连载文章4-flink中的各种转换操作
大数据·学习·flink
Lei_zhen9626 分钟前
记录一次electron-builder报错ENOENT: no such file or directory, rename xxxx的问题
前端·javascript·electron
咖喱鱼蛋28 分钟前
Electron一些概念理解
前端·javascript·electron
yqcoder29 分钟前
Vue3 + Vite + Electron + TS 项目构建
前端·javascript·vue.js
鑫宝Code1 小时前
【React】React Router:深入理解前端路由的工作原理
前端·react.js·前端框架
codebolt1 小时前
ADS学习记录
学习
Komorebi.py2 小时前
【Linux】-学习笔记05
linux·笔记·学习
Mr_Xuhhh2 小时前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法