webpack study notes
概念:webpack 是前端项目工程化的具体解决方案。
主要功能:它提供了友好的前端模块化开发支持,以及代码压缩混淆、处理浏览器端 JavaScript 的兼容性、性能优化等强大的功能。
目前 Vue,React 等前端项目,基本上都是基于 webpack 进行工程化开发的
基本使用
-
项目根目录下执行
npm init –y
初始化包管理配置文件 package.json -
执行
npm install webpack@5.42.1 webpack-cli@4.7.2 -D
安装 webpack 相关的两个包 -
在项目根目录中,创建名为 webpack.config.js 的 webpack 配置文件,并初始化如下的基本配置:
module.exports = { mode: 'development' //mode用来指定构建模式。可选值有 development 和 production }
-
在 package.json 的 scripts 节点下,新增 dev 脚本如下:
"scripts": { "dev": "webpack" //script 节点下的脚本,可以通过 npm run 执行 }
5.运行 npm run dev
命令,启动webpack进行项目的打包构建
webpack.config.js 文件的作用
webpack.config.js 是 webpack 的配置文件。webpack 在真正开始打包构建之前,会先读取这个配置文件,从而基于给定的配置,对项目进行打包。
注意:由于 webpack 是基于 node.js 开发出来的打包工具,因此在它的配置文件中,支持使用 node.js 相关的语法和模块进行 webpack 的个性化配置。
自定义打包的入口与出口
在 webpack 4.x 和 5.x 的版本中,有如下的默认约定:
-
默认的打包入口文件为
/src/index.js
-
默认的输出文件路径为
/dist/main.js
在 webpack.config.js 配置文件中,通过 entry 节点指定打包的入口。通过 output 节点指定打包的出口。
const path = require('path') //导入 node.js 的路径的模块
module.exports = {
entry: path.join(__dirname, './src/index.js'),
output: {
path: path.join(__dirname, './dist'),
filename: 'bundle.js'
}
}
./
代表目前所在的目录。../
代表上一层目录。/
代表根目录。
webpack 中的插件
-
webpack-dev-server
每当修改了源代码,webpack 会自动进行项目的打包和构建
-
运行命令
npm install webpack-dev-server@3.11.2 -D
-
修改 package.json -> scripts 中的 dev 命令如下:
"scripts": { "dev": "webpack serve", }
-
再次运行
npm run dev
命令,重新进行项目的打包 -
在浏览器中访问 http://localhost:8080 地址,查看自动打包效果
webpack-dev-server 会启动一个实时打包的 http 服务器
devServer 节点
在 webpack.config.js 配置文件中,可以通过 devServer 节点对 webpack-dev-server 插件进行更多的配置,示例代码如下:
devServer: { open: true, host: '127.0.0.1', port: 80, }
-
-
html-webpack-plugin
html-webpack-plugin 是 webpack 中的 HTML 插件,可以通过此插件自定制 index.html 页面的内容
下面通过 html-webpack-plugin 插件,将 src 目录下的 index.html 首页,复制到项目根目录中一份。
-
运行
npm install html-webpack-plugin@5.3.2 -D
-
在 webpack.config.js 配置文件中配置 html-webpack-plugin
//导入插件 const HtmlPlugin = require('html-webpack-plugin') //创建Html插件实例对象 const htmlPlugin = new HtmlPlugin({ template: './src/html.js', //源文件路径 filename: './index.html' //目标文件路径 }) module.exports = { mode: 'development', plugins: [htmlPlugin], //plugins节点使得插件生效 }
HTML 插件在生成的 index.html 页面,自动注入了打包的 bundle.js 文件
-
webpack 中的loader
在实际开发过程中,webpack 默认只能打包处理以 .js 后缀名结尾的模块。
其他非 .js 后缀名结尾的模块,webpack 默认处理不了,需要调用 loader 加载器才可以正常打包。
loader 加载器的作用:协助 webpack 打包处理特定的文件模块。
-
打包处理css文件
-
运行
npm i style-loader@3.0.0 css-loader@5.2.6 -D
命令,安装处理 css 文件的 loader -
在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:
module: { //所有第三方文件木块的匹配规则 rules: [{ //文件后缀名的匹配规则 test: /\.css$/, //要匹配的文件类型 use: ['style-loader','css-loader'] //要调用的loader }] }
-
-
打包处理less文件
-
运行
npm i less-loader@10.0.1 less@4.1.1 -D
命令 -
在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:
module: { rules: [{ test: /\.less$/, use: ['style-loader','css-loader','less-loader'] }] }
-
-
打包处理样式表中与 url 路径相关的文件
-
运行
npm i url-loader@4.1.1 file-loader@6.2.0 -D
命令 -
在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:
module: { rules: [{ test: /\.jpg|png|gif$/, use: 'url-loader?limit=22229' }] }
limit用来指定图片的大小,单位是字节
只有 <= limit大小的图片,才会被转为base64格式
-
-
打包处理 js 文件中的高级语法
webpack 只能打包处理一部分高级的 JavaScript 语法。对于那些 webpack 无法处理的高级 js 语法,需要借助于 babel-loader 进行打包处理。
-
运行如下的命令安装对应的依赖包:
npm i babel-loader@8.2.2 @babel/core@7.14.6 @babel/plugin-proposal-decorators@7.14.5 -D
-
在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:
{ test: /\.js$/, user: 'babel-loader', exclude: /node_modules/ }
-
配置babel-loader
在项目根目录下,创建名为babel.config.js的配置文件,定义Babel的配置项如下
module.exports = { plugins: [ ["@babel/plugin-proposal-decorators", { version: "2023-05" }], ] }
-
打包发布
-
配置 webpack 的打包发布
在 package.json 文件的 scripts 节点下,新增 build 命令如下:
"script": { "dev": "webpack serve", "build": "webpack --mode production" //项目发布时,运行build命令 }
--mode 是一个参数项,用来指定 webpack 的运行模式。production 代表生产环境,会对打包生成的文件进行代码压缩和性能优化。
通过 --mode 指定的参数项,会覆盖 webpack.config.js 中的 mode 选项。
-
自动清理 dist 目录下的旧文件
为了在每次打包发布时自动清理掉 dist 目录中的旧文件,可以安装并配置 clean-webpack-plugin 插件:
npm install clean-webpack-plugin@3.0.0 -D
//按需导入插件、得到插件的构造函数之后,创建插件的实例对象 const {CleanWebpackPlugin} = require('clean-webpack-plugin') const cleanPlugin = new CleanWebpackPlugin() //把创建的cleanPlugin插件实例对象,挂载到plugins节点中 plugins: [htmlPlugin,cleanPlugin]
Source Map
Source Map 就是一个信息文件,里面储存着位置信息。也就是说,Source Map 文件中存储着压缩混淆后的代码,所对应的转换前的位置。
有了它,出错的时候,除错工具将直接显示原始代码,而不是转换后的代码,能够极大的方便后期的调试。
-
webpack 开发环境下的 Source Map
在开发环境下,webpack 默认启用了 Source Map 功能。当程序运行出错时,可以直接在控制台提示错误行的位置,并定位到具体的源代码:
开发环境下,推荐在 webpack.config.js 中添加如下的配置,即可保证运行时报错的行数与源代码的行数保持一致:
module.exports = { mode: 'development', devtool: 'eval-source-map', }
-
只定位行数不暴露源码
此时可以将 devtool 的值设置为
nosources-source-map
-
定位行数且暴露源码
此时可以将 devtool 的值设置为
source-map
-
-
Source Map 的最佳实践
-
开发环境下:
建议把 devtool 的值设置为
eval-source-map
好处:可以精准定位到具体的错误行
-
生产环境下:
建议关闭 Source Map 或将 devtool 的值设置为
nosources-source-map
好处:防止源码泄露,提高网站的安全性
-
总结
实际开发中会使命令行工具(俗称 CLI)一键生成带有 webpack 的项目,对webpack的要求
-
能够掌握 webpack 的基本使用
安装、webpack.config.js、修改打包入口
-
了解常用的 plugin 的基本使用
webpack-dev-server、html-webpack-plugin
-
了解常用的 loader 的基本使用
loader 的作用、loader 的调用过程
-
能够说出 Source Map 的作用
精准定位到错误行并显示对应的源码
方便开发者调试源码中的错误
webpack.config.js示例
const path = require('path')
const HtmlPlugin = require('html-webpack-plugin') //导入html-webpack-plugin插件,得到插件的构造函数
const htmlPlugin = new HtmlPlugin({ //new 构造函数,创建插件的实例对象
template: './src/index.html', // 指定要复制哪个页面
filename: './index.html' // 指定复制出来的文件名和存放路径
})
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = { // 使用 Node.js 中的导出语法,向外导出一个 webpack 的配置对象
devtool: 'nosources-source-map', // 在开发调试阶段 devtool 的值设置为 eval-source-map
// devtool: 'eval-source-map', // 在实际发布的时候 devtool 的值设置为 nosources-source-map
mode: 'development',
entry: path.join(__dirname, './src/index1.js'), // entry: '指定要处理哪个文件'
output: { // 指定生成的文件要存放到哪里
path: path.join(__dirname, 'dist'), // 存放的目录
filename: 'js/bundle.js' // 生成的文件名
},
plugins: [htmlPlugin, new CleanWebpackPlugin()], //插件的数组,webpack 在运行时会加载并调用这些插件
devServer: {
open: true, // 首次打包成功后,自动打开浏览器
port: 80, // 在 http 协议中,如果端口号是 80,则可以被省略
host: '127.0.0.1' // 指定运行的主机地址
},
module: {
rules: [{ // 定义了不同模块对应的 loader
test: /\.css$/,
use: ['style-loader', 'css-loader']
},{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader']
},{
test: /\.jpg|png|gif$/,
use: 'url-loader?limit=470&outputPath=images' //多个参数之间,使用 & 符号进行分隔
},{
test: /\.js$/,
use: 'babel-loader', // 使用 babel-loader 处理高级的 JS 语法
exclude: /node_modules/ //排除 node_modules 目录中的 JS 文件
}]
},
resolve: {
alias: {
'@': path.join(__dirname, './src/') //指定代码中 @ 表示 src 这一层目录
}
}
}
package.json示例(json不支持注释)
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js", //项目默认执行文件
"scripts": { //script 节点下的脚本,可以通过 npm run XXX 执行
"dev": "webpack serve",
"build": "webpack --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": { //生产环境下,项目运行所需依赖。-S
"jquery": "^3.6.0"
},
"devDependencies": { //开发环境下,项目所需依赖。-D
"@babel/core": "^7.14.6",
"@babel/plugin-proposal-decorators": "^7.14.5",
"babel-loader": "^8.2.2",
"clean-webpack-plugin": "^4.0.0-alpha.0",
"css-loader": "^5.2.6",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.3.2",
"less": "^4.1.1",
"less-loader": "^10.0.1",
"style-loader": "^3.0.0",
"url-loader": "^4.1.1",
"webpack": "^5.42.1",
"webpack-cli": "^4.7.2",
"webpack-dev-server": "^3.11.2"
}
}