写在前头:这篇文章只是我个人在学习过程中对webpack文档的简单总结,更多详细信息请在官网阅读。
一、webpack是什么
webpack 是一个用于现代 JavaScript 应用程序的静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容。
静态打包工具:主要是指那些能够将多个JavaScript模块以及其他类型的静态资源(如CSS、图片、字体等)进行处理、转换、合并和优化,最终输出适合浏览器加载和执行的静态资源文件的工具。
二、为什么要使用webpack
1.在没有打包工具时面临的问题
-
手工合并与压缩: 开发者需要手动将多个JavaScript文件合并成一个或几个大的文件,进行压缩,减少文件大小。CSS文件同样需要手动合并并使用CSS压缩工具进行优化。
-
依赖管理: 早期并没有成熟的模块化解决方案,大部分项目基于全局命名空间来管理依赖,或者使用如RequireJS这样的库来实现异步模块加载(AMD)。这种方式下,每个模块都需要手动指定其依赖关系,并且无法享受到现代模块化带来的诸多便利。
-
资源引用: 图片、字体等静态资源一般直接通过HTML标签进行引用,大量的HTTP请求会降低页面加载速度。为了改善这种情况,开发者可能会手动将小图片合并为雪碧图(CSS Sprite),或者使用CDN加速资源加载。
-
工作流复杂: 没有自动化工具的支持,开发流程中的构建、测试、发布等环节相对繁琐,容易出错且耗时较长。
2.webpack做了什么解决问题
-
模块化管理:
- Webpack 支持 CommonJS、AMD 和 ES6 模块规范,允许开发者按照模块化的方式组织项目结构,使得代码更具可维护性和可复用性。
- 它能解析项目中的模块依赖关系,形成一个依赖图谱,确保各个模块按正确顺序加载和执行。
-
资源打包:
- Webpack 可以将项目中的所有 JavaScript、CSS、图片、字体等静态资源打包成一个或多个bundle文件,减少HTTP请求的数量,从而加快网页加载速度。
- 支持代码分割和动态导入,允许异步加载模块,仅在需要时加载相应代码,优化首屏加载速度。
-
转换和编译:
- Webpack 通过Loader机制处理非JavaScript资源,如将ES6/7+/TypeScript代码转换为浏览器可识别的语法,将SCSS/Less等预处理器编写的样式转换为CSS,将React/Vue等模板文件转换为JS模块等。
-
优化与压缩:
- 提供多种优化策略,如Tree Shaking去除无用代码,UglifyJsPlugin或TerserPlugin压缩代码,SourceMap便于调试,SplitChunksPlugin提取公共代码等。
- 支持资源指纹(hashing),避免客户端缓存问题。
-
插件系统与扩展性:
- Webpack有大量的内置插件和第三方插件,可以进行更高级别的构建定制,如HtmlWebpackPlugin生成HTML文件,CleanWebpackPlugin清理输出目录,CopyWebpackPlugin复制静态资源等。
三、核心概念
1.入口起点(entry points)
Webpack 的入口起点(entry point)是构建依赖图的起始位置。在 Webpack 中,入口起点是指定 Webpack 开始构建应用内部依赖关系图的初始模块。当你定义了一个或多个入口起点后(通常一个HTML文档一个起点),Webpack 会从这些起点出发,递归地解析并追踪所有直接和间接依赖的模块。这一过程最终将形成一个完整的依赖关系图(dependency graph),Webpack 将根据这个依赖图将所有模块打包成一个或多个 bundle 文件,以便在浏览器中高效加载和运行。
例如使用vue-cli搭建的vue项目的src目录下的main.js就是一个单页面应用的打包起点。
2.输出(output)
Webpack 的输出(Output)配置允许您定义编译后的资源(通常是捆绑包/bundle)如何命名、存储以及它们最终在硬盘上的位置。即通过配置打包成你想要的样子。
例如使用vue-cli搭建的vue项目中使用run build打包命令后生成的dist文件夹。
3.加载器(loader)
webpack中,loader的主要作用是对非JavaScript文件进行转换,使webpack能够处理它们。因为webpack默认只能处理JavaScript模块,所以当我们需要打包其他类型的文件(如CSS、图片、TypeScript、SCSS、LESS等)时,就需要使用相应的loader来预处理这些文件。
例如在使用vue-cli搭建的vue项目中的package-lock.json文件中,我们可以看到babel-loader(ES6+转ES5),ts-loader,css-loader等等。
4.plugin(插件)
Webpack 的插件(Plugin)是一种强大的工具,它们允许开发者深入到 Webpack 构建流程的核心,执行编译和打包之外的更多高级任务。Webpack 的构建过程由一系列有序的事件组成,而插件则可以通过监听这些事件并在适当的时机执行相应的操作来扩展和定制构建流程。
例如:HotModuleReplacementPlugin(启动热更新),DllPlugin(拆分 bundles,从而大幅减少构建时间)。
5.模块(Moudules)
在模块化编程中,开发者将程序分解为功能离散的 chunk,并称之为 模块。项目中的每个文件都是一个模块。
6.依赖图
每当一个文件依赖另一个文件时,webpack 都会将文件视为直接存在 依赖关系。这使得 webpack 可以获取非代码资源,如 images 或 web 字体等。并会把它们作为 依赖 提供给应用程序。
Webpack从命令行或配置文件中定义的一个或多个入口点(entry point)开始,递归地分析这些入口点所依赖的其他模块。它会遍历整个项目的文件结构,找到所有相关的依赖项,并将它们组织成一个依赖图。Webpack的依赖图是其实现模块打包和优化的关键机制。
7.模块热替换(hot module replacement)
Webpack的模块热替换(Hot Module Replacement,简称HMR)是webpack提供的一个强大特性,它允许在运行时更新各种模块,而无需进行完全刷新。这极大地提升了开发效率,尤其是在开发复杂的单页面应用(SPA)时。
当源文件发生变化时,webpack会重新构建模块,并与浏览器之间建立一个WebSocket连接。通过这个连接,webpack将新的模块发送到浏览器端,浏览器端接收到新的模块后,通过HMR runtime来替换掉旧的模块。在这个过程中,当前页面的状态会被保留,比如页面的滚动位置、已输入的内容等都不会丢失。
四、总结
webpack通过模块化管理,构建一个模块依赖图,进行代码分割和支持动态导入(import)让模块可以按需加载;将代码进行转换和编译,让浏览器能识别;webpack对代码进行压缩和优化,提升加载速度;提供了模块热替换,为开发提高了效率和使用体验。
参考文档
webpack