先简单回顾下 webpack 原理
Webpack
可以看做是模块打包机,把解析的所有模块变成一个对象,然后通过入口模块去加载我们的东西,然后依次实现递归的依赖关系,通过入口来运行所有的文件。由于 webpack
只认识js,所以需要通过一系列的 loader
和 plugin
转换成合适的格式供浏览器运行。
loader
主要是对资源进行加载/转译的预处理工作,其本质是一个函数,在该函数中对接收到的内容进行转换,返回转换后的结果。某种类型的资源可以使用多个 loader
,执行顺序是从右到左,从下到上。
plugin
(插件)主要是扩展 webpack
的功能,其本质是监听整个打包的生命周期。webpack
基于事件流框架 Tapable
, 运行的生命周期中会广播出很多事件,plugin
可以监听这些事件,在合适的时机通过 webpack
提供的 API 改变输出结果。
新建一个目录,进入目录初始化 package.json
,并安装 webpack
依赖
// 初始化包
npm init -y
// 安装依赖
npm i webpack webpack-cli -D
webpack
默认配置文件名字为 webpack.config.js
,于是在项目根目录下新建一个名为 webpack.config.js
的文件,在配置文件里写最简单的单页面配置:
let path = require("path");
module.exports = {
mode: "development",
entry: "./src/js/index.js",
output: {
filename: "js/bundle.js",
path: path.resolve("dist"),
publicPath: "http://cdn.xxxxx"
}
}
配置详解
development
为开发模式,打包后代码不会被压缩production
为生产模式,打包后代码为压缩代码filename
:打包后文件,filename 的值可设置成带 hash
戳的文件:js/bundle.[hash].js
/ js/bundle.[hash:8].js
(只显示 8 位 hash 戳)path
:打包文件路径,需为绝对路径publicPath
:上线的cdn地址TIP: 上述代码中
path
为内置模块,无需安装,直接引入即可。
新建后还需在项目根目录下的 src/js
目录下新建 index.js
文件,然后随便输入一句 js 代码。
配置后可使用 webpack
命令尝试打包,若报错找不到命令可 npm i webpack -g
全局安装后再打包,打包成功后会输出到项目根目录下的 dist
目录。
项目目录结构大致如下
├─package.json
├─webpack.config.js
├─src
| ├─js
| | └index.js
├─dist
由于 webpack
只认识 js
,因此需通过 html-webpack-plugin
插件打包 html 文件
npm i html-webpack-plugin -D
安装后在 webpack.config.js
配置文件中
let HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
plugins: [ new HtmlWebpackPlugin({
template: "./src/index.html" }) ]
}
production
模式下可以开启 html 文件的压缩配置:
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
minify: {
removeAttributeQuotes: true, collapseWhitespace: true },
hash: true
})
]
配置详解
removeAttributeQuotes
:删除属性双引号collapseWhitespace
:代码压缩成一行TIP: 如果不指定模板
template
配置,将是插件默认的 html文件,而不是项目中的 html 文件
webpack 通过安装 webpack-dev-server
开启服务
npm i webpack-dev-server -D
配置 webpack.config.js
devServer: {
port: 5000,
compress: true,
open: true,
client: {
progress: true }
}
配置详解
webpack-dev-server
配置
gzip
压缩progress
:在浏览器中以百分比显示编译进度配置好可运行 webpack-dev-server
命令查看效果,若找不到命令可 npm i webpack-dev-server -g
全局安装下
开发过程中容易遇到接口跨域问题,可通过 devServer.proxy
配置解决
假设接口地址为 http://localhost:3000/api/users
,对 /api/users
的请求可如下配置
devServer: {
proxy: {
'/api': 'http://localhost:3000',
},
},
但实际项目中接口的地址有很多种可能,一般不会有 /api
目录,即一般接口地址为http://localhost:3000/users
,因此枚举配置会很麻烦,可通过代理请求解决
即先请求 http://localhost:3000/api/users
接口地址,然后通过 devServer 代理到 http://localhost:3000/users
本文通过 express
开启接口服务,接口地址为 http://localhost:3000/user
,接口代码不再赘述,后期上传完整的源码,可通过 node "项目路径\webpack5\src\js\server.js"
启动接口服务,然后配置 webpack.config.js
devServer: {
proxy: {
"/api": {
target: "http://localhost:3000/",
pathRewrite: {
"/api": ""
},
},
}
}
devServer
配置详解
当后端接口没有写好,又不希望被阻塞进度,可以通过 mock 前期跟后端约定好的接口数据格式来模拟调试页面。可使用有自定义函数和应用自定义中间件的能力的配置 devServer.setupMiddlewares
,在 middlewares.unshift
中的回调函数使用 res.send
把需要 mock 的数据传递进去:
devServer: {
setupMiddlewares: (middlewares, devServer) => {
if (!devServer) {
throw new Error("webpack-dev-server is not defined");
}
middlewares.unshift({
name: "user-info",
// `path` 是可选的,接口路径
path: "/user",
middleware: (req, res) => {
// mock 数据模拟接口数据
res.send({
name: "moon mock" });
},
});
return middlewares;
},
}
样式处理需要用到的 loader 及其作用:
less-loader
:加载和转译 LESS 文件postcss-loader
:使用 PostCSS 加载和转译 CSS/SSS 文件,如可以处理 autoprefixer
css 包,为css添加浏览器前缀css-loader
:解析 @import
and url()
语法,使用 import 加载解析后的css文件,并且返回 CSS 代码mini-css-extract-plugin
的 loader
:抽取出 css 文件,通过 link 标签引入 html 文件