webpack@4.41.2

  • 浏览器厂商前缀
1
2
3
4
"browserslist": [
"> 1%",
"last 2 versions"
]
  • src 源代码 里面的代码 不能够直接在浏览器上运行的
  • css 模块化
1
2
3
4
5
6
7
{
loader: 'css-loader',
options: {
importLoaders: 2,
modules: true // css模块化
}
}
  • html-webpack-plugin
    • 自动生成html文件
  • clean-webpack-plugin
    • 每次清除已打包文件
  • HMR 热更新
    • 页面重新加载导致状态丢失
  • JS 热更新
1
2
3
4
module.hot.accept('./sth-Js', () => {
// 对 sth JS文件不自动刷新
sth()
})
  • Babel处理ES6代码
  • @babel-loader @babel/preset-env@babel/core
  • import '@babel/polyfill'
    • 打个补丁
    • 但会污染全局环境
  • core-js
    • 具有所有的es5 polyfill(除了function*)
  • regengeator + core-js = 所有es6特性被低版本浏览器支持 = @babel/polyfill
  • .babelrc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
// presets: [['@babel/preset-env', {
// useBuiltIns: 'usage', // 按需引入polyfill
// corejs: 3
// }]] // 添加预设,babel-loader并不能直接将es6->es5
plugins: [
['@babel/plugin-transform-runtime', // 避免代码冲突
{
"absoluteRuntime": false,
"corejs": 3,
"helpers": true,
"regenerator": true,
"version": "7.0.0-beta.0"
}
]
]
}
  • vue-loader | vue-template-complier

  • webpack-dev-server

    • 看不到打包文件,会将打包文件放到内存当中
  • Tree Shaking

    • 只支持 ES Module | 静态引入,编译时引入
    • 不支持 CommonJS | 动态引入,执行时引入
    • optimization
      • production 模式下自动开启
  • package.json

    • sideEffects [‘@bundle’] 取消 Tree Shaking 的影响
  • 不同的打包模式

    • webpack-merge
    • webpack.pro.js
    • webpack.dev.js
    • webpack.test.js
  • 代码分割

    • Code Splitting
    • splitChunks默认异步代码分割
    • import(/* webpackChunkName: “lodash”*/‘lodash’)
      • webpackChunkName 自定义打包名
  • 懒加载

    • 异步引入
  • CSS 代码分割

    • mini-css-extract-plugin@1.3.9
    • “sideEffects”: [“*.css”]
      • production mode 自动tree-shaking 未使用文件
    • css-minimizer-webpack-plugin@1.2.0
      • CSS 代码压缩
  • 自动加载模块,不必在任何地方都import或require个模块

    • webpack.ProvidePlugin({key,value})
  • 生产 开发 模式公用

    • babel-loader
    • noParse
    • IgnorePlugin
    • ParallelUglifyPlugin
  • 开发模式

    • 自动刷新、热更新 Webpack.HotModuleReplacementPlugin
    • DllReferencePlugin React Vue 预先打包一次
  • 减小产出代码体积

    • 代码体积小,加载速度更快

    • 合理分包,不重复加载

    • 程序运行速度更快,内存占用更小

    • 图片比较小的时候可以采用base64编码 url-loader

    • cdn 引入 加速

    • scope hoisting 作用域提升 webpack@4.41.2 默认配置

1
2
3
plugins:[
new webpack.optimize.ModuleConcatenationPlugin();
]
  • webpack.base.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
const path = require('path');

const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

// 多进程打包
const HappyPack = require('happypack')

module.exports = {
// noParse: [/vue\.min\.js$/], // 忽略解析
entry: {
main: './src/index.js',
},
module: {
rules: [
// {
// test: /\.js$/,
// use: ['happypack/loader?id=babel'] // 不再需要babel-loader编译
// },
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.(png|jpg|jpeg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
// 图片小于10kb 使用base64 格式产出
// 大于10kb 像file-loader,使用 url 格式产出
name: '[path][name].[ext]',
outputPath: 'images',
limit: 10 * 1024
}
}
]
},
{
test: /\.(eot|svg|ttf|woff)/,
loader: 'file-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new CleanWebpackPlugin(),
// new webpack.ProvidePlugin({
// '_': lodash, // 无需在模块引入lodash包
// 'join': ['lodash', 'join']
// }),
// new webpack.IgnorePlugin(/\.\/locale/, /moment/), // 忽略moment包里的locale文件夹
new HappyPack({
id: 'babel',
loaders: ['babel-loader?cacheDirectory'], // 开启编译缓存
})
],
optimization: {
splitChunks: { // 代码分割
chunks: 'all', // 无论 同步引入 还是 异步引入 都要代码分割
minSize: 20000,
// 把 第三方模块代码 拆分成vendors.js
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true, // 已存在chunk进行复用
filename: 'vendors.js'
}
},
// default: {
// minChunks: 2,
// priority: -20, // 优先级
// reuseExistingChunk: true
// }
}
}
}
  • webpack.dev.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
const path = require('path');

const VueLoaderPlugin = require('vue-loader/lib/plugin')
const Webpack = require('webpack')

const distPath = path.join(__dirname, '..', 'dist')

const { merge } = require('webpack-merge')

// 公共配置
const baseConfig = require('./webpack.base')

// 预先打包
const DllReferencePlugin = require('webpack/lib/DllReferencePlugin')

