目录
3.2 CSS/LESS解析 -- css-loader style-loader
3.3 图片/文字解析 -- file-loader url-loader
一、webpack安装
1. 生成初始化package.json
npm init -y
2. 安装webpack
npm install webpack webpack-cli --save-dev
测试安装是否成功
.\node_modules\.bin\webpack -v
二、核心概念
2.1 Bundle、Module、Chunk
2.1.1 Bundle
Bundle是由多个不同的模块生成,bundles 包含了早已经过加载和编译的最终源文件版本。 **Bundle 分离(Bundle Splitting):**这个流程提供了一个优化 build 的方法,允许 webpack 为应用程序生成多个 bundle。最终效果是,当其他某些 bundle 的改动时,彼此独立的另一些 bundle 都可以不受到影响,减少需要重新发布的代码量,因此由客户端重新下载并利用浏览器缓存。
2.1.2 Module
**模块(Module)**提供比较完整程序接触面(surface area)更小的离散功能块。精心编写的模块提供了可靠的抽象和封装界限,使得应用程序中每个模块都具有条理清楚的设计和明确的目的。 模块解析(Module Resolution)一个模块可以作为另一个模块的依赖模块,resolver 是一个库(libary)用于帮助找不到模块的绝对路径,模块将在resolve.modules中指定的所有目录内搜索。
2.1.3 Chunk
Chunk这是 webpack 特定的术语被用在内部来管理 building 过程。bundle 是由 chunk 组成,其中有几种类型(例如,入口 chunk(entry chunk)和子 chunk(child chunk))。通常 chunk 会直接对应所输出的 bundle,但是有一些配置并不会产生一对一的关系。 **代码分离(Code Splitting)**指将代码分离到每个 bundles/chunks 里面,你可以按需加载,而不是加载一个包含全部的 bundle。 **配置(Configuration)**webpack 的配置文件是一个普通的 JavaScript 文件,它导出为一个对象。然后由 webpack 根据这个对象定义的属性进行处理。
2.2 Entry
webpack是一个模块打包器,会将一切资源,当成模块进行打包,各模块之前存在依赖关系。故需要通过入口文件找到依赖。
// 单入口文件
module.exports = {
entry: './path/demo01/src/files'
};
// 多入口文件
module.exports = {
entry: {
app: './src/app.js',
app2: './src/app2.js'
},
output: {
filename: '[name].js', // 通过占位符确保文件名称的唯一,指定打包出来的文件名称
path: __dirname + '/dist'
}
};
2.3 Output
Output用来指定打包后的文件输出到磁盘中。包括目录和文件名称
// 单入口
module.exports = {
entry: './path/demo01/src/files'
output: {
filename: 'bundle.js',
path: __dirname + '/dist'
}
};
// 多入口
module.exports = {
entry: {
app: './src/app.js',
app2: './src/app2.js'
},
output: {
filename: '[name].js',
path: __dirname + '/dist'
}
};
2.4 Loaders
2.4.1 用处
webpack开箱即用只支持JS和JSON两种文件类型,需要通过Loader来支持其他文件类型,并转换成有效的模块,并添加到模块图中。
2.4.2 常见的Loaders
名称 | 描述 |
babel-loader | 转换ES6\ES7等JS新语法 |
css-loader | 支持.css文件的加载和解析 |
less-loader(sass-loader scss-loader也是一样) | 将less文件转换成css |
ts-loader | 将TS转换成JS |
file-loader | 进行图片、文字等的打包 |
raw-loader | 将文件以字符串形式导入 |
thread-loader | 多进程打包JS和CSS |
2.4.3 Loaders用法
'use strict';
const path = require('path')
module.exports = {
entry: {
index: './src/index.js',
search: './src/search.js'
},
output: {
filename: '[name].js',
path: path.join(__dirname, 'dist'),
},
mode: 'production',
module: {
// 需要用的loader放到rules数组中
rules: [
// test: 指定匹配规则
// use: 指定使用的loaders名称
{ test:/\.txt$/, use: 'raw-loader'}
]
}
}
2.5 Plugins
2.5.1 用处
插件用于bundle文件的优化、资源管理和环境变量注入
作用域整个构建过程
2.5.2 常见的Plugins
名称 | 描述 |
CommonsChunkPlugin | 将chunks相同的模块代码提取成公共js |
CleanWebpackPlugin | 清理构建目录 |
ExtractTextWebpackPlugin | 将CSS从bunlde文件里提取成一个独立的css文件 |
CopyWebpackPlugin | 将文件或文件夹拷贝到构建的输出目录 |
HtmlWebpackPlugin | 创建html文件去承载输出的bundle |
raw-loader | 将文件以字符串形式导入 |
thread-loader | 多进程打包JS和CSS |
2.6 Mode
2.6.1 用处
用来指定当前的构建环境是:production、development或是none
设置mode可以使用webpack内置的函数,默认 production
2.6.2 内置插件
三、资源解析工具
3.1 ES6解析 -- babel-loader
3.1.1 安装
npm i @babel/core @babel/preset-env babel-loader -D
3.1.2 配置
'use strict';
const path = require('path')
module.exports = {
entry: {
index: './src/index.js',
search: './src/search.js'
},
output: {
filename: '[name].js',
path: path.join(__dirname, 'dist'),
},
mode: 'production',
module: {
rules: [
// test: 指定匹配规则
// use: 指定使用的loaders名称
{
test:/.js$/,
use: 'babel-loader'
}
]
},
plugins: [
]
}
新建.babelrc.js文件
// .babelrc
{
"presets": [
"@babel/preset-env"
]
}
3.1.3 react-jsx解析
npm i react react-dom @babel/preset-react -D
修改.babelrc.js文件
{
"presets": [
"@babel/preset-env",
"@babel/preset-react" // 用于解析react语法
]
}
3.2 CSS/LESS解析 -- css-loader style-loader
3.2.1 背景
css-loader用于加载.css文件,并将其转换成 commonjs 对象
style-loader 将样式通过<style>标签插入到head中
3.2.2 使用
安装
npm -i style-loader css-loader -D
配置:
// webpack.config.js
'use strict';
const path = require('path')
module.exports = {
entry: {
index: './src/index.js',
search: './src/search.js'
},
output: {
filename: '[name].js',
path: path.join(__dirname, 'dist'),
},
mode: 'production',
module: {
rules: [
// test: 指定匹配规则
// use: 指定使用的loaders名称
{
test: /.js$/,
use: 'babel-loader'
},
{
test: /.css$/,
use: [
'style-loader',
'css-loader'
]
}
]
},
plugins: [
]
}
3.2.3 解析less
npm i less less-loader -D
module: {
rules: [
// test: 指定匹配规则
// use: 指定使用的loaders名称
{
test: /.js$/,
use: 'babel-loader'
},
{
test: /.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /.less$/,
use: [
'style-loader',
'css-loader',
'less-loader'
]
}
]
},
3.3 图片/文字解析 -- file-loader url-loader
3.3.1 背景
可以使用file-loader对文字和图片进行处理
url-loader实际上就是在file-loader基础上进行了封装,可以对设定 limit 大小的图片和字体文件,自动进行base64的转换
3.3.2 使用
npm i file-loader -D
module: {
rules: [
.....
{
test: /.(png|jpg|gif|jpeg)$/,
use: 'file-loader'
},
{
test: /.(woff|woff2|eot|ttf|otf)$/,
use: 'file-loader'
}
]
},
3.3.3 使用url-loader压缩图片和字体文件
module: {
rules: [
.....
{
test: /.(png|jpg|gif|jpeg)$/,
use: {
loader: 'url-loader',
options: {
limit: 2048 // 图片小于2k
}
}
},
{
test: /.(woff|woff2|eot|ttf|otf)$/,
use: {
loader: 'url-loader',
options: {
limit: 2048 // 图片小于2k
}
}
}
]
},
四、监听、热更新、文件指纹
4.1 文件监听
4.1.1 什么是文件监听
即在发现源码发生变化时,自动重新构建出新的输出文件
4.1.2 开启
文件监听有两种开启方式:
1) 在启动webpack时,带上 --watch 参数
2)在配置webpack.config.js中,设置watch:true
4.2 热更新: webpack-dev-server
不刷新浏览器,且放在内存中。使用HotModuleReplacementPlugin插件。
npm i webpack-dev-server -D
// webpack.config.js
const webpack = require('webpack');
module.exports = {
...
module: {
rules: [
...
]
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist',
hot: true
}
}
// package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config webpack.config.js",
"watch": "webpack --watch",
"dev": "webpack-dev-server --open"
}
4.3 文件指纹
4.3.1 什么是文件指纹
修改打包后输出的文件名的后缀
4.3.2 文件指纹如何生成
Hash: 与整个项目的构建相关,只要项目文件有修改,整个项目构建hash值就会更改
Chunkhash: 和webpack打包的chunk有关,不同的 entry 会生成不同的 chunkhash 值
Contenthash: 根据文件内容来定义 hash,文件内容不变,则 contenthash 不变
4.3.3 文件指纹的使用
设置 MiniCssExtractPlugin 的 filename
占位符名称 | 含义 |
[ext] | 资源后缀名 |
[name] | 文件名称 |
[paht] | 文件的相对路径 |
[folder] | 文件所在的文件夹 |
[contenthash] | 文件的内容Hash,默认是md5生成 |
[hash] | 文件内容的Hash,默认是md5生成 |
[emoji] | 一个随机的指代文件内容的emoji |
安装:
npm i mini-css-extract-plugin -D
// webpack.prod.js
module.exports = {
output: {
filename: '[name]_[chunkhash:8].js',
path: path.join(__dirname, 'dist'),
},
module: {
rules: [
..
{
test: /.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
},
{
test: /.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader'
]
},
// 使用file-loader
{
test: /.(png|jpg|gif|jpeg)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name]_[hash:8].[ext]'
}
}
]
},
{
test: /.(woff|woff2|eot|ttf|otf)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name]_[hash:8].[ext]'
}
}
]
}
]
}
}
四、HTML/CSS/JS 代码压缩
4.1 JS 文件压缩
webpack 内置了 uglifyjs-webpack-plugin
4.2 CSS文件压缩
使用 optimize-css-assets-webpack-plugin
4.2.1 安装
npm i optimize-css-assets-webpack-plugin -D
npm i cssnano -D // 前者依赖cssnano,故也需要安装
4.2.2 配置
// webpack.prod.js
// 引入插件
const OptionsCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
// 使用插件
module.exports = {
...
plugins: [
new OptionsCssAssetsWebpackPlugin({
assetNameRegExp: /\.css$/g,
cssProcessor: require('cssnano')
})
]
}
4.3 HTML文件压缩
使用html-webpack-plugin
4.3.1 安装
npm i html-webpack-plugin -D
4.3.2 配置
// webpack.prod.js
// 引入插件
const OptionsCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
// 使用插件
module.exports = {
...
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, "src/search.html"), // html模板所在位置
filename: 'search.html', // 打包出来的名称
chunks: ['search'], // 指定生成的html使用哪些chunk
inject: true, // 打包后的css会自动注入
minify: {
html5: true,
collapseWhitespace: true,
preserveLineBreaks: false,
minifyCSS: true,
minifyJS: true,
removeComments: false
}
}),
new HtmlWebpackPlugin({
template: path.join(__dirname, "src/index.html"), // html模板所在位置
filename: 'index.html', // 打包出来的名称
chunks: ['index'], // 指定生成的html使用哪些chunk
inject: true, // 打包后的css会自动注入
minify: {
html5: true,
collapseWhitespace: true,
preserveLineBreaks: false,
minifyCSS: true,
minifyJS: true,
removeComments: false
}
})
]
}
五、进阶用法
5.1 文件自动清理
为了避免每次构建前都要手动删除dist,要使用 clean-webpack-plugin 实现自动删除dist
5.1.1 安装
npm i clean-webpack-plugin -D
5.1.2 配置
// webpack.prod.js
// 引入
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
// 使用
module.exports = {
plugins: [
new CleanWebpackPlugin()
]
}
5.2 autopreFixer 自动补齐CSS3前缀
由于要兼容各种浏览器,手动去编写太耗时间。可以使用PostCSS的插件autopreFixer,在代码生成时处理
5.2.1 安装
npm i postcss-loader autoprefixer -D
5.2.2 配置
// webpack.prod.js
module.exports = {
module: {
rules: [
{
test: /.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
},
{
test: /.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader',
{
loader: 'postcss-loader',
options: {
plugins: () => [
require('autoprefixer')({
browsers: ['last 2 version', '>1%', 'ios 7'] // 低版本
// overrideBrowserslist: ['last 2 version', '>1%', 'ios 7'] // 高版本
})
]
}
}
]
},
]
}
5.2.3 问题
若在打包过程中出现下面的错误,是因为版本台新,将 browsers 换成 overrideBrowsersList 即可
5.3 使用px2rem-loader将px自动转成rem
过去使用媒体查询来适配各种屏幕的手机,之后出现了rem。但设置<html>上的html需要手动写js。这里可以用px2rem-loader将px自动转换成rem。
同时,可以使用lib-flexible库来动态计算根元素的rem的单位(px)
5.3.1 安装
npm i px2rem-loader -D
npm i lib-flexible -S
5.3.2 配置
// webpack.prod.js
module.exports = {
module: {
rules: [
{
test: /.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
},
{
test: /.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader',
{
loader: 'postcss-loader',
options: {
plugins: () => [
require('autoprefixer')({
// browsers: ['last 2 version', '>1%', 'ios 7']
overrideBrowserslist: ['last 2 version', '>1%', 'ios 7'] // 高版本
})
]
}
},
{
loader: 'px2rem-loader',
options: {
remUnit: 75, // 代表 1rem = 75px 适合 750的视觉稿
remPrecesion: 8 // 代表px转换成rem后,小数点位数
}
}
]
}
]
}
}
参考链接:
webpack中的bundle、module、chunk: https://juejin.im/post/5d70ad50f265da03cf7aae91