22.Weppack生产环境优化
模式mode
为不同工作环境创建不同配置
- 配置文件根据环境不同导出不同配置
- 一个环境对应一个配置文件
yarn webpack
yarn webpack --env production
const webpack = require('webpack')
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const { compilation } = require('webpack')
class MyPlugin {
apply(compiler) {
console.log('MyPlugin run')
compiler.hooks.emit.tap('MyPlugin', compilation => {
for (const name in compilation.assets) {
// console.log(name)
// console.log(compilation.assets[name].source())
if (name.endsWith('.js')) {
const contents = compilation.assets[name].source()
// 替换代码中的注释
const withoutComments = contents.replace(//**+*//g, '')
// 覆盖原有内容
compilation.assets[name] = {
source: () => withoutComments,
size: () => withoutComments.length
}
}
}
})
}
}
module.exports = (env, argv) => {
const config = {
mode: 'none',
entry: './src/main.js',
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist'),
// publicPath: 'dist/'
},
devServer: {
contentBase: '/public',
// http://localhost:8080/api/users ---> https://api.github.com/api/users
proxy: {
'/api': {
target: 'https://api.github.com',
// http://localhost:8080/api/users ---> https://api.github.com/users
pathRewrite: {
'^api': ''
},
// 不能使用 localhost:8080 作为请求 GitHub 的主机名
changeOrigin: true
},
},
hot: true
// hotOnly: true // 只使用 HMR,不会 fallback 到 live reloading
},
devtool: 'source-map',
module: {
rules: [ // 其他模块加载规则
{
test: /.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
},
{
test: /.css$/,
use: [
'style-loader',
'css-loader'
]
},
// {
// test: /.png$/,
// use:'file-loader'
// }
{
test: /.png$/,
use: {
loader: 'url-loader',
options: {
limit: 10 * 1024, // 10kb以下文件采用url-loader超出采用file-loader
esModule: false, // 打包图片object%20Module
}
}
},
{
test: /.html$/,
use: {
loader: 'html-loader'
}
}
]
},
plugins: [
// 用于生成 index.html
new HtmlWebpackPlugin({
title: 'Webpack Plugin Sample', // 设置标题
meta: {
viewport: 'width=device-width'
},
template: './index.html' // 生成html的模板
}),
// 用于生成 about.html
new HtmlWebpackPlugin({
filename: 'about.html'
}),
new MyPlugin(),
new webpack.HotModuleReplacementPlugin()
]
}
if (env === 'production') {
config.mode = 'production'
config.devtool = false
config.plugins = [
..config.plugins,
new CleanWebpackPlugin(),
new CopyWebpackPlugin([
// public/** public下的文件会拷贝到dist
'public'
]),
]
}
return config
}
23.多配置文件
yarn webpack --config webpack.prod.js
yarn webpack --config webpack.dev.js
"scripts": {
"build": "webpack --config webpack.prod.js --watch"
}
webpack.common.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode: 'none',
entry: './src/main.js',
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist'),
// publicPath: 'dist/'
},
devServer: {
contentBase: '/public',
// http://localhost:8080/api/users ---> https://api.github.com/api/users
proxy: {
'/api': {
target: 'https://api.github.com',
// http://localhost:8080/api/users ---> https://api.github.com/users
pathRewrite: {
'^api': ''
},
// 不能使用 localhost:8080 作为请求 GitHub 的主机名
changeOrigin: true
},
},
hot: true
// hotOnly: true // 只使用 HMR,不会 fallback 到 live reloading
},
devtool: 'source-map',
module: {
rules: [ // 其他模块加载规则
{
test: /.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
},
{
test: /.css$/,
use: [
'style-loader',
'css-loader'
]
},
// {
// test: /.png$/,
// use:'file-loader'
// }
{
test: /.png$/,
use: {
loader: 'url-loader',
options: {
limit: 10 * 1024, // 10kb以下文件采用url-loader超出采用file-loader
esModule: false, // 打包图片object%20Module
}
}
},
{
test: /.html$/,
use: {
loader: 'html-loader'
}
}
]
},
plugins: [
// 用于生成 index.html
new HtmlWebpackPlugin({
title: 'Webpack Plugin Sample', // 设置标题
meta: {
viewport: 'width=device-width'
},
template: './index.html' // 生成html的模板
}),
// 用于生成 about.html
new HtmlWebpackPlugin({
filename: 'about.html'
})
]
}
webpack.dev.js
yarn add webpack-merge --dev
const common = require('./webpack.common')
const { merge } = require('webpack-merge')
const webpack = require('webpack')
module.exports = merge(common, {
mode: 'production',
plugins: [
new webpack.HotModuleReplacementPlugin()
]
})
webpack.prod.js
const common = require('./webpack.common')
const { merge } = require('webpack-merge')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = merge(common, {
mode: 'production',
plugins: [
new CleanWebpackPlugin(),
new CopyWebpackPlugin(['public'])
]
})
24.DefinePlugin
为代码注入全局成员
const webpack = require('webpack')
plugins: [
new webpack.DefinePlugin({
// 值要求的是一个代码片段
API_BASE_URL: JSON.stringify('https://api.example.com')
// API_BASE_URL: '*http://api.example.com*' // api服务地址
})
]
25.Tree-shaking
【摇掉】代码中未引用的部分
未引用代码(dead-code)
生产模式自动开启
一组功能搭配后的使用效果
optimization: {
usedExports: true, // 只导出外部使用的成员
minimize: true // 压缩
}
26.合并模块(Scope Hoisting)
optimization: {
usedExports: true, // 只导出外部使用的成员
concatenateModules:true, // 合并模块
minimize: true // 压缩
}
27.Webpack Tree Shaking 与 Babel
Webpack Tree Shaking使用ESM
Babel转成CommonJS
最新版本的webpack不会让ESM实效
presets: [
['@babel/preset-env', { modules: 'commonjs' }]
]
presets: [
['@babel/preset-env', { modules: false }]
]
28.Webpack sideEffects
// package.json
"sideEffects": [
"./src/extend.js",
"./src/global.css"
]
29.Webpack 代码分割
并不是每个模块在启动时都需要
分包,按需加载(Code Splitting)
HTTP1.1缺点
同域并行请求限制
每次请求都会有一定的延迟
请求的Header浪费带宽流量