背景
使用 Webpack 打包资源时体积过大,通常需要将基础库分离出来。
基础库分离
使用 html-webpack-externals-plugin
使用 html-webpack-externals-plugin
将 react
、react-dom
基础库通过 CDN 引入,不打如 bundle 中
初始化项目
安装依赖
1 2
| npm install --save react react-dom npm install --save-dev webpack webpack-cli babel-loader @babel/core @babel/preset-env @babel/preset-react html-webpack-plugin html-webpack-externals-plugin
|
根目录下新建 webpack.config.js
和 .bablerc
webpack.config.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
| const path = require("path");
const HtmlWebpackExternalsPlugin = require("html-webpack-externals-plugin");
module.exports = { entry: "./src/index.js", output: { path: path.join(__dirname, "dist"), }, mode: "development", module: { rules: [ { test: /.js$/, use: "babel-loader", }, ], }, plugins: [ new HtmlWebpackExternalsPlugin({ externals: [ { module: "react", entry: "https://cdn.bootcss.com/react/16.13.1/umd/react.development.js", global: "React", }, { module: "react-dom", entry: "https://cdn.bootcss.com/react-dom/16.13.1/umd/react-dom.development.js", global: "ReactDOM", }, ], }), ], };
|
.bablerc
内容
1 2 3
| { "presets": ["@babel/preset-env", "@babel/preset-react"] }
|
根目录下新建 index.html
index.html
内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div id="root"></div> <script src="https://cdn.bootcss.com/react/16.13.1/umd/react.development.js"></script> <script src="https://cdn.bootcss.com/react-dom/16.13.1/umd/react-dom.development.js"></script> <script src="./dist/main.js"></script> </body> </html>
|
修改 package.json
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
| { "name": "webpack-externals", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "webpack", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "react": "^16.13.1", "react-dom": "^16.13.1" }, "devDependencies": { "@babel/core": "^7.9.0", "@babel/preset-env": "^7.9.5", "@babel/preset-react": "^7.9.4", "babel-loader": "^8.1.0", "html-webpack-externals-plugin": "^3.8.0", "html-webpack-plugin": "^4.2.0", "webpack": "^4.42.1", "webpack-cli": "^3.3.11" } }
|
新建src/index.js
src/index.js
内容
1 2 3 4 5 6 7 8
| import React from "react"; import ReactDOM from "react-dom";
function App() { return <div>Hello, Webpack</div>; }
ReactDOM.render(<App />, document.getElementById("root"));
|
执行npm start
此时的 dist
目录中的 main.js
就是只打包了我们自己写的 src/index.js
的内容
不想用 CDN,想使用 node_modules
中的怎么办
webpack.config.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
| const path = require("path");
const HtmlWebpackExternalsPlugin = require("html-webpack-externals-plugin");
module.exports = { entry: "./src/index.js", output: { path: path.join(__dirname, "dist"), }, mode: "development", module: { rules: [ { test: /.js$/, use: "babel-loader", }, ], }, plugins: [ new HtmlWebpackExternalsPlugin({ externals: [ { module: "react", entry: "umd/react.development.js", global: "React", }, { module: "react-dom", entry: "umd/react-dom.development.js", global: "ReactDOM", }, ], }), ], };
|
会在ouput
目录下新建一个vendor
的目录, 将对应的两个文件拷过去,此时 html 文件中的script
引用路径也需要更改
index.html
内容更改为
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div id="root"></div> <script src="./dist/vendor/react/umd/react.development.js"></script> <script src="./dist/vendor/react-dom/umd/react-dom.development.js"></script> <script src="./dist/main.js"></script> </body> </html>
|
webpack 4 中还可以使用SplitChunksPlugin
来提取公共资源
使用 SplitChunksPlugin
使用 optimization.SplitChunksPlugin
webpack.config.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
| const path = require("path");
module.exports = { entry: "./src/index.js", output: { path: path.join(__dirname, "dist"), }, mode: "development", module: { rules: [ { test: /.js$/, use: "babel-loader", }, ], }, optimization: { splitChunks: { cacheGroups: { vendor: { test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/, name: "vendor", chunks: "all", }, }, }, }, };
|
会在output
目录下生成一个vendor.js
的文件,在 html 中引用即可
1 2 3 4 5 6 7 8 9 10 11 12 13
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div id="root"></div> <script src="./dist/vendor.js"></script> <script src="./dist/main.js"></script> </body> </html>
|