Webpack5 多頁面的項(xiàng)目實(shí)踐
| 特性維度 | 單頁面應(yīng)用-SPA | 多頁面統(tǒng)一目錄-MPA | 多頁面單獨(dú)部署-MPA |
|---|---|---|---|
| 入口數(shù)量 | 單個(gè),只有一個(gè) HTML 文件 | 多個(gè),多個(gè) HTML 文件 | 多個(gè),多個(gè) HTML 文件,分別打包輸出 |
| 資源輸出結(jié)構(gòu) | 所有資源輸出到統(tǒng)一目錄(如 js/, css/) | 所有頁面的資源共用 js/, css/ 等目錄 | 每頁資源放在各自目錄(如 index/js/, index/css/) |
| 公共資源復(fù)用 | 高:依賴打入主包或懶加載 chunk,資源完全共享 | 中:可通過 splitChunks 提取公共模塊,多個(gè)頁面共用依賴 | 低:默認(rèn)每個(gè)頁面依賴重復(fù)打包,需通過 CDN 或構(gòu)建優(yōu)化共享資源 |
| 首屏加載速度 | 中低:主包體積大需優(yōu)化 | 高:每頁只加載自身資源 | 高:每頁打包獨(dú)立、加載自身資源 |
| 項(xiàng)目推薦模式 | 用戶交互復(fù)雜、狀態(tài)集中、路由頻繁 | 頁面之間結(jié)構(gòu)清晰、流程獨(dú)立但資源共用 | 需要頁面級(jí)灰度、子模塊獨(dú)立開發(fā)與部署 |
1. 示例多頁面配置
- 配置外部依賴、CDN 資源以及頁面級(jí) CDN 擴(kuò)展
- 自動(dòng)生成入口和 HtmlWebpackPlugin 實(shí)例
- 導(dǎo)出生成的入口配置、插件配置、依賴過濾配置
- entries:入口配置對(duì)象(用于 entry)
- plugins:HtmlWebpackPlugin 實(shí)例數(shù)組(用于 plugins)
- externals:供主配置使用(用于排除模塊打包)
1.1多頁面統(tǒng)一目錄(MPA)
dist/ ├── test1.html ├── test2.html ├── js/ │ ├── test1.[hash].js │ └── test2.[hash].js └── 圖片、字體等資源
const path = require("path");
const glob = require("glob");
const { merge } = require("webpack-merge");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const resolve = (dir) => path.resolve(__dirname, "..", dir);
// 打包排除某些依賴
const externals = {
vue: "Vue",
vuex: "Vuex",
"vue-router": "VueRouter",
axios: "axios",
vant: "vant",
};
// cdn資源
const assetsCDN = {
// 開發(fā)環(huán)境
dev: {
css: ["http://xxx/npm/vant@2.12/lib/index.css"],
js: ["http://xxx/npm/eruda@2.4/eruda.min.js"],
},
// 生產(chǎn)環(huán)境
build: {
css: ["http://xxx/npm/vant@2.12/lib/index.css"],
js: [
"http://xxx/npm/vue@2.6/dist/vue.min.js",
"http://xxx/npm/vuex@3.6/dist/vuex.min.js",
"http://xxx/npm/vue-router@3.5/dist/vue-router.min.js",
"http://xxx/npm/axios@0.21/dist/axios.min.js",
"http://xxx/npm/vant@2.12/lib/vant.min.js",
],
},
};
const entryCDN = {
test: {
dev: merge(assetsCDN.dev, {
css: [],
js: ["http://res.wx.qq.com/open/js/jweixin-1.6.0.js"],
}),
build: merge(assetsCDN.build, {
css: [],
js: ["http://res.wx.qq.com/open/js/jweixin-1.6.0.js"],
}),
},
};
const getEntry = () => {
// 多頁面打包的入口集合
const entries = {};
// 多頁面打包的模板集合
const plugins = [];
// 借助 glob 獲取 src 目錄下的所有入口文件
const globPath = resolve("src/views/**/main.js");
// 遍歷文件集合,生成所需要的 entries、plugins 集合
glob.sync(globPath).map((item) => {
const match = item.match(/src/views/(.*)/main.js$/);
const name = match?.[1];
entries[name] = [item];
// CDN配置
const env = process.env.NODE_ENV === "production" ? "build" : "dev";
const pageCDN = (entryCDN[name] && entryCDN[name][env]) || assetsCDN[env];
if (!entryCDN[name]) {
console.warn(`頁面 ${name} 未配置 entryCDN,已使用默認(rèn)配置`);
}
// 多頁面所需要的模板集合
plugins.push(
new HtmlWebpackPlugin({
title: "",
filename: `${name}.html`,
template: "public/index.html",
favicon: "public/favicon.ico",
chunks: [name],
minify:
process.env.NODE_ENV === "production"
? {
//壓縮HTML文件
removeComments: true, // 移除HTML中的注釋
collapseWhitespace: true, // 刪除空白符和換行符
}
: false,
cdn: process.env.NODE_ENV === "production" ? entryCDN[name].build : entryCDN[name].dev,
})
);
});
// 對(duì)外輸出頁面打包需要的 入口集合、依賴過濾
return { entries, plugins, externals };
};
module.exports = getEntry();const { entries, plugins, externals } = require("./entry");
entry: {
base: ["core-js/stable", "regenerator-runtime/runtime"],
...entries
}1.2多頁面單獨(dú)部署(MPA)
dist/
├── test1/
│ ├── index.html
│ └── js/
│ └── test1.[hash].js
└── test2/
├── index.html
└── js/
└── test2.[hash].js// 在多頁面統(tǒng)一目錄的基礎(chǔ)上新增配置
const CopyWebpackPlugin = require("copy-webpack-plugin");
const getEntry = () => {
// 多頁面打包的入口集合
const entries = {};
// 多頁面打包的模板集合
const plugins = [];
// 借助 glob 獲取 src 目錄下的所有入口文件
const globPath = resolve("src/views/**/main.js");
const base = ["core-js/stable", "regenerator-runtime/runtime"];
// 遍歷文件集合,生成所需要的 entries、plugins 集合
glob.sync(globPath).map(item => {
const match = item.match(/src/views/(.*)/main.js$/);
const name = match?.[1];
entries[name] = [...base, item];
const env = process.env.NODE_ENV === "production" ? "build" : "dev";
const pageCDN = (entryCDN[name] && entryCDN[name][env]) || assetsCDN[env];
if (!entryCDN[name]) {
console.warn(`頁面 ${name} 未配置 entryCDN,已使用默認(rèn)配置`);
}
// 多頁面所需要的模板集合
plugins.push(
new HtmlWebpackPlugin({
title: "",
filename: `${name}/index.html`,
template: "public/index.html",
// favicon: "public/favicon.ico",
chunks: [name],
minify:
process.env.NODE_ENV === "production"
? {
//壓縮HTML文件
removeComments: true, // 移除HTML中的注釋
collapseWhitespace: true // 刪除空白符和換行符
}
: false,
cdn: pageCDN
}),
new CopyWebpackPlugin({
patterns: [{ from: "public/favicon.ico", to: `${name}/favicon.ico` }]
})
);
});
// 對(duì)外輸出頁面打包需要的 入口集合、依賴過濾
return { entries, plugins, externals };
};// 1. 注釋掉 entry base 的配置 // 2. css、img、font的filename 增加 [name]/ splitChunks: false // ? 禁用公共拆包
到此這篇關(guān)于Webpack5 多頁面的項(xiàng)目實(shí)踐的文章就介紹到這了,更多相關(guān)Webpack5 多頁面內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript 限制輸入和粘貼(IE和火狐3.x下測(cè)試通過)
限制輸入和粘貼的js代碼2008-11-11
javascript實(shí)現(xiàn)鼠標(biāo)拖尾特效
這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)鼠標(biāo)拖尾特效,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
不用AJAX和IFRAME,說說真正意義上的ASP+JS無刷新技術(shù)
注明:以下方法都經(jīng)過實(shí)例和開發(fā)的長期驗(yàn)證,其實(shí)這些技術(shù)早就有,今天只不過自己歸納一下2008-09-09
JavaScript分步實(shí)現(xiàn)一個(gè)出生日期的正則表達(dá)式
本文把出生日期分割成幾個(gè)部分,分步地介紹了實(shí)現(xiàn)一個(gè)出生日期校驗(yàn)的完整過程。對(duì)出生日期正則表達(dá)式感興趣的朋友參考下吧2018-03-03
Javascript 繼承機(jī)制的實(shí)現(xiàn)
要用ECMAScript實(shí)現(xiàn)繼承機(jī)制,首先從基類入手。所有開發(fā)者定義的類都可作為基類。出于安全原因,本地類和宿主類不能作為基類,這樣可以防止公用訪問編譯過的瀏覽器級(jí)的代碼,因?yàn)檫@些代碼可以被用于惡意攻擊。2009-08-08
echarts數(shù)據(jù)可視化實(shí)現(xiàn)多個(gè)柱狀堆疊圖頂部顯示總數(shù)示例
這篇文章主要為大家介紹了echarts實(shí)現(xiàn)多個(gè)柱狀堆疊圖頂部顯示總數(shù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
js實(shí)現(xiàn)點(diǎn)擊鏈接后窗口縮小并居中的方法
這篇文章主要介紹了js實(shí)現(xiàn)點(diǎn)擊鏈接后窗口縮小并居中的方法,實(shí)例分析了javascript操作窗口的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03

