目录
一、entry、output
二、loader
三、plugin
四、mode
五、代码分离
六、懒加载
七、结果分析
系列教程
webpack4教程(初识篇)
webpack4教程(番外篇)
一、entry、output
1、entry
每个entry属性,对应一个入口文件(依赖图的开端),便于单页、多页应用的js引入。
//单入口
entry: {
main: './src/index.js'
}
//单入口可以简写
//entry: './src/index.js'
//多入口
entry: {
one: './src/one/index.js',
two: './src/two/index.js',
three: './src/three/index.js'
}
2、output
//单入口
//const path = require('path')
output: {
path: path.resolve(__dirname, 'dist')
filename: bundle.js
}
//多入口
//const path = require('path')
output: {
path: path.resolve(__dirname, 'dist')
filename: [name].js //使用[name]占位符,自动识别入口文件名,从而区分打包文件名
}
PS:即使存在多入口,也只能存在一个output。
3、管理输出
//const HtmlWebpackPlugin = require('html-webpack-plugin');
//const CleanWebpackPlugin = require('clean-webpack-plugin');
plugins: [
new CleanWebpackPlugin(), //每次打包前,清理dist目录
new HtmlWebpackPlugin() //创建html模板
]
4、缓存
浏览器具有缓存功能,但是缓存系统只识别文件名。当我们在服务器上,更新了文件内容,但是没有更改文件名时,浏览器则继续使用缓存文件,而不去下载新文件。因此,监听文件内容变化,实时更改产出文件名,这一做法尤为关键。
(1)使用hash值,保证文件名的唯一性
filename: '[name].[contenthash].js'
(2)提取引导模板
//打包时,会抽离出runtime部分
optimization: {
runtimeChunk: 'single'
}
(3)防止更新一个文件,多个文件改名
//开发模式
new webpack.HashedModulesPlugin()
//生产模式
new webpack.HashedModuleIdsPlugin()
PS:只改动了一个文件的代码,但是这会改变工程文件的解析顺序。此时,就部分文件而言(如:抽离出来的第三方依赖包),尽管内容没变,但是webpack会根据解析顺序的变化,认为该文件发生了改动。因此,[contenthash]也随之变化。
二、loader
1、module.rules
//不推荐在import、cli中进行loader配置
module: {
rules: [
//rule
{
test: /\.css$/,
use: [
//loader——工作顺序:尾至头
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: true
}
}
]
}
]
}
2、加载css
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}
3、加载图像
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
}
4、加载字体
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
'file-loader'
]
}
5、加载数据
{
test: /\.(csv|tsv)$/,
use: [
'csv-loader'
]
},
{
test: /\.xml$/,
use: [
'xml-loader'
]
}
PS:通过转换器,任何类型的模块,都可以在js中直接导入。若不使用转换器,只支持.js/.json文件导入。
三、plugin
插件提供强大的功能,丰富webpack的打包能力。
//通过new实例,启用插件
plugins: [
new webpack.ProgressPlugin(), //webpack自带一系列插件
new HtmlWebpackPlugin({template: './src/index.html'}) //使用对象,为插件配置参数
]
四、mode
模式 | 概述 |
---|---|
development | 会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development。启用 NamedChunksPlugin 和 NamedModulesPlugin。 |
production | 会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。启用 FlagDependencyUsagePlugin,FlagIncludedChunksPlugin,ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 TerserPlugin。 |
none | 退出任何默认优化选项 |
1、开发模式
(1)映射源代码
//将编译后的代码,映射回源代码,以达到错误追踪的效果,便于调试
devtool: 'inline-source-map' //根据需求选择devtool
(2)监听代码变化,自动编译
//不推荐使用观察模式、webpack-dev-middleware
devServer: {
port: 3000,
contentBase: './dist' //在dist目录,启动服务器
}
PS:使用webpack-dev-server命令启动服务器。
(3)热替换
概述:无刷新,基于webpack-dev-server。
//配置文件
devServer: {
hot: true
}
plugins: [
new webpack.HotModuleReplacementPlugin()
]
//js模块
import 模块1 from './模块1'
if(module.hot) {
//监听模块变化
module.hot.accept('./模块1', () => {
//调用模块1的api
})
}
PS:由于loader已完成module.hot.accept()工作,css热加载无需手动调用module.hot.accept()。
2、生产模式
(1)tree-shaking
在生产模式下,打包过程中,会删除依赖包中,无引用的部分,按需产出精简的代码。
(2)设置副作用
//package.json
"sideEffects": false //让webpack顺利进行tree-shaking
PS:设置副作用,只是告诉webpack,期望自己的包是没有副作用的。尽管存在副作用,也不会影响到tree-shaking
(3)映射源代码
devtool: 'source-map'
(4)压缩css
optimization: {
minimizer: [
new TerserJSPlugin({}),
new OptimizeCSSAssetsPlugin({})
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
],
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader"
]
}
]
}
PS:生产模式下,默认压缩代码。
3、双模式配置
配置文件名 | 概述 |
---|---|
webpack.common.js | 公共配置 |
webpack.dev.js | 开发模式配置 |
webpack.prod.js | 生产模式配置 |
(1)合并配置文件
const merge = require('webpack-merge') //合并工具
const common = require('./webpack.common.js')
module.exports = merge(common, {
//开发模式/生产模式专属配置
})
(2)命令
//开发模式,启动服务器
webpack-dev-server --open --config webpack.dev.js
//生产模式,打包
webpack --config webpack.prod.js
五、代码分离
1、防止重复
多入口文件可能存在重复引入的情况,进行代码分离,抽取重复引入的代码。
//抽取重复引入的代码,到单独的文件中
optimization: {
splitChunks: {
chunks: 'all'
}
}
2、预取、预加载
(1)预取
import(/* webpackPrefetch: true */ '模块');
(2)预加载
import(/* webpackPreload: true */ '模块');
(3)区别
- preload chunk 会在父 chunk 加载时,以并行方式开始加载。prefetch chunk 会在父 chunk 加载结束后开始加载。
- preload chunk 具有中等优先级,并立即下载。prefetch chunk 在浏览器闲置时下载。
- preload chunk 会在父 chunk 中立即请求,用于当下时刻。prefetch chunk 会用于未来的某个时刻。
- 浏览器支持程度不同。
六、懒加载
在用户交互上,动态引入代码
import('模块') //返回promise,可以使用async+await等异步加载手段
七、结果分析
webpack stats 可交互饼图