
初始指令
开发环境:webpack ./src/index.js -o ./build/index.js --mode=development生产环境:webpack ./src/index.js -o ./build/index.js --mode=production# 注意点,这里设置的mode变量,在webpack配置文件中需要通过argv这个参数获取,# 而不是直接通过process.env.NODE_ENV获取module.exports = (env, argv) => {const env = argv.mode}
配置文件
webpack.config.js
loader
- less-loader
- 将less文件编译成css文件
- 需要下载 less-loader、less俩个npm包
- css-loader
- 将css文件变成commonjs模块加载到js文件中,里面的内容是样式字符串
- style-loader
- 创建style标签,将js中的样式资源插入到head标签中
- url-loader
- 图片文件处理
- file-loader
- 处理文件
一般url-loader和file-loader一起配合使用
- postcss-loader
- webpack和postcss预处理器结合
- eslint-loader
- 语法检查
babel-loader
html-webpack-plugin
- 默认会创建一个空的Html文件,自动引入打包输出的所有资源文件
- mini-css-extract-plugin
- css单独打包成一个文件
- 该插件使用不能和style-loader一起使用
- optimize-css-assets-webpack-plugin
- 压缩css文件 ```javascript const { resolve } = require(‘path’); const HtmlWebpackPlugin = require(‘html-webpack-plugin’) const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’) const OptimizeCssAssetsWebpackPlugin = require(‘optimize-css-assets-webpack-plugin’)
module.exports = { entry: ‘./src/index.js’, output: { filename: ‘build.js’, path: resolve(dirname, ‘build’), environment: { arrowFunction: false, } }, module: { rules: [ { test: /.css$/, use: [ // ‘style-loader’, // 样式存放在style标签中 MiniCssExtractPlugin.loader, // 样式存放在单独css文件中 ‘css-loader’, // css-loader { // postcss-loader loader: ‘postcss-loader’, options: { postcssOptions: { ident: ‘postcss’, plugins: () => [ require(‘postcss-preset-env’)() ] } } } ] }, { test: /.less/, use: [ // ‘style-loader’, // 样式存放在style标签中 MiniCssExtractPlugin.loader, // 样式存放在单独css文件中 ‘css-loader’, // css-loader { // postcss-loader loader: ‘postcss-loader’, options: { postcssOptions: { ident: ‘postcss’, plugins: () => [ require(‘postcss-preset-env’)() ] } } }, ‘less-loader’ // less-loader ] }, // 下面的loader只能处理js和css文件中使用的图片资源,但是在html中使用图片资源时,不能够被正确的处理 { test: /.(jpg|png|gif)$/, loader: ‘url-loader’, options: { limit: 10 * 1024, // 当图片资源小于10kb时,我们使用base64来替代图片 // url-loader 默认使用esmodule来进行解析, // html-loader默认使用的是commonjs来解析, 所以我们关闭url-loader的es6模块化 esModule: false, name: ‘[hash:10].[ext]’, output: ‘images’ } }, { test: /.html$/, loader: ‘html-loader’,// 解决上面图片资源直接在html文件中引入问题 }, { exclude: /.(css|js|html|less|jpg|png|gif)$/, loader: ‘file-loader’, options: { output: ‘media’ name: ‘[hash:10].[ext]’ } }, { test: /.js$/, exclude: /node_modules/, loader: ‘eslint-loader’, // 需要在package.json中配置eslint的风格 enforce: ‘pre’, // 当loader中有俩个相同的文件匹配时,通过这个配置指定loader执行先后顺序 options: { // 自动修复 fix: true } }, { test: /.js$/, exclude: /node_modules/, loader: ‘babel-loader’, options: { presets: [[ ‘@babel/preset-env’, { useBuiltIns: ‘usage’, // 指定core-js版本 corejs: { version: 3 }, // 指定兼容性支持到哪个版本浏览器 targets: { chrome: ‘60’, firefox: ‘60’, ie: ‘9’, safari: ‘10’, edge: ‘17’ } } ]] } } ] }, plugins: [ new HtmlWebpackPlugin({ template: ‘./src/index.html’ // 复制模版文件,并自动引入静态资源 minify: { collapseWhitespace: true, // 移除空格 removeComments: true, // 移除注释 } }), new MiniCssExtractPlugin({ filename: ‘css/index.css’ }), new OptimizeCssAssetsWebpackPlugin() ], mode: ‘development’, // production devServer: { contentBase: resolve(dirname, ‘build’), compress true, port: 3000, hot: true, // 开启HMR open: true // 自动打开浏览器 } }
<a name="rFzxP"></a>
#### devServer
自动编译,在开发过程中每次修改代码之后不需要重新打包
```javascript
启动指令
npx webpack-dev-server
需要通过npm下载webpack-dev-server
css兼容性处理
postcss -> postcss-loader -> post-preset-env
post-preset-env 帮postcss找到package.json中browserlist里面的配置,通过配置加载指定的css兼容性样式
browserslist配置参考链接
// package.json
{
"browserslist": { // 下面俩个模式根据process.env.NODE_ENV来区分的
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
"production": [
">0.2%",
"not dead",
"not op_mini all"
]
}
}
语法检查
eslint-loader
一般使用airbnb的代码风格
yarn add eslint-config-airbnb-base eslint-plugin-import eslint
// package.json
{
"eslintConfig": {
"extends": "airbnb-base",
"env": {
"browser": true
}
}
}
压缩
js压缩:mode设置为production即可
html压缩:设置HtmlWebpackPlugin的minify配置
性能优化
HMR
模块热更新:一个模块发生变化,只会重新打包这一个模块
- css文件使用:开发环境下使用style-loader来代替MiniCssExtractPlugin.loader,style-loader为我们实现了HMR功能
js文件使用:默认不能使用
- 需要修改js代码
if(module.hot) { module.hot.accept('./xxx.js', function() { // 执行该模块中的方法,重新调用 }) }
- 需要修改js代码
html文件使用:默认不能使用
- 解决:修改entry入口[‘./src/index.js’,’./src/index.html’]
- 但是一般html文件不需要做HMR ```json webpack.dev.config.js
const { resolve } = require(‘path’); const HtmlWebpackPlugin = require(‘html-webpack-plugin’) const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’) const OptimizeCssAssetsWebpackPlugin = require(‘optimize-css-assets-webpack-plugin’)
module.exports = { entry: [‘./src/index.js’,’./src/index.html’], output: { filename: ‘build.js’, path: resolve(dirname, ‘build’) }, module: { rules: [ { test: /.css$/, use: [ ‘style-loader’, // 样式存放在style标签中 // MiniCssExtractPlugin.loader, // 样式存放在单独css文件中 ‘css-loader’, // css-loader { // postcss-loader loader: ‘postcss-loader’, options: { postcssOptions: { ident: ‘postcss’, plugins: () => [ require(‘postcss-preset-env’)() ] } } } ] }, { test: /.less/, use: [ ‘style-loader’, // 样式存放在style标签中 // MiniCssExtractPlugin.loader, // 样式存放在单独css文件中 ‘css-loader’, // css-loader { // postcss-loader loader: ‘postcss-loader’, options: { postcssOptions: { ident: ‘postcss’, plugins: () => [ require(‘postcss-preset-env’)() ] } } }, ‘less-loader’ // less-loader ] }, // 下面的loader只能处理js和css文件中使用的图片资源,但是在html中使用图片资源时,不能够被正确的处理 { test: /.(jpg|png|gif)$/, loader: ‘url-loader’, options: { limit: 10 * 1024, // 当图片资源小于10kb时,我们使用base64来替代图片 // url-loader 默认使用esmodule来进行解析, // html-loader默认使用的是commonjs来解析, 所以我们关闭url-loader的es6模块化 esModule: false, name: ‘[hash:10].[ext]’, output: ‘images’ } }, { test: /.html$/, loader: ‘html-loader’,// 解决上面图片资源直接在html文件中引入问题 }, { exclude: /.(css|js|html|less|jpg|png|gif)$/, loader: ‘file-loader’, options: { output: ‘media’ name: ‘[hash:10].[ext]’ } }, { test: /.js$/, exclude: /node_modules/, loader: ‘eslint-loader’, // 需要在package.json中配置eslint的风格 enforce: ‘pre’, // 当loader中有俩个相同的文件匹配时,通过这个配置指定loader执行先后顺序 options: { // 自动修复 fix: true } }, { test: /.js$/, exclude: /node_modules/, loader: ‘babel-loader’, options: { presets: [[ ‘@babel/preset-env’, { useBuiltIns: ‘usage’, // 指定core-js版本 corejs: { version: 3 }, // 指定兼容性支持到哪个版本浏览器 targets: { chrome: ‘60’, firefox: ‘60’, ie: ‘9’, safari: ‘10’, edge: ‘17’ } } ]] } } ] }, plugins: [ new HtmlWebpackPlugin({ template: ‘./src/index.html’ // 复制模版文件,并自动引入静态资源 minify: { collapseWhitespace: true, // 移除空格 removeComments: true, // 移除注释 } }), new MiniCssExtractPlugin({ filename: ‘css/index.css’ }), new OptimizeCssAssetsWebpackPlugin() ], mode: ‘development’, // production devServer: { contentBase: resolve(dirname, ‘build’), compress true, port: 3000, hot: true, // 开启HMR open: true // 自动打开浏览器 } }
<a name="knHFB"></a>
### source-map
开发环境一般使用:eval-source-map<br /> 生产环境一般使用:source-map / cheap-module-source-map
```json
module.exports = {
devtool: 'source-map' // 可选项见下方
}
- source-map
- 错误代码准确信息 和 源代码的错误信息位置
- inline-source-map
- 只生成一个内联source-map
- 错误代码准确信息 和 源代码的错误信息位置
- hidden-source-map
- 提示错误原因,但是没有错误位置,不能追踪源代码错误,只能提示到构建后代码的错误
- eval-source-map
- 每一个文件都生成对应的source-map
- 错误代码准确信息 和 源代码的错误信息位置
- nosources-source-map
- 错误代码准确信息 ,但是找不到源代码
- cheap-source-map
const { resolve } = require(‘path’); const HtmlWebpackPlugin = require(‘html-webpack-plugin’) const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’) const OptimizeCssAssetsWebpackPlugin = require(‘optimize-css-assets-webpack-plugin’)
module.exports = { entry: [‘./src/index.js’,’./src/index.html’], output: { filename: ‘build.js’, path: resolve(dirname, ‘build’) }, module: { rules: [ { test: /.js$/, exclude: /node_modules/, loader: ‘eslint-loader’, // 需要在package.json中配置eslint的风格 enforce: ‘pre’, // 当loader中有俩个相同的文件匹配时,通过这个配置指定loader执行先后顺序 options: { // 自动修复 fix: true } }, { oneOf: [ { test: /.css$/, use: [ ‘style-loader’, // 样式存放在style标签中 // MiniCssExtractPlugin.loader, // 样式存放在单独css文件中 ‘css-loader’, // css-loader { // postcss-loader loader: ‘postcss-loader’, options: { postcssOptions: { ident: ‘postcss’, plugins: () => [ require(‘postcss-preset-env’)() ] } } } ] }, { test: /.less/, use: [ ‘style-loader’, // 样式存放在style标签中 // MiniCssExtractPlugin.loader, // 样式存放在单独css文件中 ‘css-loader’, // css-loader { // postcss-loader loader: ‘postcss-loader’, options: { postcssOptions: { ident: ‘postcss’, plugins: () => [ require(‘postcss-preset-env’)() ] } } }, ‘less-loader’ // less-loader ] }, // 下面的loader只能处理js和css文件中使用的图片资源,但是在html中使用图片资源时,不能够被正确的处理 { test: /.(jpg|png|gif)$/, loader: ‘url-loader’, options: { limit: 10 * 1024, // 当图片资源小于10kb时,我们使用base64来替代图片 // url-loader 默认使用esmodule来进行解析, // html-loader默认使用的是commonjs来解析, 所以我们关闭url-loader的es6模块化 esModule: false, name: ‘[hash:10].[ext]’, output: ‘images’ } }, { test: /.html$/, loader: ‘html-loader’,// 解决上面图片资源直接在html文件中引入问题 }, { exclude: /.(css|js|html|less|jpg|png|gif)$/, loader: ‘file-loader’, options: { output: ‘media’ name: ‘[hash:10].[ext]’ } }, { test: /.js$/, exclude: /node_modules/, loader: ‘babel-loader’, options: { presets: [[ ‘@babel/preset-env’, { useBuiltIns: ‘usage’, // 指定core-js版本 corejs: { version: 3 }, // 指定兼容性支持到哪个版本浏览器 targets: { chrome: ‘60’, firefox: ‘60’, ie: ‘9’, safari: ‘10’, edge: ‘17’ } } ]] } } ] } ] }, plugins: [ new HtmlWebpackPlugin({ template: ‘./src/index.html’ // 复制模版文件,并自动引入静态资源 minify: { collapseWhitespace: true, // 移除空格 removeComments: true, // 移除注释 } }), new MiniCssExtractPlugin({ filename: ‘css/index.css’ }), new OptimizeCssAssetsWebpackPlugin() ], mode: ‘development’, // production devServer: { contentBase: resolve(dirname, ‘build’), compress true, port: 3000, hot: true, // 开启HMR open: true // 自动打开浏览器 } }
<a name="w4WTp"></a>
### 缓存
- 针对babel开启构建缓存
- cacheDirectory: true
- 通过hash后缀进行静态资源缓存
- hash 每一次编译都会生成一个新的hash
- chunkhash 根据打包的chunk生成hash值
- 可能由于代码里引入了别的模块导致的变化而改变hash值
- contenthash 根据文件内容变动生成hash值
```json
webpack.dev.config.js
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
module.exports = {
entry: ['./src/index.js','./src/index.html'],
output: {
filename: 'build.[contenthash:10].js',
path: resolve(__dirname, 'build')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'eslint-loader', // 需要在package.json中配置eslint的风格
enforce: 'pre', // 当loader中有俩个相同的文件匹配时,通过这个配置指定loader执行先后顺序
options: {
// 自动修复
fix: true
}
},
{
oneOf: [
{
test: /\.css$/,
use: [
'style-loader', // 样式存放在style标签中
// MiniCssExtractPlugin.loader, // 样式存放在单独css文件中
'css-loader', // css-loader
{ // postcss-loader
loader: 'postcss-loader',
options: {
postcssOptions: {
ident: 'postcss',
plugins: () => [
require('postcss-preset-env')()
]
}
}
}
]
},
{
test: /\.less/,
use: [
'style-loader', // 样式存放在style标签中
// MiniCssExtractPlugin.loader, // 样式存放在单独css文件中
'css-loader', // css-loader
{ // postcss-loader
loader: 'postcss-loader',
options: {
postcssOptions: {
ident: 'postcss',
plugins: () => [
require('postcss-preset-env')()
]
}
}
},
'less-loader' // less-loader
]
},
// 下面的loader只能处理js和css文件中使用的图片资源,但是在html中使用图片资源时,不能够被正确的处理
{
test: /\.(jpg|png|gif)$/,
loader: 'url-loader',
options: {
limit: 10 * 1024, // 当图片资源小于10kb时,我们使用base64来替代图片
// url-loader 默认使用esmodule来进行解析,
// html-loader默认使用的是commonjs来解析, 所以我们关闭url-loader的es6模块化
esModule: false,
name: '[hash:10].[ext]',
output: 'images'
}
},
{
test: /\.html$/,
loader: 'html-loader',// 解决上面图片资源直接在html文件中引入问题
},
{
exclude: /\.(css|js|html|less|jpg|png|gif)$/,
loader: 'file-loader',
options: {
output: 'media'
name: '[hash:10].[ext]'
}
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [[
'@babel/preset-env',
{
useBuiltIns: 'usage',
// 指定core-js版本
corejs: {
version: 3
},
// 指定兼容性支持到哪个版本浏览器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
safari: '10',
edge: '17'
}
}
]],
cacheDirectory: true
}
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html' // 复制模版文件,并自动引入静态资源
minify: {
collapseWhitespace: true, // 移除空格
removeComments: true, // 移除注释
}
}),
new MiniCssExtractPlugin({
filename: 'css/index.[contenthash:10].css'
}),
new OptimizeCssAssetsWebpackPlugin()
],
}
tree shaking
- 去除无用的js代码,减少代码体积
- 使用production模式
- 使用ES6模块化
- 可能出现的问题:会将css/less等直接导入的文件丢失
- 可以通过在package.json中配置”sideEffects”: [“.css”, “.less”, “./src/polyfill.js”]
- 或者可以通过 import styles from ‘./xxx.less’ 这种css-module的方式去使用
- 副作用配置链接
code split
代码分割
- 可以将node_modules中代码单独打包成一个chunk输出
- 自动分析多入口文件,会将公共文件单独打包成一个chunk
当我们在js代码中使用import(‘xxxx.js’) 这种语法的时候,会默认将我们引入的js模块单独打包成一个chunk,在react或者vue中我们router中import组件和这种方式一致
module.exports = {
optimization: {
splitChunks: {
chunks: 'all'
}
}
}
多进程打包
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'thread-loader',
options: {
workers: 2
}
},
{
loader: 'babel-loader',
options: {
presets: [[
'@babel/preset-env',
{
useBuiltIns: 'usage',
// 指定core-js版本
corejs: {
version: 3
},
// 指定兼容性支持到哪个版本浏览器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
safari: '10',
edge: '17'
}
}
]],
cacheDirectory: true
}
}
],
}
externals
忽略第三方库被打包,需要通过cdn的方式去引入依赖包
externals: {
'jquery': 'jQuery
}
dll
打包一次第三方的包或者库,后面不再打包
最后配置
webpack.dev.config.js
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
module.exports = {
entry: ['./src/index.js'],
output: {
filename: 'js/[name].[contenthash:10].js',
path: resolve(__dirname, 'build')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'eslint-loader', // 需要在package.json中配置eslint的风格
enforce: 'pre', // 当loader中有俩个相同的文件匹配时,通过这个配置指定loader执行先后顺序
options: {
// 自动修复
fix: true
}
},
{
oneOf: [
{
test: /\.css$/,
use: [
'style-loader', // 样式存放在style标签中
// MiniCssExtractPlugin.loader, // 样式存放在单独css文件中
'css-loader', // css-loader
{ // postcss-loader
loader: 'postcss-loader',
options: {
postcssOptions: {
ident: 'postcss',
plugins: () => [
require('postcss-preset-env')()
]
}
}
}
]
},
{
test: /\.less/,
use: [
'style-loader', // 样式存放在style标签中
// MiniCssExtractPlugin.loader, // 样式存放在单独css文件中
'css-loader', // css-loader
{ // postcss-loader
loader: 'postcss-loader',
options: {
postcssOptions: {
ident: 'postcss',
plugins: () => [
require('postcss-preset-env')()
]
}
}
},
'less-loader' // less-loader
]
},
// 下面的loader只能处理js和css文件中使用的图片资源,但是在html中使用图片资源时,不能够被正确的处理
{
test: /\.(jpg|png|gif)$/,
loader: 'url-loader',
options: {
limit: 10 * 1024, // 当图片资源小于10kb时,我们使用base64来替代图片
// url-loader 默认使用esmodule来进行解析,
// html-loader默认使用的是commonjs来解析, 所以我们关闭url-loader的es6模块化
esModule: false,
name: '[hash:10].[ext]',
output: 'images'
}
},
{
test: /\.html$/,
loader: 'html-loader',// 解决上面图片资源直接在html文件中引入问题
},
{
exclude: /\.(css|js|html|less|jpg|png|gif)$/,
loader: 'file-loader',
options: {
output: 'media'
name: '[hash:10].[ext]'
}
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [[
'@babel/preset-env',
{
useBuiltIns: 'usage',
// 指定core-js版本
corejs: {
version: 3
},
// 指定兼容性支持到哪个版本浏览器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
safari: '10',
edge: '17'
}
}
]],
cacheDirectory: true
}
}
]
}
]
},
optimization: {
splitChunks: {
chunks: 'all'
}
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html' // 复制模版文件,并自动引入静态资源
minify: {
collapseWhitespace: true, // 移除空格
removeComments: true, // 移除注释
}
}),
new MiniCssExtractPlugin({
filename: 'css/index.[contenthash:10].css'
}),
new OptimizeCssAssetsWebpackPlugin()
],
mode: 'development', // production
devServer: {
contentBase: resolve(__dirname, 'build'),
compress true,
port: 3000,
hot: true, // 开启HMR
open: true // 自动打开浏览器
}
}

