1.什么是webpack?
webpack是一个前端的静态模块资源打包工具,能让浏览器也支持模块化。它将根据模块的依赖靠关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。
webpack的作用
- webpack核心主要进行javascript资源打包
- 它可以结合其他插件工具,将多种静态资源css,png,sass分类转换成一个个静态文件,这样可以减少页面的请求
- 可集成babel工具实现es6转es5,解决兼容性问题
- 可集成http服务器
- 可集成模块热加载,当代码改变后自动刷新浏览器等等功能
2.webpack配置有哪些 ?
- entry。指定Webpack打包的入口文件,可以是单个或多个JavaScript文件。这个配置决定了Webpack从哪个模块开始生成依赖关系图。
- output。设置Webpack打包后输出的目录和文件名称,包括path、filename和publicPath等。
- module。配置了不同的loaders来处理不同的模块,例如,对于CSS文件,可以使用css-loader和style-loader。
- resolve。设置Webpack如何解析模块依赖,包括别名、扩展名等。
- plugins。使用不同的插件可以增强Webpack的功能,例如,使用html-webpack-plugin可以将打包后的js文件自动引用到HTML文件中。
- devServer。提供了一个简单的web服务器和实时重载功能,可以通过devServer.contentBase、devServer.port、devServer.proxy等进行配置。
- optimization。可以使用optimization.splitChunks和optimization.runtimeChunk配置代码拆分和运行时代码提取等优化策略。
- externals。用于配置排除打包的模块,例如,可以将jQuery作为外置扩展,避免将其打包到应用程序中。
- devtool。配置source-map类型。
- context。webpack使用的根目录,string类型必须是绝对路径。
- target。指定Webpack编译的目标环境。
- performance。输出文件的性能检查配置。
- noParse。不用解析和处理的模块。
- stats。控制台输出日志控制。
3.有哪些常见的 Loader 和 Plugin?
Loader:
- babel-loader:将ES6+的代码转换成ES5的代码。
- css-loader:解析CSS文件,并处理CSS中的依赖关系。
- style-loader:将CSS代码注入到HTML文档中。
- file-loader:解析文件路径,将文件赋值到输出目录,并返回文件路径。
- url-loader:类似于file-loader,但是可以将小于指定大小的文件转成base64编码的Data URL格式
- sass-loader:将Sass文件编译成CSS文件。
- less-loader:将Less文件编译成CSS文件。
- postcss-loader:自动添加CSS前缀,优化CSS代码等。
- vue-loader:将Vue单文件组件编译成JavaScript代码。
Plugin:
- HtmlWebpackPlugin:生成HTML文件,并自动将打包后的javaScript和CSS文件引入到HTML文件中。
- CleanWebpackPlugin:清除输出目录。
- ExtractTextWebpackPlugin:将CSS代码提取到单独的CSS文件中。
- DefinePlugin:定义全局变量。
- UglifyJsWebpackPlugin:压缩JavaScript代码。
- HotModuleReplacementPlugin:热模块替换,用于在开发环境下实现热更新。
- MiniCssExtractPlugin:与ExtractTextWebpackPlugin类似,将CSS代码提取到单独的CSS文件中。
- BundleAnalyzerPlugin:分析打包后的文件大小和依赖关系。
4.Loader和Plugin的区别
功能不同:
Loader本质是一个函数,它是一个转换器。webpack只能解析原生js文件,对于其他类型文件就需要loade进行转换。Plugin它是一个插件,工作原理是:webpack 通过内部的事件流机制保证了插件的有序性,底层是利用发布订阅模式,webpack 在运行过程中会广播事件,插件只需要监听它所关心的事件,在特定的时机对资源做处理
用法不同:
Loader的配置是在module.rules下进行。类型为数组,每⼀项都是⼀个 Object ,⾥⾯描述了对于什么类型的⽂件( test ),使⽤什么加载( loader )和使⽤的参数( options ) 。Plugin的配置在plugins下。类型为数组,每一项是一个 Plugin 的实例,参数都通过构造函数传入。
5.webpack的构建流程
初始化参数:解析webpack配置参数,合并shell传入和webpack.config.js文件配置的参数,形成最后的配置结果开始编译:上一步得到的参数初始化compiler对象,注册所有配置的插件,插件监听webpack构建生命周期的事件节点,做出相应的反应,执行对象的run方法开始执行编译。确定入口:从配置的entry入口,开始解析文件构建ast语法树,找到依赖,递归下去编译模块:递归中根据文件类型和loader配置,调用所有配置的loader对文件进行转换,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理完成模块编译并输出:递归完事后,得到每个文件结果,包含每个模块以及他们之间的依赖关系,根据entry配置生成代码块chunk输出完成:输出所有的chunk到文件系统
6.Webpack的Tree Shaking原理
Webpack的Tree Shaking是一个利用ES6模块静态结构特性来去除生产环境下不必要代码的优化过程。其工作原理在于:
- 当Webpack分析代码时,它会标记出所有的
import语句和export语句。 - 然后,当Webpack确定某个模块没有被导入时,它会在生成的bundle中排除这个模块的代码。
- 同时,Webpack还会进行递归的
标记清理,以确保所有未使用的依赖项都不会出现在最终的bundle中。
为了启用Tree Shaking,需要在webpack配置文件中添加如下设置:
javascriptmodule.exports = { // ... optimization: { usedExports: true, concatenateModules: true, minimize: true, }, // ...};
确保你使用的是ES6模块语法(即import和export),因为只有这样才能让Tree Shaking发挥作用。
7.热更新原理
什么是 webpack 热更新?
开发过程中,代码发生变动后,webpack 会重新编译,编译后浏览器替换修改的模块,局部更新,无需刷新整个页面 好处:节省开发时间、提升开发体验
热更新原理
主要是通过websocket实现,建立本地服务和浏览器的双向通信。当代码变化,重新编译后,通知浏览器请求更新的模块,替换原有的模块
- 通过webpack-dev-server开启server服务,
本地 server 启动之后,再去启动 websocket 服务,建立本地服务和浏览器的双向通信 - webpack 每次编译后,会生成一个
Hash值,Hash 代表每一次编译的标识。本次输出的 Hash 值会编译新生成的文件标识,被作为下次热更新的标识 - webpack监听文件变化(主要是通过文件的生成时间判断是否有变化),当文件变化后,重新编译
- 编译结束后,通知浏览器
请求变化的资源,同时将新生成的 hash 值传给浏览器,用于下次热更新使用 - 浏览器拿到更新后的模块后,用新模块替换掉旧的模块,从而实现了局部刷新
8.Babel
Babel 是一个用于将新版本ES6+代码转换为向后兼容版本(ES5)代码的JavaScript编译器。它还为JSX语法提供了编译支持,还有一些其他插件可用于转换特定类型的代码 。
作用
babel 主要用于将新版本的代码转换为向后兼容的 js 语法(Polyfill 方式),以便能够运行在各版本的浏览器或其他环境中
Babel 的流程
3 个阶段: parsing (解析)、transforming (转换)、generating (生成)
- 通过babylon将 js 转化成 ast (抽象语法树)
- 通过babel-traverse是一个对 ast 进行遍历,使用 babel 插件转化成新的 ast
- 通过babel-generator将 ast 生成新的 js 代码
9.npm install 的执行过程
npm install 是 Node.js 包管理器 (npm) 的一个命令,用于安装一个项目所依赖的模块。
执行过程大致如下:
- 读取 package.json 文件,该文件列出了项目所需要的依赖。
- 根据 package.json 中的依赖信息以及 node_modules 目录状态,npm 会决定哪些模块需要下载和安装。
- npm 会查看每个模块的可用版本,并选择符合 package.json 中指定版本范围的最新版本进行安装。
- 下载所需模块到本地的 node_modules 目录。
- 如果模块包含子模块(package.json 中 dependencies 或 devDependencies 中的模块),则递归执行上述步骤安装这些子模块。
10.npm run start 的整个过程?
npm run start 是一个常见的命令,用于启动基于 Node.js 的应用程序。这个命令实际上是一个快捷方式,它告诉 npm 运行在 package.json 文件中定义的 start 脚本。
当你执行 npm run start 时,以下是发生的事情:
- 查找当前目录下的 package.json 文件。
- 在 package.json 文件中,找到
scripts对象。 - 在
scripts对象中,找到start键。 - 执行与
start键关联的命令字符串。
11. 什么是Code Splitting
Code Splitting代码分割,是一种优化技术。它允许将一个大的chunk拆分成多个小的chunk,从而实现按需加载,减少初始加载时间,并提高应用程序的性能 。
在Webpack中通过optimization.splitChunks配置项来开启代码分割
12. 如何提高webpack的打包速度
开启持久化缓存(Webpack 5 自带):Webpack 5 内置了文件缓存机制,减少二次构建时间。开启多线程并行编译:Webpack 默认是单线程执行的,可以用thread-loader或parallel-webpack进行多线程处理。使用DllPlugin和HardSourceWebpackPlugin: DllPlugin可以将第三方库预先打包成单独的文件,减少构建时间。HardSourceWebpackPlugin可以缓存中间文件,加速后续构建过程使用 ESBuild/SWC 替代 Babel:Babel 解析速度较慢,ESBuild 比 Babel 快 10~100 倍。SWC 也是一个超快的 JS/TS 编译器,比 Babel 快 20 倍。开启 Babel Loader 缓存:如果仍在使用 Babel,可开启缓存减少重复编译。- 利用
terser-webpack-plugin多线程压缩:Webpack 默认 JS 压缩器terser是单线程的,可以开启多线程加速。 - 使用
cache-loader缓存:cache-loader可以缓存编译结果,提高二次构建速度。 减少构建体积:Tree Shaking(移除无用代码)、CDN 加速(减少vendor.js体积)、Gzip 压缩(减少文件大小)移除不必要的插件: 移除不必要的插件和配置,避免不必要的复杂性和性能开销
13. 如何减少打包后的代码体积
代码分割(Code Splitting):将应用程序的代码划分为多个代码块,按需加载Tree Shaking:配置Webpack的Tree Shaking机制,去除未使用的代码压缩代码:使用工具如UglifyJS或Terser来压缩JavaScript代码使用压缩工具:使用现代的压缩工具,如Brotli和Gzip,来对静态资源进行压缩利用CDN加速:将项目中引用的静态资源路径修改为CDN上的路径,减少图片、字体等静态资源等打包
14. module chunk bundle分别什么意思,有什么区别
在 Webpack 中,module、chunk 和 bundle 是三个核心概念,它们分别代表构建过程中的不同阶段和结构。
定义
- Module(模块)
- 模块是 Webpack 的
基本单位,代表项目中的每个文件,如 JavaScript、CSS、图片、字体等。
- Chunk(代码块)
- Chunk 是 Webpack 在构建过程中生成的代码块,由多个模块组成。
- Webpack 会根据入口文件和动态引入的模块,创建多个 Chunk。
- 每个 Chunk 通常对应一个或多个最终生成的文件。
- Bundle(最终文件)
- Bundle 是 Webpack 最终生成的打包文件,包含了构建后的代码和资源。
- 通常是
.js、.css或其他静态资源文件。 - 文件名可以通过
output.filename自定义。
关系和构建过程
-
从 Module 到 Chunk:
- Webpack 根据依赖关系,将多个模块分组,生成一个或多个 Chunk。
- 例如,多个模块(
moduleA.js、moduleB.js)可能会被打包到同一个 Chunk 中。
-
从 Chunk 到 Bundle:
- 每个 Chunk 会被进一步处理,最终输出为 Bundle 文件(如
main.js)。 - 动态加载的模块可能会生成独立的 Bundle 文件。
- 每个 Chunk 会被进一步处理,最终输出为 Bundle 文件(如
15. Vite
原理
- Vite 利用浏览器支持原生的
es module模块,开发时跳过打包的过程,提升编译效率 - 当通过 import 加载资源时,浏览器会发出 HTTP 请求对应的文件,Vite拦截到该请求,返回对应的模块文件
Vite 的限制
Vite 主要对应的场景是开发模式(生产模式是用 rollup 打包)
16.Vite 热更新速度
Vite 热更新的速度不会随着模块增多而变慢
Webpack 的热更新原理:一旦某个依赖(比如上面的 a.js)改变,就将这个依赖所处的 整个module 更新,并将新的 module 发送给浏览器重新执行
试想如果依赖越来越多,就算只修改一个文件,热更新的速度会越来越慢
Vite 的热更新原理:如果 a.js 发生了改变,只会重新编译这个文件 a,而其余文件都无需重新编译
所以理论上 Vite 热更新的速度不会随着文件增加而变慢