Vite学习|青训营笔记

127 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第11天。

前端工程痛点

  1. 模块化

    • 提供模块加载方案
    • 兼容不同模块的规范
  2. 资源编译

    浏览器的速度赶不上我们前端一些语言一些特性的速度,所以就需要进行编译

    • 对于高级语法转译:less/scss/typescript
    • 资源加载等:图片,字体等
  3. 产物质量

    • 关于一些dead code的删除等,语法降级等
  4. 开发效率

    热更新

Vite概览

新一代的前端构建工具

大部分的浏览器都支持ESM

浏览器原生ESM支持

<!DOCTYPE html>
<html>
    <head>
        <title>tset</title>
    </head>
    <body>
        <script type="mode">
        	import {foo} from './foo.js'
        	console.log(foo)
        </script>
    </body>
</html>
export const foo = "foo"

两大要素

  • script标签添加type="module"
  • 使用ESM模块导入导出语法

优势

  • 无需打包项目源代码
  • 天然的就支持按需加载
  • 可以利用文件级的浏览器缓存
sequenceDiagram
    浏览器->>Vite Dev Server: 请求/src/main.tsx
    Vite Dev Server->>浏览器: 编译文件内容,将数据返回给浏览器

内置的web构建功能

Vite开箱即用的功能等价于

  • webpack
  • css-loader
  • style-loader
  • less-loader
  • HTMLWebpackPlugin
  • ....

Vite使用

//安装pnpm
npm i pnpm
//执行初始化命令
pnpm create vite
//安装依赖
pnpm install
//启动项目
npm run dev

使用Sass/Scss& CSS Modules

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

使用静态资源

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

参考链接:功能 | Vite 官方中文文档 (vitejs.dev)

使用HMR

无需配置,自动开启即可

生成环境Tree Shaking(树摇)

Tree shaking 在vite里面无需配置,默认开启

优化原理:

  • 基于ESMimport/export语句依赖关系,与运行时状态无关
  • 在构建阶段将未使用的代码进行删除

Vite整体架构

为什么要进行预打包

  • 避免node-modules过多文件请求
  • CommonJs格式转换为ESM格式

实现原理

  • 服务启动前扫描代码中用到的依赖
  • Esbuild对依赖代码进行预打包
  • 改写import指定依赖为与构建产物路径
//改写前
import React from 'react'
//改写后
import React from '/node_modules/.vite/react.js'

单文件编译

Esbuild编译TS/JS

优势:

  • 编译速度大大提升

劣势

  • 不支持类型检查
  • 不支持ES5,可能有些兼容性不好的浏览器不兼容

代码压缩

使用minify

 build: {
      terserOptions: {
        compress: {
          drop_console: true,
          drop_debugger: true,
        },
      },
      minify: "terser",
 }

参考链接:构建选项 | Vite 官方中文文档 (vitejs.dev)

插件机制

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

Vite进阶路线

深入双引擎

  • ESbuild
  • Rollup.js

插件机制

示例

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
                }
            }
        }
    }
}

使用插件

vite.config.js里面声明插件

import plugin from './myPlugin'
export default defineConfig({
plugins:[plugin()]
})

代码分割

出现原因:

  • 无法进行并发请求
  • 缓存复用率低

我们将一个入口文件差分为几个,当我们需要改变A组件的时候,那么只有A组件对应的文件进行更改

Babel

出现的原因

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

语法安全降级

  • 上层解决方案:@vite/plugin-legacy
  • 底层原理
    • 借助Babel进行语法自动降级
    • 提前注入Polyfill,如core.js