环境搭建:安装Node.js 和 NPM
安装nvm
https://github.com/nvm-sh/nvm
ps: nvm(Node.js Version Manager)也就是 Node.js 的包管理器,可以通过它方便安装和切换不同的Node.js版本。
Mac通过 curl 安装:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
Windows的安装方法 参考这里
检查node和NPM版本安装成功如下:
环境搭建:安装webpack和webpack-cli
创建空目录和package.json
mkdir webpack.1-1 cd webpack.1-1 npm init -y
安装 webpack 和 webpack-cli
npm install webpack webpack-cli --save-dev
检查是否安装成功 cd node_modules.bin> webpack -v
在项目根目录下创建一个webpack.config.js
文件
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.join(__dirname, 'dist'),// 打包的文件夹名
filename: 'bundle.js' // 打包的文件名
},
mode: 'production'
}
同时,在项目根目录下,创建src文件夹及其子文件`helloworld.js`和`index.js`
`helloworld.js`
export function helloworld() {
return 'hello webpack';
}
`index.js`
import { helloworld } from './helloworld';
document.write(helloworld());
这样一个简单的demo就完成了,在工程命令行中执行命令 webpack
开始打包工程。
打包好的结果是这样的:
由于我们打包出来的dist文件夹下面是没有html文件的,所以我们在dist文件夹下新建一个index.html
文件,然后将bundle.js引进来。然后在浏览器中打开,一个简单的demo效果就出来了。
总结一下:
'use strict';
const path = require('path');
module.exports = {
entry: './src/index.js', // 用来指定webpack的打包入口 // 如果是Windows电脑应该这样配置 entry: '../../src/index.js',
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js' // 打包的文件名
},
mode: 'production'
}
`index.html`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Webpack</title>
</head>
<body>
<script src="./bundle.js" type="text/javascript"></script>
</body>
</html>
通过 npm script 运行 webpack
在package.json
文件中运行的脚本,默认是可以读取到 node_modules/.bin/
下面的所以命令的通过npm run build
运行打包
原理:模块的局部安装会在node_modules/.bin目录下创建软链接
在package.json
的scripts
中添加一条脚本命令: "build":"webpack",
{
"name": "webpack.1.2",
"version": "1.0.0",
"description": "通过 npm script 运行 webpack",
"main": "index.js",
"scripts": {
"build":"webpack",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^4.35.3",
"webpack-cli": "^3.3.5"
}
}
通过在终端运行npm run build
即可完成打包项目。
webpack 核心概念之entry用法
在webpack.config.js
文件中:
单入口:entry是一个字符串。
module.exports = {
entry:'./src/file.js'
}
多入口:entry是一个对象
module.exports = {
entry: {
index: './src/index.js',
search: './src/search.js'
}
}
webpack 核心概念之Output的用法
Output用来告诉webpack如何将编译后的文件输出到磁盘
module.exports = {
entry: './src/index.js',
output: {
path: path.join(__dirname, 'dist'), // 单入口只要配置path和filename这两个参数
filename: 'bundle.js'
},
mode:'production'
}
Output多入口配置
module.exports = {
entry: {
index: './src/index.js',
search: './src/search.js'
},
output: {
filename: '[name].js', // 通过占位符确保文件名称的唯一性
path: __dirname + '/dist'
},
mode:'production'
}
webpack 核心概念之loaders的用法
webpack的开箱即用只支持js和json两种文件类型,通过loaders去支持其他文件类型,并且将他们转化成有效的模块,并且可以添加到依赖图中,loaders本身是一个函数,接受源文件作为参数,返回转换后的结果。
常见的loaders
名称 | 描述 |
---|---|
babel-loader | 转换ES6ES7等新特性语法 |
css-loader | 支持.css文件的加载和解析 |
less-loader | 将less转换为css |
ts-loader | 将ts转换为js |
file-loader | 进行图片,字体等的打包 |
raw-loader | 将文件以字符串的形式导入 |
thread-loader | 多进程打包js和css |
module.exports = {
entry: './src/index.js',
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
mode: 'production',
module: {
rules: [
{
test: /\.txt$/, use: 'raw-loader' // test 指定匹配规则 use 指定使用的loader名称
}
]
}
}
webpack 核心概念之plugins的用法
插件用于bundle文件的优化,资源管理和环境变量注入,作用于整个构建过程
常见的plugins
名称 | 描述 |
---|---|
CommonsChunkPlugin | 将chunks相同的模块代码提取成公共js文件 |
CleanWebpackPlugin | 清理构建项目 |
ExtractTextWebpackPlugin | 将chunks相同的模块代码提取成公共js文件 |
CommonsChunkPlugin | 将css从bundle文件里提取成独立的css文件 |
CopyWebpackPlugin | 将文件或者文件夹拷贝到构建的输出目录 |
HtmlWebpackPlugin | 创建html文件去承载输出的bundle |
UglifyjsWebpackPlugin | 压缩js |
ZipWebpackPlugin | 将打包出的资源生成一个Zip包 |
module.exports = {
entry: './src/index.js',
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
mode: 'production',
module: {
rules: [
{
test: /\.txt$/, use: 'raw-loader' // test 指定匹配规则 use 指定使用的loader名称
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html' // 创建html文件去承载输出的bundle
})
]
}
webpack核心概念之mode的用法
概念:Mode用于指定当前的构建环境是:production , development ,还是 none 。设置mode的值,可以使用webpack在相应阶段的内置函数,默认值为production(webpack4.x以后才有的概念),如果是productin,webpack会默认开启一些在生产阶段才使用的内置功能,如下参考:
选项 | 描述 |
---|---|
development | 设置process.env.NODE_ENV的值为development,开启NameChunksPlugin和NameModulesPlugin |
production | 设置process.env.NODE_ENV的值为production,开启FlagDependencyUsagePlugin,FlagIncludedChunksPlugin,ModuleConcatenationPlugin,NoEmitOnErrorsPlugin,OccurrenceOrderPlugin,SideEffectsFlagPlugin和TerserPlugin |
none | 不开启任何优化选项 |
资源解析:解析ES6语法
首先,安装三个插件: npm i @babel/core @babel/preset-env babel-loader -D
ps: -D 是 --save-dev 的简称 -i 是 install 的简称。
在项目根目录下,新建.babelrc文件,配置如下:
{
"presets":[
"@babel/preset-env", // ES6解析成ES5语法
]
}
在 webpack.config.js文件中,module对象中添加一个新的plugin,如下:
'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: /\.js$/, // 匹配js文件 注意这个地方 千万不能写成'/\.js$/' 遇到过的坑
use: 'babel-loader' // 用于将ES6等高级语法解析成ES5语法
}
]
}
}
资源解析:解析React jsx
首先安装相关依赖: npm i react react-dom @babel/preset-react -D
在src文件下新建search.js
文件用于接下来的测试:
'use strict';
import React from 'react';
import ReactDOM from 'react-dom';
import logo from './images/webpack.jpg'
import './search.less'
class Search extends React.Component {
render() {
return <div className='search-text'>
search page
<img src={logo}/>
</div>;
}
}
ReactDOM.render(
<Search />,
document.getElementById('root')
);
在.babelrc中增加React的babel preset的配置
{
"presets":[
"@babel/preset-env", // ES6解析成ES5语法
"@babel/preset-react" // 增加React的babel preset设置
]
}
资源解析:解析css
安装:npm i style-loader css-loader -D
css-loader用于加载.css文件,并且转化成commonjs对象,style-loader将样式通过<style>
标签插入到head中。
`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: /\.js$/, // 匹配js文件
use: 'babel-loader' // 用于将ES6等高级语法解析成ES5语法
}, {
test: /\.css$/,
use: ['style-loader', 'css-loader'] // 注意 解析顺序是从右往左的,先解析css-loader 后解析style-loader将css插入dom中。
}
]
}
}
资源解析:解析less
less-loader 用于将less转换成css,安装 npm i less less-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: /\.js$/, // 匹配js文件
use: 'babel-loader' // 用于将ES6等高级语法解析成ES5语法
},
{
test: /\.css$/,
use: [ // 注意 解析顺序是从右往左的,先解析css-loader 后解析style-loader将css插入dom中。
'style-loader',
'css-loader'
]
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader' // 用于解析less
]
}
]
}
}
资源解析:解析字体。
安装 npm install file-loader -D
在search.less
中添加字体:
@font-face {
font-family: 'SourceHanSerifSC-Heavy';
src: url('./font-family/SourceHanSerifSC-Heavy.otf') format('truetype')
}
.search-text {
text-align: center;
font-size: 20px;
color: red;
font-family: 'SourceHanSerifSC-Heavy';
}
然后在webpack.config.js
中配置:file-loader
'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: /\.js$/, // 匹配js文件
use: 'babel-loader' // 用于将ES6等高级语法解析成ES5语法
},
{
test: /\.css$/,
use: [ // 注意 解析顺序是从右往左的,先解析css-loader 后解析style-loader将css插入dom中。
'style-loader',
'css-loader'
]
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader' // 用于解析less
]
},
{
test: /\.(png|jpg|gif|jpeg)$/, // 解析图片和字体
use: 'file-loader'
}
]
}
}
资源解析:解析图片。
url-loader
安装 npm i url-loader -D
如下图所示,在没有使用url-loader之前
, search.js
大小是125KiB,图片大小是16.2KiB
配置url-loader
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: /\.js$/, // 匹配js文件
use: 'babel-loader' // 用于将ES6等高级语法解析成ES5语法
},
{
test: /\.css$/,
use: [ // 注意 解析顺序是从右往左的,先解析css-loader 后解析style-loader将css插入dom中。
'style-loader',
'css-loader'
]
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader' // 用于解析less
]
},
{
test: /\.(png|jpg|gif|jpeg)$/,
use: [
{
loader:'url-loader',
options:{
limit:20480 // 如果一张图片小于20k webpack将自动将图片转为base64打包进文件,如果超过这个大小,将单独打包。
}
}
]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: 'file-loader'
}
]
}
}
当配置了url-loader
之后,webpack已经将大小为16.2KiB大小的图片(小于我们的限制),打包进search.js中了,search.js从之前的125kib大小变成了147kib,大约增加了16.2kib大小。
webpack中的文件监听
文件监听是在发现源码发生变化的时候,自动重新构建出新的输出文件。
webpack开启监听模式的两种模式:
启动 webpack
命令时候,带上--watch
参数
package.json
中配置如下:
"scripts": {
"build": "webpack --watch"
},
上面方式有个缺陷,就是每次webpack更新代码,都要手动刷新浏览器!
在配置 webpack.config.js
中设置watch:true
通过轮询判断文件的最后编辑时间,是否发生变化,当某个文件发生变化,并不会立即告诉监听者,而是先缓存起来,等aggregateTimeout。
module.exports = {
// 默认是false ,不开启状态
watch: true,
// 只有开启监听模式watchOptions才有意义
watchOptions: {
// 不监听的文件或者文件夹,默认为空,支持正则匹配。
ignored: /node_modules/,
// 监听到变化发生后,会等300ms再去执行更新,默认是300ms
aggregateTimeout: 300,
// 判断文件是否发生变化,是通过不停的询问系统指定文件有没有发生变化实现的,默认每秒问1000次。
poll: 1000
},
}
webpack中的热更新:webpack-dev-server及其原理
首先安装: npm i webpack-dev-server -D
在package.json
中配置如下:
"scripts": {
"dev": "webpack-dev-server --open"
},
在webpack.config.js
中配置:
const webpack = require('webpack');
module.exports = {
mode: 'development', // 开发环境
plugins: [
// webpack 自带的热更新插件
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist', // webpack服务的基础目录
hot: true
}
}
webpack中的热更新:webpack-dev-middleware(WDM)及其原理。
WDM将webpack输出的文件传输服务器,适用于灵活的应用场景。
const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-devmiddleware');
const app = express();
const config = require('./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!\n');
});
「原理分析」
webpack compile: 将js编译成,bundle.js
HMR Server:将热更新的文件输出给 HMR Runtime
Bundle server: 提供文件在浏览器的访问
HMR runtime: 会被注入到浏览器,更新文件的变化。
bundle.js:构建输出的文件
原理图如下所示:
文件指纹策略
「打包后输出的文件名的后缀」
文件指纹如何生成?
hash:整个项目的构建相关,只要项目文件有修改,整个项目的构建的hash就会改变。 Chunkhash:和webpack打包的chunk有关,不同的entry会生成不同的chunkhash值。 contenthash:根据文件内容来定义hash,文件内容不变,则contenthash不变。
js的文件指纹的设置
设置 output 的 filename,使用 [chunkhash]
module.exports = {
output: {
filename: '[name]_[chunkhash:8].js',
path: path.join(__dirname, 'dist')
},
}
css的文件指纹的设置
设置MiniCssExtractPlugin
的filename,使用[contenthash]
占位符名称 | 含义 |
---|---|
[ext] |
资源后缀名 |
[name] |
文件名称 |
[path] |
文件的相对路径 |
[folder] |
文件所在的文件夹 |
[contenthash] |
文件的内容hash,默认是md5生成 |
[hash] |
文件的内容hash,默认是md5生成 |
[emoji] |
一个随机的指代文件内容的emoji |
首先安装插件 npm install mini-css-extract-plugin -D
在新建的 webpack.prod.js
文件中配置:
module: {
rules: [
{
test: /\.js$/, // 匹配js文件
use: 'babel-loader' // 用于将ES6等高级语法解析成ES5语法
},
{
test: /\.css$/,
use: [ // 注意 解析顺序是从右往左的,先解析css-loader 后解析style-loader将css插入dom中。
// 'style-loader',
MiniCssExtractPlugin.loader, // MiniCssExtractPlugin是将css代码提取出来,这两个loader不能同时使用。
'css-loader'
]
},
{
test: /\.less$/,
use: [
// 'style-loader',
MiniCssExtractPlugin.loader, // MiniCssExtractPlugin是将css代码提取出来,这两个loader不能同时使用。
'css-loader',
'less-loader' // 用于解析less
]
},
{
test: /\.(png|jpg|gif|svg|jpeg)$/,
use: [
{
loader: 'file-loader', // file-loader 和url-loader都行
options: {
name: '[name]_[hash:8][ext]'
}
}
]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
{
loader: 'file-loader', // file-loader 和url-loader都行
options: {
name: '[name]_[hash:8][ext]'
}
}
]
}
]
},
webpack 的代码的压缩
js文件的压缩
webpack 内置了,uglifyjs-webpack-plugin
在打包代码的时候,会自动压缩js代码。
css 文件的压缩
使用optimize-css-assets-webpack-plugin
,同时使用需要依赖 cssnano
预处理器
安装 npm i optimize-css-assets-webpack-plugin cssnano -D
在webpack.prod.js
中配置plugins:
const OptimizeCssAssetsWebpackPlugin = requir('optimize-css-assets-webpack-plugin')
plugins: [
new OptimizeCssAssetsWebpackPlugin({
assetNameRegExp:/.css$/g,
cssProcessor: require('cssnano')
})
],
执行 npm run build
查看压缩效果
html文件的压缩
首先安装插件: npm i html-webpack-plugin -D
在webpack.prod.js
配置文件中配置:
const HtmlWebpackPlugin = require('html-webpack-plugin')
plugins: [
new MiniCssExtractPlugin({
filename: `[name]_[contenthash:8].css`
}),
new OptimizeCssAssetsWebpackPlugin({
assetNameRegExp: /.css$/g,
cssProcessor: require('cssnano')
}),
new HtmlWebpackPlugin({ // 通常一个html页面用一个HtmlWebpackPlugin,如果有两那就写两个
template: path.join(__dirname, 'src/index.html'), //html模板所在的位置
filename: 'index.html',// 指定打包出来的html文件名称
chunks: ['index'],// chunk名称 指定生成的html要使用哪些chunk
inject: true,// 是否将打包出来的js或者css将自动注入到index.html中
minify: {
html5: true,
collapseWhitespace: true,
preserveLineBreaks: false,
minifyCSS: true,
minifyJS: true,
removeComments: false
}
}),
new HtmlWebpackPlugin({ // 通常一个html页面用一个HtmlWebpackPlugin,如果有两那就写两个
template: path.join(__dirname, 'src/search.html'), //html模板所在的位置
filename: 'search.html',// 指定打包出来的html文件名称
chunks: ['search'],// chunk名称 指定生成的html要使用哪些chunk
inject: true,// 是否将打包出来的js或者css将自动注入到search.html中
minify: {
html5: true,
collapseWhitespace: true,
preserveLineBreaks: false,
minifyCSS: true,
minifyJS: true,
removeComments: false
}
}),
],
执行 npm run build
查看压缩效果
自动清理构建目录
npm install clean-webpack-plugin -D
避免在每次构建的时候,都需要手动清理dist文件。
在webpack.dev.js
中配置如下:
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
// 这个地方注意,可能会报错必须用解构的方式
`plugins`下添加如下代码:` new CleanWebpackPlugin()`执行npm run build 打包构建
### 自动补全css3前缀,autoprefixer
先安装插件:`npm i postcss-loader autoprefixer -D`
在`webpack.prod.js`的module中配置如下:
{
test: /\.less$/,
use: [
// 'style-loader',
MiniCssExtractPlugin.loader, // MiniCssExtractPlugin是将css代码提取出来,这两个loader不能同时使用。
'css-loader',
'less-loader', // 用于解析less
{
loader: 'postcss-loader',
options: {
plugins: () => [
require('autoprefixer')({
browsers: ['last 2 version', '>1%', 'ios 7 ']
})
]
}
}
]
},
移动端CSS px自动转化成rem
安装插件:npm i px2rem-loader -D
到开发环境中,再直接引用npm i lib-flexible -S
{
loader: 'px2rem-loader',
options: {
remUnit: 75, // 1rem == 75px
remPrecision: 8 // 当px转换为rem的时候,小数点后面的位数。
}
}
然后将flexble.js 内联进我们的html中!
静态资源内联
资源内联的意义:
页面框架的初始化脚本 上报相关打点 css内联避免页面闪动
raw-loader
内联html
<script>${require('raw-loader!./meta.html')}</script>
安装 npm i raw-loader@0.5.1 -D
raw-loader
内联js
<script>${require('raw-loader!babel-loader!../../node_modules/lib-flexible/flexible.js')}</script>
css内联
借助 style-loader
借助 html-inline-css-webpack-plugin
配置如下:
// 'style-loader',
{
loader: 'style-loader',
options: {
insertAt: 'top', // 样式插入到<head>中
singleton: true // 将所有的style标签合并成一个
}
},
多页面应用(MPA)概念,多页面打包通用方案
动态获取entry和设置html-webpack-plugin
数量利用global.sync
安装glob npm i glob -D
在webpack.prod.js文件中
配置如下:
const glob = require('glob')
const setMPA = () => {
const entry = {}
const htmlWebpackPlugin = []
const entryFiles = glob.sync(path.join(__dirname, './src/*/index.js'))
Object.keys(entryFiles).map(index => {
const entryFile = entryFiles[index]
const match = entryFile.match(/src\/(.*)\/index\.js/)
const pageName = match && match[1]
entry[pageName] = entryFile
htmlWebpackPlugin.push(
new HtmlWebpackPlugin({ // 通常一个html页面用一个HtmlWebpackPlugin,如果有两那就写两个
template: path.join(__dirname, `src/${pageName}/index.html`), // html模板所在的位置
filename: `${pageName}.html`, // 指定打包出来的html文件名称
chunks: [pageName], // chunk名称 指定生成的html要使用哪些chunk
inject: true, // 是否将打包出来的js或者css将自动注入到index.html中
minify: {
html5: true,
collapseWhitespace: true,
preserveLineBreaks: false,
minifyCSS: true,
minifyJS: true,
removeComments: false
}
})
)
})
return {
entry,
htmlWebpackPlugin
}
}
const { entry, htmlWebpackPlugin } = setMPA()
module.exports = {
entry,
plugins: [
new MiniCssExtractPlugin({
filename: `[name]_[contenthash:8].css`
}),
new OptimizeCssAssetsWebpackPlugin({
assetNameRegExp: /.css$/g,
cssProcessor: require('cssnano')
}),
new CleanWebpackPlugin()
].concat(htmlWebpackPlugin)
}
使用source map
「作用:通过source map定位到源代码,开发环境开启,线上环境关闭,线上排查问题的时候,可以将问题上传到错误监控系统」
sourcemap 关键字
eval
使用eval包裹模块代码sourcemap
产生.map 文件cheap
不包含列信息(当代码报错的时候,只显示报错位置所在的行信息)inline
将.map作为DataURI嵌入,不单独成.map文件module
包含loader的sourcemap
sourcemap类型
devtool | 首次构建 | 二次构建 | 是否适合生产环境 | 可以定位的代码 |
---|---|---|---|---|
(none) | +++ | +++ | yes | 最终输出的代码 |
eval | +++ | +++ | no | webpack生产的代码(一个个的模块) |
cheap-eval-source-map | + | ++ | no | 经过loader转换后的代码(只能看到行) |
cheap-module-source-map | o | ++ | no | 源代码(只能看到行) |
eval-source-map | -- | + | no | 源代码 |
cheap-source-map | + | o | yes | 经过loader转换后的代码(只能看到行) |
cheap-module-source-map | o | - | yes | 源代码(只能看到行) |
inline-source-map | + | o | no | 经过loader转换后的代码(只能看到行) |
inline-cheap-module-source-map | o | - | no | 源代码(只能看到行) |
source-map | -- | -- | yes | 源代码 |
inline-source-map | -- | -- | no | 源代码 |
hidden-source-map | -- | -- | yes | 源代码 |
提取页面公共资源
先安装: npm i html-webpack-externals-plugin -D
新增react的开发环境的CDN:
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
一下是react的线上环境的CDN:
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
在webpack.prod.js
中配置线上环境的CDN:
const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin')
plugins中:
new HtmlWebpackExternalsPlugin({
externals: [
{
module: 'react',
entry: 'https://unpkg.com/react@16/umd/react.production.min.js',
global: 'React'
},
{
module: 'react-dom',
entry: 'https://unpkg.com/react-dom@16/umd/react-dom.production.min.js',
global: 'ReactDOM'
}
]
})
使用 SplitChunksPlugin分离react和react-dom
optimization: {
splitChunks: {
cacheGroups: {
commons: {
name: 'vendors', // 提取出来的技术包的名字
test: /(react | react - dom)/, // 匹配出需要分离的包
chunks: 'all',
}
}
}
},
在 new HtmlWebpackPlugin
对象参数中加入 chunks: ['vendors', pageName],
使用 SplitChunksPlugin分离页面公共文件
optimization: {
splitChunks: {
minSize: 300, // 分离的包的体积的大小,设置成0kb只要引用了,就会打包,假如为1000kb
cacheGroups: {
commons: {
name: 'commons', // 提取出来的包的名字,记得在new HtmlWebpackPlugin中加入chunks: ['commons', pageName],
chunks: 'all', // 将所有引入的库进行分离;默认是async是将异步引入的库进行分离;inital是将同步引入的库进行分离
minChunks: 2 // 设置最小引用次数为2次,才会打包出commons.js文件来
}
}
}
},
在 new HtmlWebpackPlugin
对象参数中加入 chunks: ['commons', pageName],