// 开发环境配置
const devConfig = {
watch: true, // 监听任何已解析文件的更改,Watch 模式默认开启
watchOptions: {
ignored: /node_modules/,
aggregateTimeout: 600, // 延迟编译
poll: 1000 // Boolean:true 轮询检查变动 1000 + 600 = 1.6s
},
mode: 'development',
devtool: 'cheap-module-eval-source-map', // production: devtool: 'cheap-module-source-map'
devServer: { // 开发环境有效
// secure: false, // https 专用
contentBase: './dist',
open: true, // 打开默认浏览器
hot: true, // 热更新
port: 1023,// 运行端口
proxy: {
// context: ['/api1', 'api2'], // 多个路径请求转发
'/api': {
target: 'http://localhost:3333',
pathRewrite: { '^/api': '' },
changeOrigin: true
}
}
},
module: {
rules: [
// {
// test: /\.m?js$/,
// use: {
// loader: "babel-loader",
// options: {
// cacheDirectory: true // 缓存优化
// }
// },
// exclude: /node_modules/,// 处理范围不包括 | include
// },
{
test: /\.(css)$/,
// loader 执行顺序,从后往前,从下往上
use: [
'style-loader',
'css-loader',
'postcss-loader',
]
},
]
},
optimization: {
usedExports: true // 按需导入 tree shaking
},
plugins: [
new Webpack.HotModuleReplacementPlugin(),
// new VueLoaderPlugin(),
new DllReferencePlugin({
manifest: require(path.join(distPath, '_vendor.mainfest.json'))
})
],
output: {
// publicPath: 'https://www.bootcdn.cn/', // cdn优化
filename: '[name].js',
path: path.resolve(__dirname, '../dist')
},
}

module.exports = merge(devConfig, baseConfig)
  • webpack.dll.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const path = require('path')

// 拆分 bundles
const DllPlugin = require('webpack/lib/DllPlugin')

const distPath = path.join(__dirname, '..', 'dist')
module.exports = {
mode: 'development',
entry: {
// The library to be extracted (需要提取的库)
_vendor: ['lodash']
},
output: {
// 打包生成的 bundle 的名字 _vendor.dll.js
filename: '[name].dll.js',
path: distPath,
// 保持与 webpack.DllPlugin 中名称一致
// 全局变量 _dll__vendor
library: '_dll_[name]'
},
plugins: [
new DllPlugin({
name: '_dll_[name]',
// 生成一个文件 _vendor.manifest.json
path: path.join(distPath, '[name].mainfest.json') // 映射文件
})
]

}
  • webpack.pro.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
const path = require('path');

const { merge } = require('webpack-merge')

// 公共配置
const baseConfig = require('./webpack.base')

// CSS代码分割
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// CSS代码压缩
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')

// 生产环境配置
const proConfig = {
mode: 'production',
// devtool: 'cheap-module-source-map', // production: devtool: 'cheap-module-source-map'
devServer: { // 开发环境有效
// secure: false, // https 专用
contentBase: './dist',
open: true, // 打开默认浏览器
// hot: true, // 热更新
port: 1023,// 运行端口
proxy: {
// context: ['/api1', 'api2'], // 多个路径请求转发
'/api': {
target: 'http://localhost:3333',
pathRewrite: { '^/api': '' },
changeOrigin: true
}
}
},
module: {
rules: [
{
test: /\.(css)$/,
// loader 执行顺序,从后往前,从下往上
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
]
},
]
},
plugins: [
new MiniCssExtractPlugin(),
],
optimization: {
// minimize: true, // production mode 自动开启
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
test: /\.css$/,
chunks: 'all',
enforce: true
}
}
},
minimizer: [
new CssMinimizerPlugin()
]
},
output: {
filename: '[name].[contenthash:8].js',
path: path.resolve(__dirname, '../dist')
},
}

module.exports = merge(proConfig, baseConfig)
  • package.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
{
"name": "webpack-try",
"sideEffects": [
"@babel/polyfill",
"*.css"
],
"version": "1.0.0",
"description": "webpack4 | node 12.1.0",
"private": true,
"scripts": {
"build:dev": "webpack --config ./build/webpack.dev.js",
"build:pro": "webpack --config ./build/webpack.pro.js",
"dev": "webpack-dev-server --config ./build/webpack.dev.js",
"dll": "webpack --config ./build/webpack.dll.js"
},
"keywords": [],
"browserslist": [
"> 1%",
"last 2 versions"
],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.12.10",
"@babel/plugin-transform-runtime": "^7.22.4",
"@babel/preset-env": "^7.12.11",
"autoprefixer": "^10.4.14",
"babel-loader": "^8.2.2",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^5.0.1",
"css-minimizer-webpack-plugin": "^1.2.0",
"file-loader": "^6.2.0",
"happypack": "^5.0.1",
"html-webpack-plugin": "^4.5.1",
"lodash": "^4.17.21",
"mini-css-extract-plugin": "^1.3.9",
"node-sass": "^5.0.0",
"postcss-loader": "^4.1.0",
"sass-loader": "^10.1.1",
"style-loader": "^2.0.0",
"url-loader": "^4.1.1",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.11.2",
"webpack-merge": "^5.7.3"
},
"dependencies": {
"@babel/polyfill": "^7.12.1",
"@babel/runtime": "^7.22.3",
"@babel/runtime-corejs3": "^7.22.3",
"core-js": "^3.8.3",
"vue": "^2.5.16",
"vue-loader": "^15.2.4",
"vue-template-compiler": "^2.5.16"
}
}
  • .babelrc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
"presets": [ // 预设 插件 二选一
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": 3
}
]
]
// "plugins": [
// [
// "@babel/plugin-transform-runtime",
// {
// "absoluteRuntime": false,
// "corejs": 3,
// "helpers": true,
// "regenerator": true,
// "version": "7.0.0-beta.0"
// }
// ]
// ]
}