vue多頁面項目實現(xiàn)版本快照功能示例詳解
背景
App落地頁迭代頻繁,且需兼容App與各小App,目前是單向前進迭代,會存在以下問題:
- 跳轉(zhuǎn)原生交互;如:某個落地頁增加了只有主App的才有的原生功能,小App就無法投放;
- 歷史版本歸因與復用,歷史測試版本的落地頁都在主鏈上進行版本迭代,不利于落地頁成功、失敗版本的區(qū)分統(tǒng)計以及沉淀;
所以需實現(xiàn)一個快照版本的功能,將構建產(chǎn)物以特定的命名規(guī)則給保留下來,并且支持鏈接訪問??梢越鉀Q已上問題;
- 若主App落地頁迭代了新的原生功能,小App可以更換投放歷史的鏈接,等小App支持了該原生功能,再恢復成主鏈接;
- 將每次迭代的鏈接利用管理后臺維護,生成完資源后將changelog等信息上傳至后臺,方便產(chǎn)品管理。
需要解決的問題:
- 如何保存頁面資源
- 只是項目中的幾個頁面需要支持這個功能,如何設計這個配置的開啟與關閉
- 每次只生成改動的頁面,實現(xiàn)增量生成。
實現(xiàn)思路:
在需要配置快照版本的頁面新增配置文件,構建過程中獲取到這些需要快照版本功能的入口,由于迭代可能只更新到其中的某個頁面,還需要做到增量生成,利用hashchunk對比構建上一次與這一次是否一致,若一致,則刪除,若不一致,則保留,最后以當前提交的commitid作為目錄將產(chǎn)物保存至dist/目錄中,一同上傳服務器中。

