webpack的常见用法(一)
解析ES6 和 解析React JSX
-
介绍
使用babel-loader
, 配置文件为.babelrc
-
.babelrc介绍
包含两块内容:
presests: 一系列plugin的集合
plugins: 一个plugin对应一个功能 -
依赖包安装
3.1 解析ES6
npm i @babel/core @babel/preset-env babel-loader -D
3.2 解析React JSX
npm i react react-dom @babel/preset-react -D
-
用法
// webpack.config.js 中
const path = require('path')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader'
}
]
}
}
// .babelrc中
{
"presets": [
"@babel/preset-env", // 解析ES6的配置
"@babel/preset-react" // 解析React JSX 的配置
]
}
解析CSS 和 解析less / sass
- 介绍
使用css-loader
,用于加载.css
文件,并且转化为commonjs
对象
使用style-loader
, 将样式通过<style>
标签插入到head
中
loader调用是链式调用, 解析也是链式解析, 解析顺序是从右到左, 所以需要先写css- loader,再写style-loader - 安装
解析css
npm i style-loader css-loader -D
解析less
npm i less less-loader -D
- 使用
// webpack.config.js 中
const path = require('path')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.css$/,
// 解析css的配置, 解析顺序从后到前
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader'
]
}
]
}
}
解析图片和字体
- 介绍
file-loader
和url-loader
均可处理图片和字体
url-loader
还可以设置较小资源,如小图片和小字体文件,自动base64,底层也是使用file-loader
- 安装
2.1 安装file-loader
npm i file-loader -D
2.2 安装url-loader
npm i url-loader -D
- 使用
3.1 使用file-loader解析
// webpack.config.js 中
const path = require('path')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.(png|jpg|svg|gif|jpeg)$/, // 解析图片的配置
use: 'file-loader'
},
{
test: /\.(woff|woff2|eot|ttf)$/, // 解析字体的配置
use: 'file-loader'
}
]
}
}
3.2 使用url-loader解析
// webpack.config.js 中
const path = require('path')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.(png|jpg|svg|gif|jpeg)$/, // 解析图片的配置
use: [{
loader: 'url-loader',
options: {
limit: 10240 // limit单位: 字节, 10240为10k, 文件大小小于该值, 自动进行base64,进行资源内联
}
}]
},
{
test: /\.(woff|woff2|eot|ttf)$/, // 解析字体的配置
use: [{
loader: 'url-loader',
options: {
limit: 10240
}
}]
}
]
}
}
- 字体文件的引入
4.1 字体文件,如FontAwesome.otf
,复制到指定文件夹中,
4.2 webpack.config.js中设置解析字体的配置
4.3 样式文件引入字体族
// 定义字体
@font-face {
font-family: 'FontAwesome',
src: url('./learnRoad/20190611-simple_demo/src/static/FontAwesome.otf') format('truetype');
}
// 使用
div {
font-size: 30px;
color: 'red';
font-family: 'FontAwesome'
}
文件监听
- 介绍
文件监听是在发现源码发生变化时, 自动重新创建出新的输出文件,文件保存在本地磁盘 - package.json中开启
介绍: 启动webpack命令时, 带上–watch参数
方法: package.json中的scripts增加"watch": "webpack --watch"
, 编译时使用npm run watch
缺点: 每次内容保存后,需要手动刷新浏览器 - webpack.config.js中开启
3.1 文件监听的原理分析
轮询判断文件的最后编译时间是否变化
某个文件发生变化, 先缓存起来,等待aggregateTimeout时间,再告诉监听者
3.2 方法
在配置webpack.config.js中设置watch:true, 并配置watchOption, 运行npm run build
module.exports={
// 默认false, 不开启文件监听
watch: true,
// watch: true时, watchOptions才有意义
watchOptions: {
// 默认为空, 不监听的文件或文件夹, 支持正则匹配
ignored: /node_modules/,
// 监听到变化后,等待300ms再去执行,默认300
aggregateTimeout: 300,
// 判断文件是否发生变化是通过不断轮询系统指定文件有没变化实现变化的, 默认每秒问1000次
poll: 1000
}
}
热更新
- 介绍
1.1 开启方式
使用webpack-dev-serve
使用webpack-dev-middleware
1.2 特点
WDS/WDM 不刷新浏览器
不输出文件, 而是放到内存中
配合使用webpack内置的HotModuleReplacementPlugin插件 - 安装
npm i webpack-dev-server -D
npm i webpack-dev-middleware-D
- 使用
webpack-dev-sever
3.1 package.json中
package.json中的scripts增加"dev": "webpack-dev-server --open"
, 编译时使用npm run dev
注: open的意思为构建完成后自动开启浏览器
3.2 webpack.config.js中
mode属性, 改为development
引入webpack
plugins中引入使用HotModuleReplacementPlugin插件
配置devServer,设置基础目录,并开启热更新
// webpack.config.js 中
const path = require('path')
const webpack = requre('webpack')
module.exports = {
mode: 'development',
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new webpack.HotModuleRelacementPlugin() // 热更新插件
],
devServer: {
contentBase: './dist', // 配置热更新基础文件
hot: true // 开启热更新
}
}
- 使用
webpack-dev-middleware
4.1 介绍
WDM将webpack输出的文件输给服务器, 适用于灵活的定制场景
4.2 使用方法
创建node_server
// demo
const express = require('express')
const webpack = require('webpack')
const webpackDevMiddleware = require('webpack-dev-middleware')
const app = express()
const config = require('./learnRoad/webpack.config.js')
const compiler = webpack(config)
app.use(webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath
}));
app.listen(3000, function() {
console.log("example app listening on port 3000")
})
文件指纹
-
介绍
含义: 打包输出的文件名的后缀
作用: 用于版本管理, 修改的文件通过新文件指纹表示新文件, 没修改的文件其文件指纹仍然没变, 页面加载时仍然可从浏览器缓存中获取 -
如何生成
2.1 Hash: 和整个项目的构建相关, 只要项目文件有修改, 整个项目构建的hash值就会更改
缺点: 只要有一个文件更改, 整个项目的文件的hash就会改
2.2 Chunkhash: 和webpack打包的chunk有关, 不同的entry会生成不同的chunk,
chunk指模块, 不同模块需要保持相对独立, 适用于多个页面打包隔离,适用js文件
2.3 Contenthash: 根据文件内容来定义hash, 文件内容不变, 则Contenthash不变, 适用于css使用 -
常见占位符及含义
[ext]
: 资源后缀名
[name]
: 文件名称
[path]
: 文件的相对路径
[folder]
: 文件所在的文件夹
[contenthash]
: 文件内容的hash, 默认是md5生成
[hash]
: 文件内容的hash, 默认实md5生成
[emoji]
: 一个随机的指定文件内容的emoji -
JS文件指纹设置
通过output的filename, 使用[Chunkhash]
// webpack.prod.js 中
const path = require('path')
module.exports = {
entry: {
main: './src/main.js',
app: './src/app.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name][chunkhash:8].js' // 8指的是取Chunkhash的前8位
}
}
- css文件指纹设置
安装插件MiniCssExtracPlugin :npm i MiniCssExtracPlugin -D
使用[Contenthash], 将css样式抽离成一个独立文件
注意: 将loader中解析css的style-loader
去掉, 因为其将css合入html的head中, 与插件MiniCssExtracPlugin功能冲突
// webpack.prod.js 中
const path = require('path')
const MiniCssExtracPlugin = require('mini-css-extract-plugin')
module.exports = {
entry: {
main: './src/main.js',
app: './src/app.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name][chunkhash:8].js'
},
plugins: [
new MiniCssExtracPlugin({
path: path.join(__dirname, 'dist') // 指定目录路径
filename: `css/[name][contenthash:8].css` // name对应entry中的key值
})
]
}
- 图片和字体文件的文件指纹设置
设置file-loader
或url-loader
的name , 使用[hash]
// 以url-loader为例
// webpack.prod.js 中
const path = require('path')
module.exports = {
entry: {
main: './src/main.js',
app: './src/app.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name][chunkhash:8].js'
},
module: {
rules:[
{
test: /\.(png|svg|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10240, // file-loader没有limit属性
path: path.join(__dirname, 'dist') // 指定目录
name: 'img/[name][hash:8].[ext]' // 放在img文件夹下, 带md5的前8位值
}
}
]
}
]
}
}
代码压缩
- js文件的压缩
内置了 uglifyjs-webpack-plugin, 编译出来就会自动压缩 - css文件的压缩
使用optimize-css-assets-webpack-plugin
, 同时使用cssnano
这个处理器
安装插件:npm i optimize-css-assets-webpack-plugin -D
// webpack.prod.js 中
const path = require('path')
const OptimizeCssAssetsPlugin = require('optimize-css-assets-plugin')
module.exports = {
entry: {
main: './src/main.js',
app: './src/app.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name][chunkhash:8].js'
},
plugins: [
new OptimizeCssAssetsPlugin({
assetNameRegExp:/\.css$/,
cssProcessor: require('cssnano')
})
]
}
- html文件的压缩
修改html-webpack-plugin
, 设置压缩参数
安装npm i html-webpack-plugin -D
// webpack.prod.js 中
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: {
main: './src/main.js',
app: './src/app.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name][chunkhash:8].js'
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, 'dist/main.html'), // html文件的模板,要与入口文件名字一致
path: path.join(__dirname, 'dist'),
filename: 'main.html', // 指定打包出来的文件的名称,要与入口文件名字一致
chunks: ['main'], // 生成的html文件的chunk,要与入口文件名字一致
inject: true, // 打包出来的chunk会主动注入到html页面中
minify: {
html5: true,
collapseWhitespace: true,
preserveLineBreaks: false,
minifyCss: true,
minifyJS: true,
removeComments: false
}
})
]
}
自动清理构建目录产物
- 当前构建时遇到的问题
每次构建的时候不会自动清理目录, 造成构建的输出目录output文件越来越多
1.2 法一: 手动删除编译文件dist
运行编译前, 先执行前置命令行
// package.json的scripts中,给build命令的添加前置命令
`"build": "rm -rf ./dist && webpack --config webpack.prod.js" ` // 或
`"build": "rimraf ./dist && webpack --config webpack.prod.js" `
1.3 法二: 自动清理构建目录
使用clean-webpack-plugin
安装 npm i clean-webpack-plugin -D
每次执行npm run build
都会先想dist文件夹中的文件删除, 并重新生成编译文件
// webpack.prod.js 中
const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin')
module.exports = {
entry: {
main: './src/main.js',
app: './src/app.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name][chunkhash:8].js'
},
plugins: [
new CleanWebpackPlugin()
]
}