Webpack / Vite

面试
Webpack
Vite

Webpack

前端打包工具,可以将各种资源文件(JS、CSS、图片等)视为模块,并通过 Loader 对这些模块进行处理,最终将它们打包成一个或多个 Bundle。

工作流程

1、解析配置文件

解析 webpack.config.js,获取打包的相关配置信息,如入口文件、输出路径、加载器、插件等。

2、入口文件

根据配置文件中指定的入口文件,递归解析入口文件及其依赖的模块。

3、Loader 处理文件

解析到各个模块时,它会根据配置中的 Loader 对模块进行处理,加载器可以对不同类型的文件进行转换、转译、压缩等操作,以便将它们转换成浏览器可以理解和执行的代码。

4、Plugin 处理文件

插件可以在打包过程的不同阶段对文件内容进行修改、优化、压缩等操作,常见的插件包括代码分割插件、压缩插件、热更新插件等。

5、打包输出

经过加载器和插件的处理后,Webpack 将所有模块打包成一个或多个 Bundle。Bundle 是一个包含所有依赖模块的 JavaScript 文件,可以被浏览器加载和执行。

Loader 和 Plugin 的区别

Loader

处理模块,把非 JavaScript 资源(CSS、TS、图片、字体)转化成模块,以便在程序里 import;

Plugin

处理和构建相关的任务(代码分割、压缩、资源优化、生成 HTML 文件等),它可以在 Webpack 的不同生命周期阶段完成不同的任务;

a. 生成 Service Worker 文件,支持 PWA 应用的离线缓存;

b. 编译结果上传到 CDN;

c. 根据环境变量自动切换配置;

d. 自动化版本号管理;

HMR 热模块替换

在【不刷新】整个页面的情况下,【实时更新】或替换应用的模块,以更新页面;

工作机制

机制:依赖于 Webpack 和 它的开发服务器 之间的通信;开发服务器可以监听到文件的更改,然后重新编译修改过的模块(不是全部),然后通过 WebSocket 连接 向 浏览器 发送更新消息,然后浏览器会使用 HMR API 处理更新;

代码分割

多入口拆分:entry 里设置 - {entry: {app: './src/app.js', admin: './src/admin.js'}}

splitChunks:自动分割公共模块;

动态导入语法(路由):import(/* webpackChunkName: "myChunk" */ './my-module.js')

import 函数(模块):const dynamicModule = import('module')

Tree-shaking

构建过程中,编译器会识别哪些模块和函数、变量被使用,哪些没有被使用;未使用的代码会被标记为死代码,然后从生成的最终代码中删除;

Babel

把 ES6 代码转换为 ES5 代码,让代码在不同浏览器里运行;

工作原理

解析:代码解析成 AST 抽象树;

转换:对 AST 进行遍历,应用各种插件进行语法树转换;

生成:遍历新的 AST 生成代码并输出;

预设和插件

两者的主要功能都是制定代码的转换规则,plugin 更多是一些微观的任务;

1、预设是应用一组预设规则的集合

@babel/preset-env: // 根据目标环境【自动确定】需要的语法和功能转换
@babel/preset-react;// 处理 React 代码,JSX
@babel/typescript;// 处理 ts 代码

2、插件是应用具体的转换插件

@babel/plugin-transform-arrow-functions; // 箭头函数转普通函数
@babel/plugin-transform-runtime; // 提供运行时工具函数,避免在每个编译单元中重复生成相同的帮助函数

Babel 和 Webpack 的协同

下载 babel-loader,@babel-core;

在 .babelrc 里定义 babel 的预设和插件;

在 webpack-config-js 里引入 babel-loader(在 js 的规则对象里 use babel-loader);

Webpack 优化项目

文件优化

代码分割:公共代码提取到单独的包中 - SplitChunksPlugin

压缩去重:移除无用代码,减小体积 - TerserPlugin、MiniCssExtractPlugin

加载优化

懒加载:动态 import;

预加载:preload、prefetch;动态 import 里添加特殊注释;

缓存优化

在输出文件的文件名里使用 hash

编译优化

开启并行压缩,提高构建速度 - parallel-webpack

不经常变动的依赖库单独打包到 dll 文件中,优化构建速度 - DllPlugin

其他

图片压缩、使用 base64 编码 - file-loader、tiny-webpack-plugin;

生产环境开启 cdn;

开启 Gzip 压缩 - gzip-loader;

Vite

原理

利用浏览器对 ES Module 的支持;遇到 import 就发送一个 HTTP 请求去加载文件,然后 Vite 会启动一个服务器拦截这些请求,在后端对项目文件进行处理,再以 ESM 格式返回给浏览器;整个过程中没有对文件进行打包编译,而是当代码执行到模块加载时请求对应的模块文件,实现动态加载;

特点

冷启动:不打包、ESBuild 预构建、速度比 webpack 快;

热更新:基于 ESM;

打包:基于 rollup;