實現(xiàn)過程:
資源命名;因為每次迭代都會生成新的commitid,符合唯一性與可追溯性,適合用于當資源目錄。再以特定的目錄名標識此文件夾屬于快照版本;最終命名snaps/{commitid}/pages/{頁面}.html
文件保存:
在以往項目配置項目打包會清除dist目錄內(nèi)容,打包完成再傳到服務器;為了實現(xiàn)歷史資源保存,需要改一下clean-webpack-plugin的配置,每次只清除上一次的主構建產(chǎn)物,而不是整個dist目錄。
版本快照的webpack配置;主要思路為:每個頁面的配置文件新增快照版本標識{snapshot: true}, 獲取到這些頁面的入口文件,傳入webpack的entry配置。
配置產(chǎn)物路徑; 產(chǎn)物文件名filename、產(chǎn)物路徑path、靜態(tài)資源路徑assetModuleFilename、靜態(tài)資源基礎路徑publicPath
filename: [name]/assets/js/main.[chunkhash:8].js, 利用chunkhash做瀏覽器緩存
path:path.join(path.resolve(), dist/snaps/${commit}),以snaps作為父目錄,commit標識每次生成快照版本的版本號。
assetModuleFilename: 將資源放入對應頁面的目錄,如dist/snaps/${commit}/assets/images/a.png,再后續(xù)實現(xiàn)增量構建時才能直接刪除。
assetModuleFilename: ({ module }) => {
let ctx = module.context;
let origin = path.resolve("src/assets");
let dir = ctx.replace(origin, "").replace(/\\/g, "/")
return `${dir}/assets/images/[hash][ext]`
}
publicPath: /snaps/{{${COMMIT_ID_PACEHOLDER}}}/, 因為webpack靜態(tài)資源基礎路徑默認配置是/,需要將其指向快照版本目錄對應的版本,確保資源能正常訪問。COMMIT_ID_PACEHOLDER是commitid占位符,因為后續(xù)需要通過hashchunk對比產(chǎn)物是否更新,如果這里指定commitid,每次構建產(chǎn)物hashchunk都不一樣,就無法做到增量更新;所以這里需要一個唯一的字符串,在構建完后用腳本去替換真實的commitid。
實現(xiàn)增量生成與頁面信息上傳至管理后臺:SnapshotPlugin
在plugin的done鉤子,獲取到此次入口的chunkHash(compilation.entrypoints[i].chunks)與上次的hashchunk記錄進行對比,若不相同,則保留文件,若相同,說明此次該頁面無改動,則將改頁面的資源刪除,則將該頁面生成的刪除刪除,最后將此次生成的hashchunk值保存下來,以供下次對比;對比文件數(shù)據(jù)結(jié)構如下:
{
"test-page-1": "6e364aeafe957d7929223750b326a4f3",
"test-page-2": "f586eeef3a1f37672d54b0e5a1d5c0c7",
}
若是需要生成的頁面,還需要替換掉COMMIT_ID_PACEHOLDER,遍歷此次生成的目錄中的js、css文件,將COMMIT_ID_PACEHOLDER替換成此次的commitid,確保資源能夠訪問。
最后通過調(diào)取接口存儲頁面鏈接、changelog、標題等信息。
關鍵代碼:
module.exports = class SnapshotPlugin {
constructor({ commitId }) {
this.curCommitId = commitId
}
apply(compiler) {
compiler.hooks.done.tap('snapshot-plugin', ({ compilation: { outputOptions, entrypoints } }) => {
console.log('快照對比----snapshot-plugin');
const PAGES_ROOT = outputOptions.path
// 獲取上次構建的chunkhash值
const snapHashMap = getLastTimeSnapHash()
// 獲取上次沒有上傳至管理后臺的頁面信息數(shù)據(jù),此次一同發(fā)送
const snapPages = getLastTimeSnapPages()
let count = entrypoints.size
for (const [key, val] of entrypoints) {
// key是入口name, val中可以獲取此次的hash值
const curChunkHash = (val.chunks.map(item => item.hash).filter(item => item) || []).join(':')
// 如果不相同,則說明有改動,將此添加到變更json中
if (!snapHashMap[key] || snapHashMap[key] !== curChunkHash) {
snapHashMap[key] = curChunkHash
// 獲取頁面的配置文件,得到頁面配置信息,如標題等
const config = getPageConfig([key]) || {}
// 生成管理后臺數(shù)據(jù)
snapPages.push(genSnapConfig(getSnapLink(this.curCommitId, key), config[key].title || key))
} else {
// 如果相同,則刪除對應的文件目錄,因為此個版本沒有更新,不需要生成快照
removeDir(`${PAGES_ROOT}/${key}`)
count--
}
}
if (count > 0) {
// 替換commitid
replaceCommitHolder(PAGES_ROOT, this.curCommitId)
// 更新頁面的chunchHash值
setCurrTimeSnapHash(snapHashMap)
} else {
removeDir(`${outputOptions.path}`)
}
if (snapPages.length > 0) {
// 調(diào)取接口存儲頁面信息
postSnapData(snapPages).then(() => {
console.log('postSnapData --- success');
// 新增成功,刪除緩存文件
removeDir(resolve(PATH_CONFIG.SNAPS_PAGES))
}).catch(() => {
console.log('postSnapData --- fail');
// 新增失敗,則將數(shù)據(jù)存儲只本地
setCurrTimeSnapPages(snapPages)
})
}
})
}
}以上就是vue多頁面項目實現(xiàn)版本快照功能示例詳解的詳細內(nèi)容,更多關于vue多頁面項目版本快照的資料請關注腳本之家其它相關文章!
相關文章
基于vue+uniapp直播項目實現(xiàn)uni-app仿抖音/陌陌直播室功能
uni-liveShow是一個基于vue+uni-app技術開發(fā)的集小視頻/IM聊天/直播等功能于一體的微直播項目。本文通過實例圖文的形式給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友參考下吧2019-11-11
一文詳解Pinia和Vuex與兩個Vue狀態(tài)管理模式
這篇文章主要介紹了一文詳解Pinia和Vuex與兩個Vue狀態(tài)管理模式,Pinia和Vuex一樣都是是vue的全局狀態(tài)管理器。其實Pinia就是Vuex5,只不過為了尊重原作者的貢獻就沿用了這個看起來很甜的名字Pinia2022-08-08
vue的ElementUI form表單如何給label屬性字符串中添加空白占位符
這篇文章主要介紹了vue的ElementUI form表單如何給label屬性字符串中添加空白占位符問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10

