Webpack
简介
一:Webpack 是一个静态模块打包工具,从入口构建依赖图,打包有关的模块,最后用于展示你的内容
二:静态模块:编写代码过程中的,html,css, js,图片等固定内容的文件
三:打包过程,注意:只有和入口有直接/间接引入关系的模块,才会被打包
四:Webpack 的作用:把静态模块内容,压缩,转译等(前端工程化)
- 把 less/sass 转成 css 代码
- 把 ES6+ 降级成 ES5 等
- 支持多种模块文件类型,多种模块标准语法
五:为何不学 vite?
现在很多项目还是基于 Webpack 来进行构建的,所以还是要掌握 Webpack 的使用
六:体验 Webpack 打包 2 个 JS 文件内容
需求:封装 utils 包,校验手机号和验证码长度,在 src/index.js 中使用,使用 Webpack 打包
步骤
一:新建项目文件夹 Webpack_study,初始化包环境,得到 package.json 文件
终端上输入
npm init -y
二:新建 src 源代码文件夹(书写代码)包括 utils/check.js 封装用户名和密码长度函数,引入到 src/index.js 进行使用
- 在 src/utils/check.js 中
// 封装校验手机号长度和校验验证码长度的函数
export const checkPhone = phone => phone.length === 11
export const checkCode = code => code.length === 6
- 在 src/index.js 中
/**
* 目标1:体验 webpack 打包过程
*/
// 1.1 准备项目和源代码
import { checkPhone, checkCode } from '../utils/check.js'
console.log(checkPhone('13900002020'))
console.log(checkCode('123123123123'))
// 1.2 准备 webpack 打包的环境
// 1.3 运行自定义命令打包观察效果(npm run 自定义命令)
三:下载 webpack webpack-cli 到项目(版本独立),终端上输入:
npm i webpack webpack-cli --save-dev
注意:
虽然 webpack 是全局软件包,封装的是命令工具,但是为了保证项目之间版本分别独立,所以这次比较特殊,下载到某个项目环境下,但是需要把 webpack 命令配置到 package.json 的 scripts 自定义命令,作为局部命令使用
四:项目中运行工具命令,采用自定义命令的方式(局部命令),此处我的自定时命令是build,终端上输入:
npm run build
说明: npm run 自定义命令名字
注意: 实际上在终端运行的是 build 右侧的具体命名
需求最终流程图:
修改入口和出口
Webpack配置影响 Webpack 打包过程
步骤:
一:项目根目录,新建 Webpack.config.js 配置文件
二:导出配置对象,配置入口,出口文件路径(别忘了修改磁盘文件夹和文件的名字)
entry: 入口
output:出口(path:打包到哪个文件夹,filename:这个文件夹的哪个文件是出口)
const path = require('path')
module.exports = {
entry: path.resolve(__dirname, 'src/login/index.js'),
output: {
path: path.resolve(__dirname, 'dist'),
filename: './login/index.js'
}
}
三:重新打包观察
图解:
案例-用户登录长短判断
需求:点击登录按钮,判断手机号和验证码长度是否符合要求
一:新建 public/login.html 准备网页模版(方便查找标签和后期自动生成 html 文件做准备)
二:核心 JS 代码写在 src/login/index.js 文件
/**
* 目标3:用户登录-长度判断案例
* 3.1 准备用户登录页面
* 3.2 编写核心 JS 逻辑代码
* 3.3 打包并手动复制网页到 dist 下,引入打包后的 js,运行
*/
// 3.2 编写核心 JS 逻辑代码
document.querySelector('.btn').addEventListener('click', () => {
const phone = document.querySelector('.login-form [name=mobile]').value
const code = document.querySelector('.login-form [name=code]').value
if (!checkPhone(phone)) {
console.log('手机号长度必须是11位')
return
}
if (!checkCode(code)) {
console.log('验证码长度必须是6位')
return
}
console.log('提交到服务器登录...')
})
三:运行自定义命令,让 Webpack 打包 JS 代码
四:手动复制 public/login.html 到 dist 下,手动引入打包后的 JS 代码文件,运行 dist/login.html 在浏览器查看效果
自动生成 html 文件
插件 html-webpack-plugin 作用:在 Webpack 打包时生成 html 文件,并引入其他打包后的资源
步骤:
一:下载 html-webpack-plugin 本地软件包到项目中
终端上输入:
npm i html-webpack-plugin --save-dev
二:配置 webpack.config.js 让 Webpack 拥有插件功能
- template 模版文件:可以是想要压缩的文件
- filename 输出文件:想要在 dist 中要输出的文件及目录,此时是输出在 dist 下的 login 下的 index.html 中
// ...
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
// ...
plugins: [
new HtmlWebpackPlugin({
template: './public/login.html', // 模板文件
filename: './login/index.html' // 输出文件
})
]
}
三:指定以 public/login.html 为模版复制到 dist/login/login.html,并自动引入其他打包后资源
四、运行打包命令,观察打包后 dist 文件夹下内容并运行查看效果
打包 css 代码
注意: Webpack 默认只识别 JS 和 JSON 文件内容,所以想要让 Webpack 识别更多不同内容,需要使用加载器
需要2个加载器来辅助 Webpack 才能打包 css 代码
- 加载器 css-loader:解析 css 代码,具体见
- 加载器 style-loader:把解析后的 css 代码插入到 DOM(style标签之间)
步骤
一:准备 css 文件引入到 src/login/index.js 中(压缩转译处理等,这里是在 src/login/index.js 中引入)
/**
* 目标5:打包 css 代码
* 5.1 准备 css 代码,并引入到 js 中
* 5.2 下载 css-loader 和 style-loader 本地软件包
* 5.3 配置 webpack.config.js 让 Webpack 拥有该加载器功能
* 5.4 打包后观察效果
*/
// 5.1 准备 css 代码,并引入到 js 中
import 'bootstrap/dist/css/bootstrap.min.css'
import './index.css' //这里的路径是自己写的css文件
注意:
这里只是引入代码内容让 Webpack 处理,不需定义变量接收在 JS 代码中继续使用,所以没有定义变量接收
二:下载 css-loader 和 style-loader 本地软件包,终端上输入:
npm i css-loader style-loader --save-dev
三:配置 webpack.config.js 让 Webpack 拥有该加载器功能
// ...
module.exports = {
// ...
module: { // 加载器
rules: [ // 规则列表
{
test: /\.css$/i, // 匹配 .css 结尾的文件
use: ['style-loader', 'css-loader'], // 使用从后到前的加载器来解析 css 代码和插入到 DOM
}
]
}
};
四:打包后运行 dist/login/index.html 观察效果,看看准备好的样式是否作用在网页上
五:上述配置表示对于以 .css 为扩展名的文件,先使用 css-loader 解析,在使用 style-loader 进行样式注入。通过这样的配置,我们可以在 JS 模块中直接导入 css文件,并在应用程序中使用它们的样式
注意:
在Webpack中,style-loader和css-loader是两个常用的加载器,用于处理CSS文件的加载和解析。
css-loader:
css-loader是一个Webpack加载器,用于解析CSS文件。它允许您在JavaScript模块中导入CSS文件,并将其转换为模块的依赖关系图。css-loader会处理CSS文件中的@import和url()等语法,并解析它们所引用的文件路径。
css-loader的主要功能包括:
- 解析CSS文件中的import语句,可以导入其他CSS文件。
- 处理CSS文件中的url()语法,可以解析其中的URL路径。
- 将CSS文件转换为JavaScript模块,以便在构建过程中处理和管理。
style-loader:
style-loader是另一个Webpack加载器,它将解析后的CSS代码注入到HTML页面中的<style>
标签中。它将CSS模块的样式应用到页面上,使得样式生效。
style-loader的主要功能包括:
- 将解析后的CSS代码注入到HTML页面中的
<style>
标签中。 - 通过JavaScript动态创建
<style>
标签,并将CSS样式应用到页面上。 - 支持使用插入顺序控制样式的优先级。
优化提取 css 代码
需求:让 Webpack 把 css 代码内容字符串单独提取到 dist 下的 css文件中
需要 mini-css-extrat-plugin
插件来实现
一:下载 mini-css-extract-plugin 插件软件包到本地项目中,终端上输入:
npm i --save-dev mini-css-extract-plugin
二:配置 webpack.config.js 让 Webpack 拥有该插件功能
// ...
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
module.exports = {
// ...
module: {
rules: [
{
test: /\.css$/i,
// use: ['style-loader', 'css-loader']
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
plugins: [
// ...
new MiniCssExtractPlugin()
]
};
三:打包后观察效果
注意: 不能和 style-loader 一起使用
好处: css 文件可以被浏览器缓存,减少 JS 文件体积,让浏览器并行下载 css 和 js文件
注意:
mini-css-extract-plugin 是Webpack中的一个插件,用于将CSS代码从JavaScript文件中提取到单独的CSS文件中。它可以将CSS文件与JavaScript文件分离,以便于浏览器并行加载,提高页面加载性能。
使用 mini-css-extract-plugin 可以将CSS文件单独打包,而不是将样式通过
style
标签嵌入到HTML页面中。这对于生产环境的构建非常有用,因为在生产环境中,我们通常希望将CSS文件进行优化和压缩,以减少文件大小,并且可以通过缓存来提高加载速度。
优化压缩过程
需求:把提出的 css 文件内样式代码压缩
需要:css-minimizer-webpack-plugin 插件来实现
步骤:
一:下载 mini-css-extract-plugin 插件软件包到本地项目中,终端上输入:
npm i css-minimizer-webpack-plugin --save-dev
二:配置 webpack.config.js 让 Webpack 拥有该插件功能
// ...
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
// ...
// 优化
optimization: {
// 最小化
minimizer: [
// 在 webpack@5 中,你可以使用 `...` 语法来扩展现有的 minimizer(即
// `terser-webpack-plugin`),将下一行取消注释(保证 JS 代码还能被压缩处理)
`...`,
new CssMinimizerPlugin(),
],
}
};
三:打包后观察 css 文件内自己代码是否被压缩了
- css-minimizer-webpack-plugin 是Webpack中的一个插件,用于压缩和优化CSS代码。它通过使用CSS压缩器来减小CSS文件的大小,并提供了一些配置选项来定制压缩的行为。
- 使用 css-minimizer-webpack-plugin 可以在Webpack构建过程中自动压缩CSS文件,减少文件大小,提高页面加载速度。它是一个优化生产环境构建的有用工具。
- 用于生产环境构建:通常在生产环境中使用,以确保CSS文件被最小化,减小文件体积。
打包 less 代码
加载器 less-loader:把 less 代码编译为 css 代码,还需要依赖 less 软件包
步骤:
一、新建 login/index.less 文件,设置背景图样式(此图片在 src/login/assets 文件夹下)
html {
body {
background: url('./assets/login-bg.png') no-repeat center/cover;
}
}
二、将 less 样式引入到 src/login/index.js 中
/**
* 目标8:打包 less 代码
* 8.1 新建 less 代码(设置背景图)并引入到 src/login/index.js 中
* 8.2 下载 less 和 less-loader 本地软件包
* 8.3 配置 webpack.config.js 让 Webpack 拥有功能
* 8.4 打包后观察效果
*/
// 8.1 新建 less 代码(设置背景图)并引入到 src/login/index.js 中
import './index.less'
三、下载 less 和 less-loader 本地软件包
npm i less less-loader --save-dev
四、配置 webpack.config.js 让 Webpack拥有功能
// ...
module.exports = {
// ...
module: {
rules: [
// ...
{
test: /\.less$/i,
use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"]
}
]
}
}
五、打包后运行,观察效果
打包图片
方式一
资源模块:Webpack5 内置了资源模块的打包,无需下载额外 loader
步骤:
一、配置 webpack.config.js 让 Webpack 拥有打包图片功能
- 占位符 hash:对模块内容做算法计算,得到映射的数字字母组合的字符串
- 占位符 ext:使用当前模块原本的占位符,例如 .png / .jpg 等字符串
- 占位符 query:保留引入文件时代码中查询参数(只有 URL 下生效)
二、注意:判断临界值默认为 8KB
- 大于 8KB 文件:发送一个单独的文件并导出 URL 地址
- 小于 8KB 文件:导出一个 data URL (base64字符串)
三、在 src/login/index.js 中给 img 标签添加 logo 图片
/**
* 目标9:打包资源模块(图片处理)
* 9.1 创建 img 标签并动态添加到页面,配置 webpack.config.js
* 9.2 打包后观察效果和区别
*/
// 9.1 创建 img 标签并动态添加到页面,配置 webpack.config.js
// 注意:js 中引入本地图片资源要用 import 方式(如果是网络图片http地址,字符串可以直接写)
import imgObj from './assets/logo.png'
const theImg = document.createElement('img')
theImg.src = imgObj
document.querySelector('.login-wrap').appendChild(theImg)
四、配置 webpack.config.js 让 webpack 拥有打包图片功能
// ...
module.exports = {
// ...
module: {
rules: [
// ...
{
test: /\.(png|jpg|jpeg|gif)$/i,
type: 'asset',
generator: {
filename: 'assets/[hash][ext][query]'
}
}
]
}
}
五、打包后运行观察效果
方式二
也可以用第二个方式,下载加载器来实现图片打包
一、安装 loader:常见的 loader 包括 file-loader
和 url-loader
npm install file-loader url-loader --save-dev
二、配置 loader:在 webpack 配置中,添加适当的 loader 规则。以下是一个基本的配置
module.exports = {
// ...其他配置
module: {
rules: [
{
test: /\.(png|jpe?g|gif|svg)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192, // 小于8KB的图片将转为 base64 编码,否则将使用 file-loader 拷贝文件
},
},
],
},
],
},
};
这个配置告诉 webpack 当处理以:.png / .jpg / .jpeg / .gif /.svg 结尾的文件时,使用 url-loader
三、使用图片:可以用以下方法引入图片:
import myImage from './path/to/my-image.png';
// 在使用中,例如作为img的src
const imgElement = document.createElement('img');
imgElement.src = myImage;
document.body.appendChild(imgElement);
四、打包:运行 webpack 构建命令,它会处理图片文件并将他们打包到输出目录中
//此项目中配置的命令是
npm run build
上述步骤中,url-loader
的 options
中的 limit
参数用于指定一个阈值(单位是字节)。当图片文件大小小于这个阈值时,url-loader
将会把图片转为 base64 编码,嵌入到打包后的文件中;当图片文件大小大于这个阈值时,url-loader
将会使用 file-loader
处理,将图片文件复制到输出目录,并返回文件路径。
案例-用户登录
需求:点击登录按钮,基于 npm 下载 axios 包,完成验证码登录功能
步骤:
一、使用 npm 下载 axios
npm i axios
二、引入到 src/login/index.js 中编写业务实现
/**
* 目标10:完成登录功能
* 10.1 使用 npm 下载 axios(体验 npm 作用在前端项目中)
* 10.2 准备并修改 utils 工具包源代码导出实现函数,具体看我的github上的utils文件夹下面,有默认导出axios 和命名导出alert
* 10.3 导入并编写逻辑代码,打包后运行观察效果
*/
// 10.3 导入并编写逻辑代码,打包后运行观察效果
import myAxios from '../utils/request.js'
import { myAlert } from '../utils/alert.js'
document.querySelector('.btn').addEventListener('click', () => {
const phone = document.querySelector('.login-form [name=mobile]').value
const code = document.querySelector('.login-form [name=code]').value
if (!checkPhone(phone)) {
myAlert(false, '手机号长度必须是11位')
console.log('手机号长度必须是11位')
return
}
if (!checkCode(code)) {
myAlert(false, '验证码长度必须是6位')
console.log('验证码长度必须是6位')
return
}
//提交到服务器
myAxios({
url: '/v1_0/authorizations',
method: 'POST',
data: {
mobile: phone,
code: code
}
}).then(res => {
myAlert(true, '登录成功')
localStorage.setItem('token', res.data.token)
location.href = '../content/index.html'
}).catch(error => {
myAlert(false, error.response.data.message)
})
})
三、打包后运行观察效果
搭建开发环境
- 每次改动代码,都要重新打包,很麻烦,所以这里给项目集成 webpack-dev-server 开发服务器
- 作用:启动 Web 服务,打包输出源码在内存,并会自动检测代码变化热更新到网页
步骤:
一、下载 webpack-dev-server 软件包到当前项目
npm i webpack-dev-server --save-dev
二、配置自定义命令,并设置打包的模式为开发模式
// ...
module.exports = {
// ...
mode: 'development';
//后面推荐在 package.json中的dev写入 --mode=deveplopment 来表示开发模式
//后面推荐在 package.json中的build写入 --mode=production 来表示生产模式
}
以及 json文件
"scripts": {
// ...
"dev": "webpack serve --mode=development"
},
在 js / css 文件中修改代码保存后,会实时反馈到浏览器
打包模式
一、打包模式:告知 webpack 使用响应模式的内置优化 https://webpack.docschina.org/configuration/mode/
二、分类:
模式名称 | 模式名字 | 特点 | 场景 |
---|---|---|---|
开发模式 | development | 调试代码,试试加载,模块热替换等 | 本地开发 |
生产模式 | production | 压缩代码,资源优化,更轻量等 | 打包上线 |
三、如何设置影响 webpack
- 方式一:在 webpack.config.js 配置文件设置 mode 选项
// ...
module.exports = {
// ...
mode: 'production'
//后面推荐在 package.json中的dev写入 --mode=deveplopment 来表示开发模式
//后面推荐在 package.json中的build写入 --mode=production 来表示生产模式
}
- 方式二:在 package.json 命令行设置 mode 参数
"scripts": {
"build": "webpack --mode=production",
"dev": "webpack serve --mode=development"
},
四、注意:命令行设置的优先级高于配置文件中的,推荐用命令行设置
五、体验:在 build 命令修改 mode 的值,打包输出观察打包后的 js 文件内容
打包模式的应用
- 需求:在开发模式下用 style-loader 内嵌模块,在生产模式下提取 css 代码
- 方案1:webpack.config.js 配置导出函数,但是局限性大(只接受2种模式)https://webpack.docschina.org/configuration/mode/
- 方案2:借助 cross-env(跨平台通用)包命令,设置参数区分环境
- 方案3:配置不同的 webpack.config.js (适用多种模式差异较大情况)https://webpack.docschina.org/guides/production/)
- 主要使用方案 2 尝试,其他方案可以结合跳转的官方文档查看
步骤:
一、下载 cross-env 软件包到当前项目
npm i cross-env --save-dev
二、配置自定义命令,传入参数名和值(会绑定到 process.env 对象下)
代码
"scripts": {
"build": "cross-env NODE_ENV=production webpack --mode=production",
"dev": "cross-env NODE_ENV=development webpack serve --open --mode=development"
},
三、在webpack.config.js 区分不同环境使用不同配置
module.exports = {
module: {
rules: [
//css
{
test: /\.css$/i,
use: [
process.env.NODE_ENV === 'development' ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
],
},
//less
{
test: /\.less$/i,
use: [
process.env.NODE_ENV === 'development' ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'less-loader',
],
},
],
},
//匹配
plugins: [
// 只在生产模式下使用 MiniCssExtractPlugin
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css',
}),
// 其他插件...
],
};
四、重新打包观察两种配置区别
在Webpack中,在开发模式和生产模式下选择不同的样式加载方式(内嵌模块或提取CSS代码)有助于优化开发体验和生产性能。
- 开发模式下使用 style-loader 内嵌模块:
- 快速开发反馈:在开发模式下,通常更希望快速获得样式的反馈,而不是等待单独的CSS文件加载。内嵌模块的方式使得样式可以直接注入到页面中,无需额外的HTTP请求,提高了开发的实时性。
- 热模块替换(HMR):
style-loader
支持热模块替换,可以在代码修改时保持页面状态,实现样式的无刷新更新。
- 生产模式下提取 CSS 代码:
- 优化性能:在生产环境下,通常更关注性能和加载速度。将CSS提取到独立的文件中有助于并行加载,因为浏览器可以同时下载多个文件,提高页面加载速度。
- 缓存利用:独立的CSS文件可以更好地利用浏览器缓存,减少重复下载的次数。当你的应用被缓存后,只有CSS文件发生变化时,才需要重新下载。
前端注入环境变量
- 需求:前端项目中,开发模式下打印语句生效,生产模式下打印语句失效
- 问题:cross-env 设置的只在 Node.js 环境生效,前端代码无法访问 process.env.NODE_ENV
- 解决:使用 Webpack 内置的 DefinePlugin 插件 https://webpack.docschina.org/plugins/define-plugin
- 作用:在编译时,将前端代码中匹配的变量名,替换为值或表达式
配置 webpack.config.js 中给前端注入环境变量
// ...
const webpack = require('webpack')
module.exports = {
// ...
plugins: [
// ...
new webpack.DefinePlugin({
// key 是注入到打包后的前端 JS 代码中作为全局变量
// value 是变量对应的值(在 corss-env 注入在 node.js 中的环境变量字符串)
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
})
]
}
开发环境调错 source map
source map:可以准确追踪 error 和 warning 在原始代码的位置 https://webpack.docschina.org/guides/development/
问题:代码被压缩和混淆,无法正确定位源代码位置(行数和列数)
设置:webpack.config.js 配置 devtool 选项
// ...
module.exports = {
// ...
devtool: 'inline-source-map'
}
inline-source-map 选项:把源码的位置信息一起打包在 js 文件内
注意:source map 适用于开发环境,不要在生产环境使用(防止被请以查看源码位置)
const config = {
//这里写的是 module.exports 里面的内容,到后面会赋值 module.exports = config
}
//只有开发模式下才能使用 sourcemap 选项,这里可以检查判断
if(process.env.NODE_ENV === 'development'){
config.devtool = 'inline-source-map'
}
//将config内容赋值给 module.exports
module.exports = config;
设置解析别名路径
- 解析别名:配置模块如何解析,创建 import 或 require 的别名,来确保模块引入变得更简单
示例:
- 原来路径:
import { checkPhone, checkCode } from '../src/utils/check.js'
- 配置解析别名:在 webpack.config.js 中设置
// ...
const config = {
// ...
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
}
}
- 这样我们以后,引入目标模块写的路径就更简单了,主要就是给路径一个别名让调用的时候更简洁一些
import { checkPhone, checkCode } from '@/utils/check.js'
修改完后,重新打包观察效果是否正常
优化-CDN使用
需求:开发模式使用本地第三方库,生产模式下使用 CDN 加载引入
CDN定义:内容分发网络,指的是一组分布在各个地区的服务器 https://developer.mozilla.org/zh-CN/docs/Glossary/CDN
作用:把静态资源文件/第三方库放在 CDN 网络中各个服务器中,供用户就近请求获取
好处:减轻自己服务器请求压力,就近请求物理延迟低,配套缓存策略
- 实现需求的思路图:
步骤:
一、在 html 中引入第三方库的CND地址并用模板语法判断,在你的HTML模板中,使用Webpack的变量来替代资源的路径。
<% if(htmlWebpackPlugin.options.useCdn){ %>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/css/bootstrap.min.css" rel="stylesheet">
<% } %>
二、配置 webpack.config.js 中 externals 外部扩展选项(防止某些 import 的包被打包)
// 生产环境下使用相关配置
if (process.env.NODE_ENV === 'production') {
// 外部扩展(让 webpack 防止 import 的包被打包进来)
config.externals = {
// key:import from 语句后面的字符串
// value:留在原地的全局变量(最好和 cdn 在全局暴露的变量一致)
'bootstrap/dist/css/bootstrap.min.css': 'bootstrap',
'axios': 'axios'
}
}
以及
// ...
const config = {
// ...
plugins: [
new HtmlWebpackPlugin({
// ...
// 自定义属性,在 html 模板中 <%=htmlWebpackPlugin.options.useCdn%> 访问使用
useCdn: process.env.NODE_ENV === 'production'
})
]
}
三、观察两种模式下打包效果
多页面打包
概念:单页面:单个 html 文件,切换 DOM 的方式实现不同业务逻辑展示,后续 Vue/React 会学到
多页面:多个 html 文件,切换页面实现不同业务逻辑展示
需求:把黑马头条-数据管理平台-内容页面一起引入打包使用
步骤:
一、准备源码(html,css,js)放入相应位置,并改用模块化语法导出
二、下载 form-serialize 包并导入到核心代码中使用
三、配置 webpack.config.js 多入口和多页面的设置
// ...
const config = {
entry: {
'模块名1': path.resolve(__dirname, 'src/入口1.js'),
'模块名2': path.resolve(__dirname, 'src/入口2.js'),
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: './[name]/index.js'
}
plugins: [
new HtmlWebpackPlugin({
template: './public/页面2.html', // 模板文件
filename: './路径/index.html', // 输出文件
chunks: ['模块名1']
})
new HtmlWebpackPlugin({
template: './public/页面2.html', // 模板文件
filename: './路径/index.html', // 输出文件
chunks: ['模块名2']
})
]
}
四、其中的 [name] 表示 输出的目录,如果是 login则输出在 login/index.js下,如果是content在输出在 content/index.js 下
实际的代码: 每一个模块都表示一个包,最后都会被单独压缩到 dist 下成为 文件夹
//配置项目的入口和出口
//入口
// entry: path.resolve(__dirname, 'src/login/index.js'),
//两个入口(模块名)
entry: {
'login': path.resolve(__dirname, 'src/login/index.js'),
'content': path.resolve(__dirname, 'src/content/index.js'),
'publish': path.resolve(__dirname, 'src/publish/index.js'),
},
//出口
output: {
//先配置进入哪个包
path: path.resolve(__dirname, 'dist'),
//再配置这个要到这个包下的哪个文件
// filename: './login/index.js',
//根据入口名字自己获取到对应的出口
filename: './[name]/index.js',
//生成打包内容之前,清除输出目录
clean: true
},
//插件,给webpack提供更多功能
plugins: [
//打包html文件 ,两个打包
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'public/login.html'), //以login.html为模版文件
filename: path.resolve(__dirname, 'dist/login/index.html'), //输出文件
useCdn: process.env.NODE_ENV = 'production', //production 模式下才会生效cdn引入的地址
chunks: ['login'], //引入哪些打包后的模块(和 entry 的 key 一致)
}),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'public/content.html'), //以login.html为模版文件
filename: path.resolve(__dirname, 'dist/content/index.html'), //输出文件
useCdn: process.env.NODE_ENV = 'production', //production 模式下才会生效cdn引入的地址
chunks: ['content'], //引入哪些打包后的模块(和 entry 的 key 一致)
}),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'public/publish.html'), //以login.html为模版文件
filename: path.resolve(__dirname, 'dist/publish/index.html'), //输出文件
useCdn: process.env.NODE_ENV = 'production', //production 模式下才会生效cdn引入的地址
chunks: ['publish'], //引入哪些打包后的模块(和 entry 的 key 一致)
}),
//将外面的main.css输出在 dist目录下的 login/index.css
new MiniCssExtractPlugin({
filename: './[name]/index.css'
}),
//webpack环境变量
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
}),
],
优化-分割公共代码
需求:把 2 个以上页面引用的公共代码提取
步骤:
一、配置 webpack.config.js 的 splitChunks 分割功能
// ...
const config = {
// ...
optimization: {
// ...
splitChunks: {
chunks: 'all', // 所有模块动态非动态移入的都分割分析
cacheGroups: { // 分隔组
commons: { // 抽取公共模块
minSize: 0, // 抽取的chunk最小大小字节
minChunks: 2, // 最小引用数
reuseExistingChunk: true, // 当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用
name(module, chunks, cacheGroupKey) { // 分离出模块文件名
const allChunksNames = chunks.map((item) => item.name).join('~') // 模块名1~模块名2
return `./js/${allChunksNames}` // 输出到 dist 目录下位置
}
}
}
}
}
}
二、打包观察效果