webpack學習(十二):多頁面提取公共部分(js&css)
demo地址: https://github.com/Lkkkkkkg/webpack-demo
繼上一次配置完多頁面 : https://blog.csdn.net/qq593249106/article/details/84933978
使用SplitChunksPlugin
The CommonsChunkPlugin 已經從 webpack v4 legato 中移除, webpack 4+ 版本使用內建的 SplitChunksPlugin 外掛來進行公共部分的提取:
配置 webpack.config.js
因為 SplitChunksPlugin 是 webpack 4+ 版本內建的外掛, 所以無需安裝, 只需在 webpack.config.js 中配置
optimization: {
splitChunks: {
cacheGroups: {
//打包公共模組
commons: {
chunks: 'initial', //initial表示提取入口檔案的公共部分
minChunks: 2, //表示提取公共部分最少的檔案數
minSize: 0, //表示提取公共部分最小的大小
name: 'commons' //提取出來的檔案命名
}
}
}
}
注意
還要在每一個頁面的 HtmlWebpackPlugin 的 chunks 加上 commons, 因為提取之後的 commons 需要被打包出來的頁面引用!
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin' );
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
var devMode = false; //標誌是否開發模式
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
module.exports = {
mode: 'development',
entry: { //入口檔案
index: "./src/components/index/index.js",
otherA: "./src/components/otherA/otherA.js",
otherB: "./src/components/otherB/otherB.js",
},
output: {
path: path.join(__dirname, 'dist'),
filename: 'js/[name].js', //根據入口檔案分為不同出口檔案
},
devtool: 'inline-source-map', // 不同選項適用於不同環境
devServer: {
contentBase: './dist', //將dist目錄下的檔案(index.html)作為可訪問檔案, 如果不寫這個引數則預設與webpack.cofig.js的同級目錄
port: 8080 //埠號設為8080, 預設也是8080
},
module: {
rules: [ //配置載入器, 用來處理原始檔, 可以把es6, jsx等轉換成js, sass, less等轉換成css
{
exclude: /node_modules|packages/, //路徑
test: /\.js$/, //配置要處理的檔案格式,一般使用正則表示式匹配
use: 'babel-loader', //使用的載入器名稱
},
{
test: /\.(sa|sc|c)ss$/,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader',
],
},
]
},
plugins: [ //webpack 通過 plugins 實現各種功能, 比如 html-webpack-plugin 使用模版生成 html 檔案
new CleanWebpackPlugin(['dist']), //設定清除的目錄
new HtmlWebpackPlugin({
template: "./src/components/index/index.html", //設定生成的HTML檔案的名稱, 支援指定子目錄,如:assets/admin.html
chunks: ['index', 'commons'], //指定入口檔案
filename: "index.html" //指定模板檔案的位置
}),
new HtmlWebpackPlugin({
template: "./src/components/otherA/otherA.html",
chunks: ['otherA', 'commons'],
filename: "otherA.html"
}),
new HtmlWebpackPlugin({
template: "./src/components/otherB/otherB.html",
chunks: ['otherB', 'commons'],
filename: "otherB.html"
}),
new MiniCssExtractPlugin({
filename: 'css/[name].css', //類似出口檔案
chunkFilename: 'css/[id].css'
}),
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.css$/g, //一個正則表示式,指示應優化\最小化的資產的名稱。提供的正則表示式針對配置中ExtractTextPlugin例項匯出的檔案的檔名執行,而不是源CSS檔案的檔名。預設為/\.css$/g
cssProcessor: require('cssnano'), //用於優化\最小化CSS的CSS處理器,預設為cssnano。這應該是一個跟隨cssnano.process介面的函式(接收CSS和選項引數並返回一個Promise)。
cssProcessorOptions: { safe: true, discardComments: { removeAll: true } }, //傳遞給cssProcessor的選項,預設為{}
canPrint: true //一個布林值,指示外掛是否可以將訊息列印到控制檯,預設為true
})
],
optimization: {
splitChunks: {
cacheGroups: {
//打包公共模組
commons: {
chunks: 'initial', //initial表示提取入口檔案的公共部分
minChunks: 2, //表示提取公共部分最少的檔案數
minSize: 0, //表示提取公共部分最小的大小
name: 'commons' //提取出來的檔案命名
}
}
}
}
};
這裡修改一下目錄結構, 在 src 新建一個 common 資料夾, common 資料夾下新建一個 css 資料夾, 專門用來放公共的 css 檔案, 新建一個 common.scss 放入 css 資料夾中, 測試能否打包這個公共的 scss:
common.scss
$fontSize: 100px;
h1 {
font-size: $fontSize;
}
|- /dist
|- /css //分離出來的css檔案
|- index.css
|- otherA.css
|- otherB.css
|- /js
|- index.js
|- otherA.js
|- otherB.js
|- index.html
|- otherA.html
|- otherB.html
|- /node_modules
|- /src //用於放原始檔的資料夾
|- common //存放公共檔案的目錄
|- css // 存放公共css的目錄
|- common.scss //公共css
|- components //存放頁面的目錄
|- index //主頁
|- App.js
|- index.html
|- index.js
|- index.scss
|- otherA //另一個頁面A
|- App.js
|- otherA.html
|- otherA.js
|- otherA.scss
|- otherB //另一個頁面B
|- App.js
|- otherB.html
|- otherB.js
|- otherB.scss
|- package.json
|- webpack.config.js //webpack配置檔案
修改一下 index.js, otherA.js, otherB.js, 讓它們都引入公共樣式 common.scss:
index.js
import React from 'react'
import { render } from 'react-dom'
import App from './App'
import './index.scss'
import '../../common/common.scss'
render(<App />, document.getElementById("root"))
otherA.js
import React from 'react'
import { render } from 'react-dom'
import App from './App'
import './otherA.scss'
import '../../common/css/common.scss'
render(<App />, document.getElementById("root"))
otherB.js
import React from 'react'
import { render } from 'react-dom'
import App from './App'
import './otherB.scss'
import '../../common/css/common.scss'
render(<App />, document.getElementById("root"))
打包
終端輸入 npm run build, 發現 dist 目錄下的 css 和 js 資料夾分別多了 commons.css 和 commons.js, 而且其他 css 和 js 檔案大小都變小了
|- /dist
|- /css //分離出來的css檔案
|- commons.css
|- index.css
|- otherA.css
|- otherB.css
|- /js
|- commons.js
|- index.js
|- otherA.js
|- otherB.js
|- index.html
|- otherA.html
|- otherB.html
|- /node_modules
|- /src //用於放原始檔的資料夾
|- common //存放公共檔案的目錄
|- css // 存放公共css的目錄
|- common.scss //公共css
|- components //存放頁面的目錄
|- index //主頁
|- App.js
|- index.html
|- index.js
|- index.scss
|- otherA //另一個頁面A
|- App.js
|- otherA.html
|- otherA.js
|- otherA.scss
|- otherB //另一個頁面B
|- App.js
|- otherB.html
|- otherB.js
|- otherB.scss
|- package.json
|- webpack.config.js //webpack配置檔案
開啟 index.html, otherA.html, otherB.html:
公共樣式 h1{font-size:100px} 起了效果, 提取公共 js&css成功