mode
模式:"production" | "development" | "none"
不同的模式会对 webpack 打包时进行一些对应的优化配置。
development模式下的打包,不会压缩打包后文件的体积
production模式下的打包,会压缩打包后的文件体积
所以开发过程中用development,推送上线的时候用production
entry
指定打包⼊口⽂文件,有三种不同的形式:string | object | array
一对一:一个入口、一个打包文件:
module.exports = {
entry: './src/index.js'
}
多对一:多个入口、一个打包文件
module.exports = {
entry: [
'./src/index1.js',
'./src/index2.js',
]
}
多对多:多个入口、多打包文件
module.exports = {
entry: {
'index1': "./src/index1.js",
'index2': "./src/index2.js"
}
}
output
打包后的文件位置
module.exports = {
...,
output: {
path: path.resolve(__dirname, "dist"), // //输出文件的存放路径
filename: "bundle.js", // 指定一个固定的文件名称
filename: "[name].js" // 文件名字为entry对象的key值
}
}
可以指定一个固定的文件名称,如果是多入口多出口(entry
为对象),则不能使用单文件出口,需要使用下面的方式。
通过 webpack
内置的变量占位符:[name]
webpack
默认情况下只能处理 js
模块,如果需要处理其它类型的模块,则需要使用它提供的一些其它功能,如loaders、plugins,可以处理非js文本、css、图片等
Loaders
module.exports = {
...,
module: {
rules:[
{
test:/\.xxx$/,
use:{
loader: 'xxx-load'
}
}
]
}
}
当 webpack
碰到不识别的模块的时候,webpack
会在配置的 module
中进行该文件解析规则的查找
rules
就是我们为不同类型的文件定义的解析规则对应的 loader,它是一个数组。
每一种类型规则通过 test 选项来定义,通过正则进行匹配,通常我们会通过正则的方式来匹配文件后缀类型。
use
针对匹配到文件类型,调用对应的 loader
进行处理
常用的loader:
raw-loader
file-loader
url-loader
css-loader 分析 css
模块之间的关系,并合成⼀个 css
style-loader 把 css-loader
生成的内容,用 style
标签挂载到⻚面的 head
中
rules: [
...,
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
]
同一个任务的 loader
可以同时挂载多个,处理顺序为:从右到左,也就是先通过 css-loader
处理,然后把处理后的 css
字符串交给 style-loader
进行处理
Plugins
扩展 webpack
本身的一些功能,它们会运行在 webpack
的不同阶段(钩子 / 生命周期)
HtmlWebpackPlugin
在打包结束后,⾃动生成⼀个 html
⽂文件,并把打包生成的 js 模块引⼊到该 html
中
安装:
npm install --save-dev html-webpack-plugin
使用:
在webpack.config.js文件中配置plugins
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
...
plugins: [
new HtmlWebpackPlugin({
title: "My App", // 页面的title
filename: "app.html", // 生成的html文件名字
template: "./src/html/index.html" // 引用的html模板
})
]
};
clean-webpack-plugin
安装:
npm install -D clean-webpack-plugin
删除(清理)构建目录
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports = {
...
plugins: [
...,
new CleanWebpackPlugin(),
...
]
}
mini-css-extract-plugin
提取 CSS
到一个单独的文件中
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
...,
module: {
rules: [
{
test: /\.s[ac]ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
'css-loader',
'sass-loader'
]
}
]
},
plugins: [
...,
new MiniCssExtractPlugin({
filename: '[name].css'
}),
...
]
}
sourceMap
我们实际运行在浏览器的代码是通过 webpack
打包合并甚至是压缩混淆过的代码,所生成的代码并不利于我们的调试和错误定位,我们可以通过 sourceMap
来解决这个问题,sourceMap
本质是一个记录了编译后代码与源代码的映射关系的文件,我们可以通过 webpack
的 devtool
选项来开启 sourceMap
module.exports = {
mode: 'production',
devtool: 'source-map',
...
}
WebpackDevServer
每次的代码修改都需要重新编译打包,刷新浏览器,特别麻烦,我们可以通过安装 webpackDevServer
来改善这方面的体验
npm install --save-dev webpack-dev-server
启动命令:
"scripts": {
"server": "webpack-dev-server"
}
修改 webpack.config.js
module.exports = {
...,
devServer: {
// 自动开启浏览器
open: true,
// 端口
port: 8081
}
}
启动服务以后,webpack
不在会把打包后的文件生成到硬盘真实目录中了,而是直接存在了内存中(同时虚拟了一个存放目录路径),后期更新编译打包和访问速度大大提升
Proxy
服务端代理,处理跨域问题
module.exports = {
...,
devServer: {
// 自动开启浏览器
open: true,
// 端口
port: 8081,
proxy: {
//拦截/api开头的请求,并把/api替换成/data
'/api': {
target: 'http://localhost:8787',
pathRewrite: {
"^/api": "/data",
},
}
}
}
}
通过 proxy
设置,当我们在当前 WebpackDevServer
环境下发送以 /api
开头的请求都会被转发到 http://localhost:8787 目标服务器下
Hot Module Replacement
在之前当代码有变化,我们使用的 live reload
,也就是刷新整个页面,虽然这样为我们省掉了很多手动刷新页面的麻烦,但是这样即使只是修改了很小的内容,也会刷新整个页面,无法保持页面操作状态。HMR
随之就出现了,它的核心的局部(模块)更新,也就是不刷新页面,只更新变化的部分
module.exports = {
...,
devServer: {
// 自动开启浏览器
open: true,
// 端口
port: 8081,
// 开启热更新
hot:true,
// 即使 HMR 不生效,也不去刷新整个页面(选择开启)
hotOnly:true,
proxy: {
'/api': {
target: 'http://localhost:8787'
}
}
}
}
index.js文件
import fn1 from './fn1.js';
box1.onclick = fn1;
if (module.hot) {//如果开启 HMR
module.hot.accept('./fn1.js', function() {
// 更新逻辑
box1.onclick = fn1;
})
}
上面代码就是 当 ./fn1.js 模块代码发生变化的时候,把最新的 fn1 函数绑定到 box1.onclick 上
从上面就可以看到,HMR
其实就是以模块为单位,当模块代码发生修改的时候,通知客户端进行对应的更新,而客户端则根据具体的模块来更新我们的页面逻辑(这些逻辑需要自己去实现),好在当前一些常用的更新逻辑都有了现成的插件