构建Webpack知识体系
Webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。它主要用于将项目中的所有依赖项(包括 JavaScript 文件、图片、CSS 等)打包成一个或多个 bundle,这些 bundle 可以被浏览器加载和执行。
为什么要学习Webpack?
- 理解前端“工程化”概念、工具、目标
- 一个团队总要有那么几个人熟悉Webpack,某种程度上可以成为个人的核心竞争力
- 高阶前端必经之路
什么是Webpack
-
前端项目由资源构成
-
手动管理资源的问题
- 依赖手工,比如有50个JS文件 ... 操作,过程繁琐
- 当代码文件之间有依赖的时候,就得严格按依赖顺序书写
- 开发与生产环境一致,难以接入TS或JS新特性
- 比较难接入 Less、Sass 等工具
- JS、图片、CSS资源管理模型不一致
-
对开发效率影响非常大,直到出现了很多工程化工具,其中就有Webpack
Webpack
本质上是一种前端资源编译、打包工具
- 多份资源文件打包成一个 Bundle
- 支持 Babel、Eslint、TS、CoffeScript、Less、Sass
- 支持模块化处理 css、图片 等资源文件
- 支持 HMR+开发服务器
- 支持持续监听、持续构建
- 支持代码分离
- 支持 Tree-shaking
- 支持 Source map
- ...
使用Webpack
示例
-
安装
-
编辑配置文件:webpack.config.js
const path = require('path') module.exports = { entry: './src/index',//定义当前项目的入口 mode: "development", devtool: false, output: {//定义项目打包完之后放在哪里 出口 filename: '[name].js', path: path.join(_dirname, './dist') } } -
执行编译命令
把资源编译成产物
核心流程
-
entry--入口处理- 从entry文件开始,启动编译流程
-
require/import--依赖解析- 从entry文件开始,根据require or import 等语句找到依赖资源
-
module--资源解析- 根据module配置,调用资源转移器,将png、css 等非标准JS资源转译为JS内容
-
output--资源合并打包- 将转译后的资源内容合并打包为可直接在浏览器运行的JS文件
- 递归调用2、3,直到所有资源处理完毕
模块化+一致性
- 多个文件资源合并成一个,减少 http 请求数
- 支持模块化开发
- 支持高级 JS 特性
- 支持 Typescript、CoffeeScript 方言
- 统一图片、CSS、字体 等其它资源的处理模型
- ...
配置
关于 Webpack 的使用方法,基本都围绕“配置”展开,而这些配置大致可划分为两类:
-
流程类:作用于流程中某个 or 若干个环节,直接影响打包效果的配置项
-
输入
- entry
- context
-
模块解析
- resolve
- externals
-
模块转译
- module
-
后处理
- optimization
- mode
- target
-
-
工具类:主流程之外,提供更多工程化能力的置项
-
开发效率类
- watch
- devtool
- devServer
-
性能优化类
- cache
- performance
-
日志类
- stats
- infrastructureLogging
-
-
其他
- amd
- bail
-
参考资料
常用
-
entry/output
- entry(入口):指定Webpack的入口文件,告诉Webpack从哪个文件开始打包。可以是一个字符串、字符串数组或对象。
- output(输出):定义了打包后的文件输出到哪里,以及输出文件的名称。通常包含
path(输出路径)和filename(输出文件名)两个属性。
-
module/plugins
- module:Webpack在处理文件时,会用不同的加载器(loaders)来处理不同类型的文件。这些加载器在
module部分配置。 - plugins:插件用于在构建过程中执行更复杂的任务,如优化JS文件、生成CSS文件、提供环境变量等。插件在
plugins部分配置。
- module:Webpack在处理文件时,会用不同的加载器(loaders)来处理不同类型的文件。这些加载器在
-
mode
- mode:Webpack 4引入了
mode属性,用于指定构建环境是开发(development)还是生产(production)。这个设置会影响Webpack内置的优化和插件行为。
- mode:Webpack 4引入了
-
watch/devServer/devtool
- watch(监视):
watch属性可以让Webpack在文件发生变化时自动重新构建项目。 - devServer(开发服务器):Webpack DevServer是一个小型的静态服务器,用于在开发过程中提供网页。它支持热模块替换(HMR)。
- devtool(源映射):
devtool属性用于配置源映射,帮助开发者在浏览器中调试代码时映射回原始源代码。
- watch(监视):
基本使用方法
-
声明入口entry
module.exports = { entry: "./src/index" }; -
声明产物出口output
const path = require("path"); module.exports = { entry: './src/index.js', output: { filename: '[name].js' path: path.join(__dirname, 'dist'), } }; -
运行
npx webpack
处理CSS
-
安装Loader
pnpm add -D css-loader style-loader -
添加module处理css文件
const path = require("path"); module.exports = { entry: "./src/index", output: { filename: "[name].js", path: path. join(_dirname, "./dist"), }, module: { // css 处理器 rules: [{ test: /.css/i,//固定条件 use: [ "style-loader", "css-loader" ],//使用这两个来处理以.css结尾的文件 }], }, };
Loader
在 Webpack 中,"loader" 是一个特殊的模块,它用于在 Webpack 构建过程中对模块的源代码进行转换或处理。Loaders 允许你在打包文件之前对它们进行预处理,例如编译、打包、优化、转换等操作
主要特点:
-
转换文件:
- Loaders 可以将文件从一种格式转换为另一种格式,例如将 TypeScript 转换为 JavaScript,或将 SASS 转换为 CSS。
-
处理资源:
- Loaders 可以处理图片、字体等资源文件,并将它们转换为可以在 JavaScript 模块中使用的格式。
-
代码优化:
- Loaders 可以对代码进行压缩、去重、提取公共代码等优化操作。
-
模块化:
- Loaders 支持模块化处理,允许你将复杂的任务分解为多个 loader,每个 loader 负责处理一部分任务。
-
链式处理:
- Loaders 可以链式使用,Webpack 会根据配置的顺序从右到左处理 loader,允许你将多个 loader 应用于同一个文件。
常见的 Loaders:
-
babel-loader:
- 将 JavaScript 文件使用 Babel 转换为兼容更多浏览器的代码。
-
css-loader 和 style-loader:
- 将 CSS 文件加载为模块,并将其注入到 HTML 中。
-
file-loader 和 url-loader:
- 处理图片和其他文件资源,将它们转换为 URL 或 Data URL。
-
html-loader:
- 将 HTML 文件加载为字符串。
-
eslint-loader:
- 在构建过程中对 JavaScript 代码进行 lint 检查。
参考资料:
处理JS--Babel
-
安装依赖
npm i -D @babel/core @babel/preset-env babel-loader -
声明产物出口output
const path = require("path"); module.exports = { entry: "./src/index", output: { filename: "[name].js", path: path.join(_dirname, "./dist"), }, module: { rules: [{ test: /.js?$/, use: [{ loader: 'babel-loader', options: { presets: [ ['@babel/preset-env'] ] } }] }] } } -
执行
npx webpack
Babel
是一个广泛使用的 JavaScript 编译器,它允许开发者使用最新的 JavaScript 语法特性编写代码,同时确保这些代码能够在当前和旧版的浏览器或其他环境中运行。Babel 通过转换代码,将 ES6+(ECMAScript 2015 及更高版本)的代码转换为向后兼容的 JavaScript 版本(如 ES5),从而使得现代 JavaScript 语法能够在不支持新语法的环境中运行。
主要功能:
-
代码转换:
- Babel 可以将 ES6+ 代码转换为 ES5 代码,使得可以在旧版浏览器中运行。
-
语法插件:
- Babel 通过插件支持各种新的 JavaScript 语法提案,这些插件可以单独使用或组合使用。
-
polyfill:
- Babel 可以引入 polyfills 来提供那些在旧版环境中不存在的新功能。
-
代码优化:
- Babel 转换后的代码会进行优化,以提高运行效率。
-
模块转换:
- Babel 支持将 ES6 模块转换为 CommonJS 或 AMD 模块,以便于在不同环境中使用。
-
集成开发工具:
- Babel 可以集成到各种开发工具中,如 Webpack、Rollup、Gulp 等。
-
代码高亮和格式化:
- Babel 可以与代码编辑器和 IDE 集成,提供代码高亮和自动格式化功能。
参考资料:
- babel-loader | webpack
- Babel · Babel (babeljs.io)
- Babel (babeljs.io)
- Babel (babeljs.io)
- @babel/preset-typescript · Babel (babeljs.io)
处理HTML--自动生成HTML文件
-
安装依赖
npm i -D html-webpack-plugin -
声明产物出口output
const path = require("path"); const HtmlWebpackPlugin = require('html-webpack-plugin');] module.exports = { entry: "./src/index", output: { filename: "[name].js", path: path. join(_dirname, "./dist"), }, plugins: [new HtmlWebpackPlugin()] }; -
执行
npx webpack
工具
HMR
Hot Module Replacement--模块热替换
HMR 允许在应用运行时动态地替换、添加或删除模块,而无需重新加载整个页面。
主要优势:
-
提升开发效率:
- 开发者在修改代码后,可以立即看到更改的效果,而无需手动刷新浏览器。
-
节省时间:
- 无需重新加载整个页面,减少了开发过程中的等待时间。
-
状态保持:
- HMR 可以在模块替换过程中保持应用的状态,不会被重置。
-
优化开发体验:
- 对于复杂的应用,HMR 可以提供更好的开发体验,尤其是在开发单页应用(SPA)时。
在Webpack中使用HMR:
-
开启HMR:
- webpack.config.js文件
module.exports = { // ... devServer: { hot: true, } }; -
启动Webpack:
npx Webpack serve
工作原理:
- 当Webpack检测到模块的更改时,它会使用HMR协议与运行中的应用程序通信。
- 应用程序中的HMR运行时会接收到更新指令,并应用这些更改,通常是替换内存中的模块,而不是整个页面。
- 浏览器不会失去状态,用户界面会根据新的模块进行更新。
Tree-Shaking
Tree-Shaking--树摇,用于删除Dead Code
-
Dead Code
- 代码没有被用到,不可到达
- 代码的执行结果不会被用到
- 代码只读不写
- ...
Tree-Shaking把定义了但是没使用的代码删掉
在Webpack中使用Tree Shaking:
webpack.config.js文件
module.exports = {
entry: "./src/index",
mode: "production",//1.
devtool: false,
optimization: {
usedExports: true,//2.
},
};
PS:对工具类库如Lodash有奇效
其它工具
-
缓存
- Webpack 本身缓存:Webpack 会缓存构建结果,如果源文件没有变化,下一次构建会非常快。
- 持久化缓存:通过使用如
cache-loader这样的插件,可以在多次构建之间持久化缓存。
-
Sourcemap
- Webpack 允许通过配置
devtool选项来生成 Sourcemap,例如devtool: 'source-map'
- Webpack 允许通过配置
-
性能监控
- Webpack Bundle Analyzer:一个流行的插件,可以可视化地展示包内容,帮助开发者理解包的大小和组成。
- performance hints:Webpack 会在构建时提供性能提示,警告那些体积过大的包。
-
日志
- 内置日志:Webpack 提供了基本的日志输出。
- friendly-errors-webpack-plugin:一个插件,可以美化错误输出,使其更容易理解。
- webpack-logger:一个插件,用于自定义日志记录。
-
代码压缩
- TerserWebpackPlugin:一个插件,用于压缩 JavaScript 和 JSON。
- css-minimizer-webpack-plugin:用于压缩 CSS。
- html-webpack-plugin:用于压缩 HTML 文件。
-
分包
- 动态导入:Webpack 支持 ES6 动态导入语法,允许代码分割。
- SplitChunksPlugin:Webpack 的内置插件,用于自动分割代码。
- 自定义分割点:通过配置
optimization.splitChunks选项,可以指定特定的分割点。
-
...