精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Islands Architecture(孤島架構(gòu))在攜程新版首頁的實(shí)踐

開發(fā) 新聞
本文通過攜程新版首頁項(xiàng)目系統(tǒng)的介紹了其整體架構(gòu)設(shè)計(jì),組件開發(fā),數(shù)據(jù)配置的整個(gè)流程及實(shí)現(xiàn)原理,是對島嶼式架構(gòu)的一次實(shí)踐。

作者簡介

攜程前端框架團(tuán)隊(duì),為攜程集團(tuán)各業(yè)務(wù)線在PC、H5、小程序等各階段提供優(yōu)秀的Web解決方案。當(dāng)前主要專注方向包括:新一代研發(fā)模式探索,Rust構(gòu)建工具鏈路升級、Serverless應(yīng)用框架開發(fā)、在線文檔系統(tǒng)開發(fā)、低代碼平臺(tái)搭建、適老化與無障礙探索等。

一、項(xiàng)目背景

2022,攜程PC版首頁終于迎來了首次改版,完成了用戶體驗(yàn)與技術(shù)棧的全面升級。

作為與用戶連接的重要入口,舊版PC首頁已經(jīng)陪伴攜程走過了22年,承擔(dān)著重要使命的同時(shí),也遇到了很多問題:

維護(hù)/更新困難

祖?zhèn)鞔a黑盒邏輯過多,產(chǎn)品也難以推動(dòng)新需求的上線,舊版首頁已經(jīng)不能滿足高速發(fā)展的業(yè)務(wù)需求。

技術(shù)棧陳舊且不統(tǒng)一

互聯(lián)網(wǎng)技術(shù)日新月異,舊版首頁的整體架構(gòu)設(shè)計(jì)和技術(shù)棧都相對落后,且大首頁中各個(gè)組件的研發(fā)涉及多事業(yè)部合作,存在技術(shù)選型差異的問題,增加了維護(hù)成本。

用戶體驗(yàn)有待改善

舊版攜程首頁的設(shè)計(jì)風(fēng)格沿用至今,在視覺和交互層面上,都已經(jīng)難以滿足用戶不斷提升的互聯(lián)網(wǎng)體驗(yàn)和審美需求。

綜合上述情況,為了給用戶提供更好的服務(wù),攜程首頁的整體改造迫在眉睫。

二、需求分析

攜程首頁改造需要考慮的核心問題包括以下幾個(gè)方面:

技術(shù)選型

為了優(yōu)化首屏性能,提升用戶體驗(yàn),攜程新版首頁采用服務(wù)端渲染模式。在技術(shù)選型上,考慮到我們希望應(yīng)用層是輕量的,只做頁面HTML拼接和響應(yīng)兩件事情,最終決定基于Node.js構(gòu)建應(yīng)用載體,客戶端則統(tǒng)一使用公司主流的React技術(shù)棧。

跨團(tuán)隊(duì)合作

首頁作為攜程的重要門戶,涉及多業(yè)務(wù)線的流量入口。如圖1所示,我們可以將整個(gè)頁面進(jìn)行切割,按業(yè)務(wù)線劃分成多個(gè)組件模塊。

圖片

圖1 攜程首頁業(yè)務(wù)模塊切分圖

可以看到,整個(gè)頁面的研發(fā)是需要框架部門和各個(gè)事業(yè)部業(yè)務(wù)團(tuán)隊(duì)緊密合作才能完成的,這就需要一整套完善的跨團(tuán)隊(duì)合作模式。其中,我們希望業(yè)務(wù)團(tuán)隊(duì)只需要關(guān)注業(yè)務(wù)邏輯的實(shí)現(xiàn),完成組件模塊的開發(fā)。框架團(tuán)隊(duì)則負(fù)責(zé)提供:

  • 組件模塊服務(wù)端/客戶端構(gòu)建方案
  • 組件模塊服務(wù)端渲染方案
  • 應(yīng)用層面,實(shí)現(xiàn)頁面組裝及響應(yīng)
  • 組件模塊開發(fā)環(huán)境

監(jiān)控及維護(hù)

上線后,我們需要時(shí)刻關(guān)注應(yīng)用狀態(tài),及時(shí)響應(yīng)異常情況。因此,需要對應(yīng)用及組件進(jìn)行埋點(diǎn)監(jiān)控。除此之外,由于需要跨團(tuán)隊(duì)合作,對于業(yè)務(wù)組件,我們希望各個(gè)業(yè)務(wù)團(tuán)隊(duì)不僅可以實(shí)現(xiàn)開發(fā)/構(gòu)建自由,彼此獨(dú)立互不影響,在監(jiān)控及版本管理上也能實(shí)現(xiàn)自控。因此,我們將各個(gè)業(yè)務(wù)組件包裝成Node.js應(yīng)用,開發(fā)人員可以直接在發(fā)布系統(tǒng)查看組件版本,完成發(fā)布/回退,也可以通過應(yīng)用ID在埋點(diǎn)管理平臺(tái)查看組件的相關(guān)埋點(diǎn)。

三、整體架構(gòu)設(shè)計(jì)

圖片

圖2 攜程首頁架構(gòu)設(shè)計(jì)圖

基于上述需求分析,攜程新版首頁的整體架構(gòu)設(shè)計(jì)如圖2所示,可以分為四個(gè)部分:

業(yè)務(wù)模塊開發(fā)

我們將攜程首頁拆分為多個(gè)業(yè)務(wù)模塊,由各業(yè)務(wù)團(tuán)隊(duì)負(fù)責(zé)完成相應(yīng)組件的開發(fā)。與常規(guī)React組件開發(fā)不同的是,首先,開發(fā)人員需要在配置文件中設(shè)置好模塊相關(guān)配置,如組件唯一ID;其次,組件開發(fā)需遵循一些規(guī)則,如為防止出現(xiàn)樣式污染,我們強(qiáng)制使用CSS Modules;最后,我們支持服務(wù)端渲染組件,可以在服務(wù)端生命周期中拉取數(shù)據(jù),然后在服務(wù)端/客戶端使用。為了更好的輔助業(yè)務(wù)團(tuán)隊(duì)完成組件開發(fā),框架團(tuán)隊(duì)會(huì)提供腳手架幫助創(chuàng)建組件模版,搭建開發(fā)環(huán)境,模擬完整首頁場景。

業(yè)務(wù)模塊構(gòu)建

業(yè)務(wù)模塊開發(fā)完成后,就需要構(gòu)建/發(fā)布至生產(chǎn)環(huán)境。整個(gè)構(gòu)建過程會(huì)在Pipeline中完成,開發(fā)人員git push代碼后會(huì)自動(dòng)觸發(fā)。基于不同的entry及配置,我們會(huì)使用webpack分別完成客戶端及服務(wù)端代碼的生產(chǎn)態(tài)構(gòu)建,并將客戶端構(gòu)建產(chǎn)物(js+css)上傳至靜態(tài)資源管理系統(tǒng)。

之后,我們會(huì)將服務(wù)端構(gòu)建產(chǎn)物(js)連同組件及靜態(tài)資源版本相關(guān)信息包裝成一個(gè)Job應(yīng)用,該應(yīng)用中會(huì)有一個(gè)定時(shí)任務(wù)負(fù)責(zé)推送當(dāng)前版本信息,觸發(fā)組件完成服務(wù)端渲染,這里我們是使用定時(shí)器來實(shí)現(xiàn)定時(shí)任務(wù)的管理。最后,需要由開發(fā)人員在發(fā)布系統(tǒng)中將構(gòu)建好的應(yīng)用鏡像部署到生產(chǎn)環(huán)境,完成組件的發(fā)布。

業(yè)務(wù)模塊服務(wù)端渲染

業(yè)務(wù)模塊的服務(wù)端渲染主要包括兩部分:

  • 在沙盒中完成服務(wù)端渲染
  • 將組件相關(guān)信息及渲染生成的html存到Redis中

我們將相關(guān)功能實(shí)現(xiàn)封裝成云函數(shù),作為服務(wù)提供出去。由于部分組件對服務(wù)端渲染具有數(shù)據(jù)更新的需求。因此,上文我們提到過,Job應(yīng)用中會(huì)有一個(gè)定時(shí)任務(wù),負(fù)責(zé)觸發(fā)組件進(jìn)行服務(wù)端渲染,這里也就是會(huì)觸發(fā)云函數(shù)的調(diào)用。

應(yīng)用頁面組裝

最后,我們就需要在應(yīng)用中將所有的業(yè)務(wù)模塊拼裝起來,定時(shí)從Redis中獲取組件相關(guān)信息,組裝成首頁html返回到客戶端。

四、整體架構(gòu)的核心功能實(shí)現(xiàn)

對應(yīng)上述首頁架構(gòu)設(shè)計(jì),我們簡要介紹下部分核心功能的實(shí)現(xiàn):

4.1 搭建組件開發(fā)環(huán)境,模擬首頁場景

我們會(huì)在開發(fā)階段提供腳手架輔助業(yè)務(wù)團(tuán)隊(duì)開發(fā)組件,其中一項(xiàng)重要功能就是搭建組件開發(fā)環(huán)境。常規(guī)的webpack搭建React開發(fā)環(huán)境我們這里就不贅述了,為了實(shí)現(xiàn)開發(fā)環(huán)境的統(tǒng)一標(biāo)準(zhǔn)化,我們還做了以下事情:

  • 將webpack,babel的相關(guān)配置封裝到cli中,有選擇的提供可配置項(xiàng),規(guī)范化組件開發(fā)環(huán)境
  • 對entry進(jìn)行收口。這里需要注意的是,服務(wù)端和客戶端的entry是不同的,對于客戶端entry,需要獲取服務(wù)端傳過來的數(shù)據(jù),并通過調(diào)用ReactDOM.render()完成渲染:
import React from 'react'
import ReactDOM from 'react-dom'
import Comp from 'COMP_PATH'
const render = async() => {
let data
// 獲取服務(wù)端傳遞到客戶端數(shù)據(jù)
const container = document.getElementById('__MFE___MODULE___DATA__')
if (container && container.textContent) {
try {
data = JSON.parse(container.textContent)
} catch(e) {
console.log(e)
}
}

const root = document.getElementById('__MODULE__')

// 客戶端渲染組件
if (module.hot) {
ReactDOM.render(<Comp serverData={data} />, root)
} else {
ReactDOM.hydrate(<ErrorBoundary><Comp serverData={data} /></ErrorBoundary>, root)
}
}
render()

對于服務(wù)端entry,則需要調(diào)用服務(wù)端生命周期拉取數(shù)據(jù),并調(diào)用renderToString()完成渲染:

import React from 'react'
import { renderToString } from 'react-dom/server'
import Comp from 'COMP_PATH'
const render = async() => {
let data
// 執(zhí)行服務(wù)端生命周期
if (Comp.getInitialProps) {
data = await Comp.getInitialProps(_ctx)
}
// 沙盒中傳入setMfeData方法,見下文中服務(wù)端渲染組件實(shí)現(xiàn)
setMfeData(data)

// 服務(wù)端渲染組件,返回html
return renderToString(<Comp serverData={data} />)
}
export default render()

搭建首頁場景。我們希望開發(fā)人員在組件開發(fā)時(shí),就可以看到其嵌入在整個(gè)首頁中的效果,而不是只能看到自己的組件。因此,我們在服務(wù)端處理頁面請求時(shí),通過以下方式搭建了首頁場景:

  • 讀取首頁html文件(首次從線上拉取)
  • 解析/處理首頁html,移除當(dāng)前組件相關(guān)的線上script/link標(biāo)簽,添加開發(fā)態(tài)構(gòu)建產(chǎn)物
  • 在沙盒中服務(wù)端渲染組件,替換首頁html中的組件html

4.2 SSR-Service 服務(wù)端渲染組件

我們會(huì)在沙盒中運(yùn)行服務(wù)端構(gòu)建生成的代碼(可結(jié)合上文中服務(wù)端entry看),完成組件渲染,得到服務(wù)端生命周期中返回的數(shù)據(jù)及組件html。

const vm = require('vm')
const render = async ({content, request}) => {
// content即為服務(wù)端構(gòu)建生成的代碼
const script = new vm.Script(content)
let moduleObj = {
exports: {}
}
let mfeEnv = 'prod'
let mfeData

// 基于云函數(shù)中的request模擬req
const _req = {
url: request.rawPath,
query: request.queryStringParameters,
headers: request.headers
}

let sandBox = {
...global,
process,
require,
module: moduleObj,
console,
_ctx: {
req: _req,
env: mfeEnv,
},
setMfeData: (data) => {
mfeData = data
}
}

// 沙盒中運(yùn)行,執(zhí)行服務(wù)端渲染
const ctx = vm.createContext(sandBox)
script.runInContext(ctx)
const comp = await sandBox.module.exports.default

return {
comp,
mfeData
}
}

4.3 整體頁面組裝

在首頁應(yīng)用中,我們會(huì)定時(shí)從redis中獲取組件相關(guān)信息,拼裝首頁html,在有客戶端請求進(jìn)入時(shí),直接返回緩存中的最新html。

let indexCache = ''
const renderPage = async (content) => {
// 加載首頁html
const $ = cheerio.load(content)
// 更新組件
for (let module of modules) {
try {
// moduleData為從redis取到的數(shù)據(jù)
let data = moduleData[module] || ''
if (!data) {
continue
}

data = typeof data == 'string' ? JSON.parse(data) : data
const {comp, version, mfeData, style} = data

// 更新組件相關(guān)的html,link,script標(biāo)簽
parse(module, comp, $, version, mfeData, style)
} catch(e) {
console.log(e)
}
}

// 生成html
const payload = $.html()
if (!payload) {
throw Error('renderPage error - html is null')
}

// 更新緩存
indexCache = payload
}

五、公共組件的渲染原理及技術(shù)細(xì)節(jié)

前面說的是島嶼式架構(gòu)之首頁的整體架構(gòu)和獨(dú)立組件渲染的核心實(shí)現(xiàn),其中有些獨(dú)立組件(左側(cè)菜單欄,頭部等)除了在大首頁中使用,還會(huì)在其他的頁面中使用,這里就稱為公共組件。

5.1 公共組件需求點(diǎn)和痛點(diǎn)分析

在開始開發(fā)公共組件前,需要整理一下目前各個(gè)事業(yè)部的接入需求、成本及痛點(diǎn)。所以總結(jié)了以下問題點(diǎn):

各個(gè)事業(yè)部的站點(diǎn)技術(shù)架構(gòu)不同

由于各個(gè)事業(yè)部的站點(diǎn)技術(shù)架構(gòu)不同。有的事業(yè)部可能是服務(wù)端渲染,有的可能為客戶端渲染 。在服務(wù)端渲染中,技術(shù)棧又可能出現(xiàn) JAVA 和NODE 。而在客戶端渲染中,各個(gè)事業(yè)部技術(shù)棧也不統(tǒng)一,有React、JQuery或者Vue等等前端框架。這里的問題是各個(gè)事業(yè)部的技術(shù)棧的錯(cuò)綜復(fù)雜,如果分開維護(hù)會(huì)帶來不同的版本及很高的維護(hù)成本。

所有頁面中的公共組件有變更時(shí)能否統(tǒng)一熱更新

當(dāng)公共組件的改動(dòng)或有問題需要修復(fù)時(shí),不能讓所有的頁面都去變更公共組件,而是應(yīng)該我們變更后,所有頁面上的公共組件會(huì)靜默生效,各個(gè)事業(yè)部無需關(guān)心公共組件的變更。

公共組件的樣式如何不對頁面造成巨大影響

由于各個(gè)業(yè)務(wù)方的樣式風(fēng)格不同并且還存在一些全局的公共樣式,如何才能保證每個(gè)接入方為下圖的頁面布局方式,其頁面組成的方式為陰影部分是事業(yè)部所維護(hù)的組件,其他是公共組件。

圖片

由于歷史原因,舊版的公共組件已經(jīng)使用了很多年了,新版頭尾和舊版的頭尾布局構(gòu)造不同,要如何設(shè)計(jì),才能使其改動(dòng)最小,而不是去做很大的改動(dòng)去適配公共組件。新舊版大首頁頁面布局變化如下圖:

圖片

公共組件的渲染性能問題

在背景中提到的不同形態(tài)的公共組件(比如有些不需要左側(cè)菜單或者頭部樣式的不同),如何在客戶端能第一時(shí)間展示給用戶相應(yīng)組件形態(tài)并且支持搜索引擎優(yōu)化(SEO)。當(dāng)多個(gè)公共組件在頁面中如何能快速進(jìn)行加載及渲染。

5.2 解決公共組件問題和痛點(diǎn)

問題一:各個(gè)事業(yè)部的站點(diǎn)技術(shù)架構(gòu)不同

前面提到了各個(gè)業(yè)務(wù)支線的技術(shù)棧不統(tǒng)一的問題,并且還存在服務(wù)端和客戶端渲染的情況,如果為了多個(gè)技術(shù)棧去維護(hù)多個(gè)公共組件維護(hù)成本極高,且沒有辦法做到一套代碼多端使用。這里就從服務(wù)端和客戶端渲染分析,提供的相應(yīng)解決的方案

CSR(客戶端渲染)

在CSR中,技術(shù)棧也不同。由于有React、Vue、jQuery,所以我們需要提供的應(yīng)該是一個(gè)原生JS的公共組件,這樣能保證維護(hù)成本。但是大首頁的首屏技術(shù)棧已經(jīng)為React,再去開發(fā)及維護(hù)一套原生JS組件顯得冗余。所以需要一個(gè)方案來支持多技術(shù)棧運(yùn)行,并且能夠兼容我們大首頁首屏的技術(shù)棧。

最終的方案是使用Preact,它很輕量,重點(diǎn)是它可以幫助我們解決多技術(shù)棧運(yùn)行并且能夠兼容React。可萬一有頁面同樣在使用 Preact 和我們沖突怎么辦? 這里將Preact單獨(dú)打包出來common包并且重名了全局的變量。這樣即使頁面使用了Preact也不會(huì)和我們有沖突,在webpack的 externals 的選項(xiàng)中可以配置組件需要的包名。

{
//...
externals: {
preact: 'xxxxxx'
}
// ...
}

SSR(服務(wù)端渲染)

在SSR中,在技術(shù)棧上選擇了Preact,Preact 它同樣支持 SSR,可以構(gòu)建一個(gè)服務(wù)端的JS來支持SSR。因此我們的問題就迎刃而解了,我們在組件構(gòu)建的時(shí)候多生成一份 Preact 的 SSR 的 JS,用沙盒執(zhí)行服務(wù)端渲染輸出HTML并存儲(chǔ)。我們調(diào)研了以前的老的公共組件,全部攜程的業(yè)務(wù)線存在的技術(shù)棧只有兩種:JAVA、NODE,這樣就提供兩個(gè)接入方式的外殼即可——兩套不同語言的SDK及接入方式,其內(nèi)部都是獲取統(tǒng)一的公共組件HTML字符串供頁面使用。

{
// ...
resolve: {
extensions: ['.ts', '.tsx', '.js'],
alias: isPreact ? {
"react": "preact/compat",
"react-dom": "preact/compat", // Must be below test-utils
"react/jsx-runtime": "preact/jsx-runtime"
} : {},
}
// ...
}

?(React輕松轉(zhuǎn)換Preact)

問題二:所有頁面中的公共組件有變更時(shí)能否統(tǒng)一熱更新

當(dāng)公共組件更新或者修復(fù)緊急的某些問題,不應(yīng)該影響業(yè)務(wù)方頁面,應(yīng)該是自動(dòng)進(jìn)行更新,當(dāng)用戶訪問頁面時(shí),看到就是最新的公共組件,因此我們沒有做類似npm包多版本的方式進(jìn)行管理。

基于問題一的基礎(chǔ)上:

SSR(服務(wù)端渲染)的情況

SSR的服務(wù)端的HTML從哪里來?HTML怎么樣才能是最新的?

我們需要構(gòu)建出來一份服務(wù)端的JS在沙盒中輸出HTML,存儲(chǔ)在了 Redis 中,將多個(gè)公共組件統(tǒng)一構(gòu)建出了多個(gè)HTML,分別存放在 Redis 里。業(yè)務(wù)方接入JAVA、NODE的SDK其實(shí)要做的只有一件事:守護(hù)進(jìn)程定時(shí)的去 Redis 里拿到最新的 HTML 結(jié)果。

圖片

CSR(客戶端渲染)的情況

CSR如何保持為最新公共組件的?

需要一臺(tái)機(jī)器同多語言技術(shù)棧SDK一樣,定時(shí)從 Redis 里讀取數(shù)據(jù),對外暴露一個(gè)接口,供客戶端的JS調(diào)用。這樣,每次用戶訪問頁面的時(shí)候,客戶端JS會(huì)發(fā)起請求,保證用戶所看到的的內(nèi)容永遠(yuǎn)是最新的。

圖片

問題三:樣式問題

目前新版的相比之前舊版的公共組件在樣式和交互上更加復(fù)雜。由于左側(cè)菜單的存在,使得布局構(gòu)造不同,而且各個(gè)事業(yè)部的頁面樣式可能五花八門,很難保證不會(huì)影響自身樣式和事件等問題。

比如:如果使用flex的布局,需要在最外層套用一個(gè)div,如果不套用的話則需要在body元素上添加flex樣式,但是不能保證其他的事業(yè)部的頁面的 body 是否有其他的樣式,甚至body 內(nèi)是否存在其他的div元素等。還有很多事業(yè)部的頁面的類似滾動(dòng)等事件監(jiān)聽都是在body上進(jìn)行監(jiān)聽的,所以如果外層套取div,這種形式會(huì)讓原來頁面的事件監(jiān)聽滾動(dòng)非常麻煩,各個(gè)事業(yè)部原來監(jiān)聽body的事件,需要一一進(jìn)行改動(dòng)。

圖片

觀察老項(xiàng)目發(fā)現(xiàn),之前的公共組件骨架有個(gè)最外層的div元素,并且有一個(gè)名為"container"的id,我們要做的就是將左側(cè)的菜單 fixed 在左側(cè)就好了.關(guān)于css的fixed的兼容性:

圖片

(樣式屬性兼容情況)

但是此時(shí)有個(gè)問題是,我們的左菜單是可以展開或收起的。所以在展開和收起的時(shí)候需要一個(gè)全局的通信機(jī)制,當(dāng)左側(cè)的組件變化時(shí),在組件的內(nèi)部應(yīng)該觸發(fā)全局的通信鉤子,通知 id 為container 的div元素跟隨左菜單變化,達(dá)到 flex 布局的效果。

圖片

(左側(cè)菜單展開)

圖片

(左側(cè)菜單收起)

問題四:性能問題

基于問題 1/2/3 大概已經(jīng)擬定了技術(shù)的方向,并且已經(jīng)能在各個(gè)事業(yè)部行的通了,證明思路是沒有問題的,但是還有些個(gè)瑣碎的問題需要考慮:

因?yàn)槭嵌〞r(shí)從服務(wù)端里進(jìn)行拉取,那么第一次沒有拉取時(shí)或者在客戶端渲染的情況下請求server是需要時(shí)間的,這樣請求回來HTML再進(jìn)行異步渲染,是否時(shí)間過長?

為了解決上面的問題,我們考慮了先準(zhǔn)備一個(gè)預(yù)渲染的HTML占位,類似骨架屏的意思,此時(shí)就可以先進(jìn)行骨架屏的渲染,之后再異步拉取渲染,來解決異步渲染白屏等待時(shí)間的問題。

圖片

多個(gè)公共組件的客戶端 JS 資源是否能夠合并,將Preact公共包也一起合并打包。

為了解決這個(gè)問題,我們的那臺(tái)跑沙盒JOB機(jī)器就可以繼續(xù)做這件事情。因?yàn)槊總€(gè)組件構(gòu)建后有資源的版本,我們需要將版本存儲(chǔ)一份,一旦新的組件構(gòu)建后,拉取其他公共組件的資源版本,將多個(gè)JS組裝在一起。同時(shí)因?yàn)槲覀冇昧?Preact ,抽取了 Preact 為一個(gè)共同依賴,將它放在最前面,保證它的最先執(zhí)行。

圖片

六、公共組件的數(shù)據(jù)動(dòng)態(tài)配置系統(tǒng)

介紹完攜程新版大首頁的公共組件的渲染原理及技術(shù)細(xì)節(jié),接下來就是公共組件中的數(shù)據(jù)如何支持動(dòng)態(tài)配置。

6.1 為什么需要組件數(shù)據(jù)動(dòng)態(tài)配置系統(tǒng)

攜程PC版首頁進(jìn)行改版的過程中,按業(yè)務(wù)線將整個(gè)頁面劃分成了多個(gè)組件模塊,每個(gè)組件模塊內(nèi)都有需要展示的業(yè)務(wù)數(shù)據(jù)。而頁面上線之后,隨著產(chǎn)品需求的變更,業(yè)務(wù)數(shù)據(jù)會(huì)被頻繁的更新,如果每次更新數(shù)據(jù)都發(fā)布一次模塊代碼的話,這個(gè)成本和風(fēng)險(xiǎn)很大。

因此,將代碼和數(shù)據(jù)分開發(fā)布是很有必要的,當(dāng)組件數(shù)據(jù)有改動(dòng)時(shí)無需發(fā)布組件,搭建一個(gè)專門用于發(fā)布大首頁數(shù)據(jù)配置的管理系統(tǒng)勢在必行。

6.2 組件數(shù)據(jù)動(dòng)態(tài)配置系統(tǒng)的需求分析

攜程大首頁數(shù)據(jù)配置管理系統(tǒng)的核心功能是完成數(shù)據(jù)配置的發(fā)布,并保證發(fā)布的可靠性和安全性,為了實(shí)現(xiàn)這個(gè)目標(biāo),此管理系統(tǒng)應(yīng)制定一套完整的數(shù)據(jù)檢驗(yàn)規(guī)范和發(fā)布流程,其中主要功能包括:

  • 規(guī)范數(shù)據(jù)配置上傳格式,本地配置數(shù)據(jù)與線上配置數(shù)據(jù)差異對比
  • 制定不同組件模塊的數(shù)據(jù)校驗(yàn)規(guī)則,并以此校驗(yàn)數(shù)據(jù)合法性
  • 數(shù)據(jù)配置發(fā)布前效果預(yù)覽,確保與線上其他組件模塊之間相互不影響
  • 更新線上頁面

6.3 組件數(shù)據(jù)動(dòng)態(tài)配置系統(tǒng)架構(gòu)設(shè)計(jì)

圖片

圖1 大首頁數(shù)據(jù)配置管理系統(tǒng)架構(gòu)設(shè)計(jì)

數(shù)據(jù)配置管理系統(tǒng)的架構(gòu)設(shè)計(jì) (如圖1 所示),為了實(shí)現(xiàn)需求分析中的四塊主要功能,整個(gè)管理系統(tǒng)主要搭建了兩個(gè)應(yīng)用:

前端應(yīng)用:以可視化界面的形式提供本地上傳配置文件,預(yù)覽數(shù)據(jù)效果以及更新頁面等功能,同時(shí)完成了數(shù)據(jù)校驗(yàn)和預(yù)覽檢測。

Node服務(wù):主要負(fù)責(zé)數(shù)據(jù)配置的處理及發(fā)布,將前端應(yīng)用上傳的數(shù)據(jù)配置保存到QConfig系統(tǒng)中。

其中,前端應(yīng)用提供的預(yù)覽功能的架構(gòu)設(shè)計(jì)如下圖2 所示:

圖片

圖2 預(yù)覽功能架構(gòu)設(shè)計(jì)

預(yù)覽功能的實(shí)現(xiàn)主要依賴三部分 (如圖2所示):

前端應(yīng)用:負(fù)責(zé)提供數(shù)據(jù)配置和展示頁面效果。

服務(wù)端渲染應(yīng)用:調(diào)用組件渲染函數(shù),根據(jù)數(shù)據(jù)配置渲染出當(dāng)前組件HTML,并從Redis拉取其他組件的HTML,而后組裝成一個(gè)完整頁面的HTML吐給前端應(yīng)用。

Redis:存儲(chǔ)所有組件模塊的HTML。

6.4 數(shù)據(jù)配置管理系統(tǒng)的核心功能實(shí)現(xiàn)

前面部分介紹了數(shù)據(jù)配置管理系統(tǒng)的架構(gòu)設(shè)計(jì),這里就架構(gòu)中核心功能部分的實(shí)現(xiàn)進(jìn)行詳細(xì)介紹,主要包括:

  • 數(shù)據(jù)配置規(guī)范及校驗(yàn)
  • 組件及頁面預(yù)覽

數(shù)據(jù)配置規(guī)范及數(shù)據(jù)校驗(yàn)

本地上傳的數(shù)據(jù)配置最終要傳給組件渲染出來,而數(shù)據(jù)配置的上傳者不一定是組件的開發(fā)者,上傳者并不一定清楚組件所需數(shù)據(jù)的類型和結(jié)構(gòu),那么如何保證上傳的數(shù)據(jù)與組件要求的數(shù)據(jù)結(jié)構(gòu)保持一致呢?

這就需要管理系統(tǒng)制定一套數(shù)據(jù)配置規(guī)范來約束上傳的數(shù)據(jù),然而不同的組件,其數(shù)據(jù)結(jié)構(gòu)是不同的,那么每個(gè)組件都應(yīng)有一套自己的規(guī)范。管理系統(tǒng)提供了兩種制定數(shù)據(jù)規(guī)范的方式:

  • 錄入組件的基本信息,其中包括詳細(xì)的數(shù)據(jù)結(jié)構(gòu):數(shù)據(jù)名稱,數(shù)據(jù)類型,必傳或可選等。
  • 組件使用TypeScript(推薦的組件開發(fā)語言)語言開發(fā)時(shí),可以上傳.d.ts聲明文件,系統(tǒng)會(huì)根據(jù)此文件解析出具體的組件信息及數(shù)據(jù)結(jié)構(gòu)。

規(guī)范制定完成之后管理系統(tǒng)會(huì)將其存儲(chǔ)起來,每次有上傳者上傳某一組件的數(shù)據(jù)配置后(為方便上傳者修改數(shù)據(jù),管理系統(tǒng)規(guī)定數(shù)據(jù)配置以JSON文件的形式提供),系統(tǒng)會(huì)根據(jù)組件的數(shù)據(jù)規(guī)范校驗(yàn)上傳的數(shù)據(jù)配置,如果校驗(yàn)通過則會(huì)展示上傳數(shù)據(jù)與線上數(shù)據(jù)的差別,上傳者可進(jìn)行預(yù)覽操作;如果校驗(yàn)未通過,則提示未通過原因及具體的不規(guī)范數(shù)據(jù),上傳者不可進(jìn)行后續(xù)的預(yù)覽操作,需重新上傳數(shù)據(jù)配置,直到校驗(yàn)通過。

組件及頁面預(yù)覽

此部分功能的核心實(shí)現(xiàn)在SSR Service 服務(wù)端渲染組件中(上文中有詳細(xì)介紹,這里不贅述),主要分為以下幾個(gè)步驟完成:

  • 應(yīng)用的組件渲染函數(shù)在接收到符合組件數(shù)據(jù)規(guī)范的配置數(shù)據(jù)后,將數(shù)據(jù)通過Props傳給組件,進(jìn)而render出當(dāng)前組件的HTML。
  • 從Redis中取出其他模塊的HTML 與當(dāng)前組件HTML拼接在一起,為了保證預(yù)覽的可靠性(減少其他模塊出錯(cuò)時(shí)對當(dāng)前組件的影響),其他模塊均使用生產(chǎn)態(tài)的HTML進(jìn)行拼接。為什么一定要將其他模塊的HTML拼接在一起預(yù)覽呢?為了測試配置數(shù)據(jù)發(fā)布之后對其他組件模塊的影響,若有影響則不能發(fā)布,從而保證線上頁面的安全性。

七、總結(jié)

本文通過攜程新版首頁項(xiàng)目系統(tǒng)的介紹了其整體架構(gòu)設(shè)計(jì),組件開發(fā),數(shù)據(jù)配置的整個(gè)流程及實(shí)現(xiàn)原理,是對島嶼式架構(gòu)的一次實(shí)踐。希望能對大家今后跨團(tuán)隊(duì)組件式開發(fā)的項(xiàng)目有所收獲。

責(zé)任編輯:張燕妮 來源: 攜程技術(shù)
相關(guān)推薦

2023-07-07 12:26:39

攜程開發(fā)

2023-06-06 16:01:00

Web優(yōu)化

2022-05-19 17:50:31

bookie集群延遲消息存儲(chǔ)服務(wù)

2022-08-06 08:23:47

云計(jì)算公有云廠商成本

2022-07-15 12:58:02

鴻蒙攜程華為

2022-05-13 09:27:55

Widget機(jī)票業(yè)務(wù)App

2022-03-30 18:39:51

TiDBHTAPCDP

2022-08-20 07:46:03

Dynamo攜程數(shù)據(jù)庫

2017-10-09 09:12:35

攜程運(yùn)維架構(gòu)

2016-12-15 21:41:15

大數(shù)據(jù)

2022-08-12 08:34:32

攜程數(shù)據(jù)庫上云

2023-02-08 16:34:05

數(shù)據(jù)庫工具

2022-07-08 09:38:27

攜程酒店Flutter技術(shù)跨平臺(tái)整合

2022-07-15 09:20:17

性能優(yōu)化方案

2024-04-26 09:38:36

2022-06-17 10:44:49

實(shí)體鏈接系統(tǒng)旅游AI知識(shí)圖譜攜程

2024-07-05 15:05:00

2022-08-11 22:03:59

Astro孤島架構(gòu)

2022-05-27 09:52:36

攜程TS運(yùn)營AI

2023-08-18 10:49:14

開發(fā)攜程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

亚洲精品一级片| 国产第一页精品| 亚洲少妇视频| 国产欧美日韩精品在线| 91久久精品国产91久久性色| 欧美成人国产精品高潮| 欧美重口另类| 7777精品伊人久久久大香线蕉经典版下载 | 成人成人成人在线视频| 日本a级片电影一区二区| 欧美自拍偷拍网| 成人av激情人伦小说| 色又黄又爽网站www久久| 手机看片日韩国产| 无码国产精品一区二区色情男同 | 在线观看免费av网址| 国产羞羞视频在线播放| 久久久99免费| 99www免费人成精品| 精品久久久久久久久久久国产字幕| 久久资源中文字幕| 日韩经典第一页| 污网站在线免费| videos性欧美另类高清| 亚洲精品大片www| 日本不卡二区| 天天综合网在线观看| 韩日av一区二区| 人体精品一二三区| 国产第100页| 国产精品传媒精东影业在线| 亚洲人成在线观看| 亚洲男女在线观看| 日韩一二三区| 7777女厕盗摄久久久| jizz欧美激情18| 日本在线影院| 午夜电影网亚洲视频| 亚洲av首页在线| 免费网站成人| 国产精品国产成人国产三级| 久草一区二区| 亚洲av成人精品一区二区三区在线播放 | 秋霞午夜鲁丝一区二区| 国产亚洲精彩久久| 色噜噜狠狠成人中文综合 | 中文字幕乱码av| 精品国产一区二区三区| 精品无人国产偷自产在线| 特级特黄刘亦菲aaa级| 国色天香久久精品国产一区| 欧美人狂配大交3d怪物一区| jizz欧美性11| 成人黄色免费网站| 欧美三级韩国三级日本一级| 日韩手机在线观看视频| 国产综合色区在线观看| 色琪琪一区二区三区亚洲区| 激情五月开心婷婷| 日韩高清中文字幕一区二区| 色八戒一区二区三区| 欧美少妇性生活视频| 免费电影日韩网站| 91久久国产最好的精华液| 国产一区亚洲二区三区| 欧美三区四区| 欧美三级电影一区| 亚洲天堂av一区二区| av日韩一区| 日韩一区二区精品| 娇妻高潮浓精白浆xxⅹ| 麻豆一区二区麻豆免费观看| 亚洲人成电影在线| 国产午夜精品久久久久久久久| 成人激情电影在线| 日日狠狠久久偷偷四色综合免费| 老司机成人免费视频| 欧美影院一区| 97色在线视频观看| 天天干,天天干| 精品亚洲aⅴ乱码一区二区三区| 95av在线视频| 色wwwwww| 国产精品色一区二区三区| 自拍偷拍99| av毛片午夜不卡高**水| 日本黄色一区二区| 国产高清av片| 日韩影视高清在线观看| 在线观看日韩视频| 免看一级a毛片一片成人不卡| 狠狠爱www人成狠狠爱综合网| 热草久综合在线| 国产精品久久久久久久久久久久久久久久久久| 国产伦理精品不卡| 欧美另类网站| 中文字幕免费高清电视剧网站在线观看| 亚洲3atv精品一区二区三区| 亚洲色精品三区二区一区| 国产精品亚洲欧美一级在线| 日韩大片在线观看视频| 伊人久久久久久久久久久久久久| 亚洲高清激情| 国产日韩欧美视频在线| 免费激情视频网站| 国产精品狼人久久影院观看方式| 黄色成人在线免费观看| 高清成人在线| 精品成人佐山爱一区二区| 99久久99久久精品免费| 亚洲青涩在线| 成人免费在线视频网址| 人成免费电影一二三区在线观看| 亚洲人精品午夜| 欧美一级片中文字幕| 免费观看在线一区二区三区| 亚洲一区二区精品| 国产成人自拍视频在线| 激情图区综合网| 日韩和欧美的一区二区| 不卡视频观看| 日韩精品专区在线影院重磅| 黄大色黄女片18免费| 在线视频免费在线观看一区二区| 成人免费视频网址| 福利在线播放| 91精品福利视频| 久久精品女同亚洲女同13| 亚洲综合中文| 国产欧美久久一区二区| 黄色在线免费观看大全| 精品久久久久久久久久| 日韩女优在线视频| 国产精品久久久久久麻豆一区软件| 日本不卡免费高清视频| 亚洲欧美综合一区二区| 亚洲网友自拍偷拍| 美女又黄又免费的视频| 91精品国产乱码久久久久久久| 国产精品久久久久久久久久久久久久 | 中文字幕精品三级久久久| 国产suv精品一区二区883| 正在播放久久| 99国内精品久久久久| 日韩在线观看网站| 最好看的日本字幕mv视频大全| 久久女同性恋中文字幕| 国产黄色一级网站| 日韩mv欧美mv国产网站| 欧美一级黑人aaaaaaa做受| 色综合视频在线| 欧美日韩激情网| asian性开放少妇pics| 亚洲欧美激情诱惑| 久久久久久久久久久一区| 欧美三级网站| 亚洲天堂男人天堂女人天堂| 这里只有久久精品视频| 国产精品麻豆一区二区| 日本中文字幕观看| 欧美福利电影在线观看| 国产成人看片| 在线最新版中文在线| 亚洲精品视频网上网址在线观看 | 欧美精品乱码久久久久久| 日本二区三区视频| 国产一区二区三区四区五区入口| 特级黄色录像片| 亚洲91网站| 亚洲2020天天堂在线观看| 无码精品人妻一区二区| 日本电影亚洲天堂一区| 欧日韩不卡视频| 国产麻豆视频一区二区| 青青青免费在线| 精品日韩一区| 亚洲最大av网| 午夜激情在线播放| 色偷偷9999www| 亚洲精品一区二区三区区别| 粉嫩老牛aⅴ一区二区三区| www.黄色在线| 国产激情一区二区三区四区 | 一区二区三区四区视频在线观看 | 午夜国产福利一区二区| 成人黄色大片在线观看 | 色诱女教师一区二区三区| 国产美女www爽爽爽视频| 亚洲午夜免费视频| 亚洲黄色小说视频| 国产精品一区免费在线观看| 日本免费黄视频| 国产精品99一区二区三| 国产精品美女黄网| 精品国产欧美日韩一区二区三区| 欧美黑人性视频| 国产一二在线观看| 欧美哺乳videos| 中国一级片黄色一级片黄| 一区二区三区成人| 成年人网站免费在线观看| 韩国精品免费视频| 欧美日韩亚洲第一| 欧美一区高清| 亚洲aⅴ天堂av在线电影软件| 国产伦精品一区二区三区在线播放| 日本亚洲欧洲色α| 性欧美ⅴideo另类hd| 一区二区三区视频在线| 色噜噜一区二区三区| 欧美一区二区三区小说| www.国产毛片| 午夜久久久久久久久| 肉色超薄丝袜脚交69xx图片| 久久久精品欧美丰满| 秘密基地免费观看完整版中文 | 3p视频在线观看| 日韩成人av在线| 性中国xxx极品hd| 欧美日韩黄色一区二区| 日本一级一片免费视频| 亚洲精品伦理在线| 亚洲怡红院在线观看| 久久久99精品久久| 污片免费在线观看| 国产91露脸合集magnet| 国产乱女淫av麻豆国产| 日日摸夜夜添夜夜添国产精品| 我的公把我弄高潮了视频| 欧美91大片| 一本色道久久综合亚洲二区三区| 欧美五码在线| 国产美女在线精品免费观看| 精品久久久久久久久久岛国gif| 国产精品中文字幕在线| 成人在线视频播放| 国产91精品网站| 在线观看网站免费入口在线观看国内| 欧美国产在线电影| 怡红院红怡院欧美aⅴ怡春院| 精品国产一区二区在线| 永久av在线| 色偷偷av亚洲男人的天堂| 91成人高清| 日韩一区二区久久久| 91亚洲欧美| 丝袜情趣国产精品| 黄色网址在线免费| 久久久精品一区二区| 国产精品剧情| 美女扒开尿口让男人操亚洲视频网站| 国产最新在线| 欧美成人免费观看| 毛片大全在线观看| 久久久久中文字幕2018| 多野结衣av一区| 欧美在线不卡区| 欧美free嫩15| 国产一区二区视频在线观看| **国产精品| 99影视tv| 久久国产精品免费精品3p| 久久精品国产精品国产精品污| 免费久久久久久久久| 日韩三级电影| 91精品国产调教在线观看| 台湾无码一区二区| 亚洲神马久久| 超碰av在线免费观看| 精品一区二区久久久| 永久av免费在线观看| av一区二区久久| 这里只有久久精品| 国产精品久久久久久久久久久免费看| 男人的午夜天堂| 亚洲成人激情自拍| 国产午夜精品久久久久| 欧美日韩色综合| 亚洲AV无码一区二区三区性| 日韩精品极品在线观看播放免费视频| 国产在线观看免费| 久久不射电影网| 岛国av免费在线观看| 国产成人短视频| 成人短视频软件网站大全app| 国产精品免费在线播放| 精品久久久久久久| 亚洲色欲久久久综合网东京热| 日韩专区在线视频| 99中文字幕在线| 久久久久国产成人精品亚洲午夜| 翔田千里88av中文字幕| 欧美日韩加勒比精品一区| 亚洲天堂自拍偷拍| 亚洲激情视频在线| www亚洲人| 97在线观看免费| 另类一区二区| 噜噜噜噜噜久久久久久91| 亚洲视频电影在线| 妞干网在线免费视频| 国产一区二区电影| 亚洲黄色小说视频| 亚洲成人av在线电影| 一级aaaa毛片| 亚洲人成网站777色婷婷| 大香伊人中文字幕精品| 国产欧美精品xxxx另类| 日韩极品在线| 成人一级生活片| 久久99国产精品麻豆| 精品人妻一区二区三区日产乱码卜| 亚洲免费观看高清完整版在线| 草莓视频18免费观看| 亚洲成色777777在线观看影院| 黄色在线论坛| 国产精品成人av性教育| 欧美理论电影在线精品| 男女裸体影院高潮| 另类小说欧美激情| 国产真实乱人偷精品人妻| 亚洲不卡av一区二区三区| 国产chinasex对白videos麻豆| 自拍偷拍免费精品| 欧美一区国产| 欧美伦理一区二区| 亚洲免费在线| 大尺度做爰床戏呻吟舒畅| 亚洲精品久久嫩草网站秘色| 一级黄色片在线播放| 尤物tv国产一区| 97久久香蕉国产线看观看| 久久伊人资源站| 国产精品尤物| 日本黄色特级片| 狠狠躁夜夜躁久久躁别揉| 日本美女一级片| 久久久久久av| 91亚洲无吗| 久草视频这里只有精品| 国产不卡一区视频| 青娱乐免费在线视频| 欧美一级理论片| 日韩激情美女| yy111111少妇影院日韩夜片| 欧美1区2区3区| 欧美极品jizzhd欧美仙踪林| 亚洲资源中文字幕| 蜜桃av噜噜一区二区三区麻豆| 欧美日本亚洲视频| 国产精品17p| 18禁免费观看网站| 91免费国产在线| 中文字幕在线天堂| 最近2019年中文视频免费在线观看| 国产一区二区主播在线| 一区二区免费在线视频| 国产一区二区三区美女| 久久久久久久福利| 亚洲国产精品系列| 日韩影片中文字幕| 四虎影院一区二区三区 | 韩国av网站在线| 91精品网站| 国产精品亚洲欧美| 久久久久久久久福利| 欧美美女直播网站| 亚洲区欧洲区| 精品欧美一区二区在线观看视频| 欧美亚洲视频| 国产中文字幕久久| 日韩欧美你懂的| 欧美a级在线观看| 色一情一乱一伦一区二区三区丨| 精品一区二区三区日韩| 欧美激情一区二区视频| 亚洲精品美女久久| 日本综合视频| av在线免费观看国产| 26uuu国产日韩综合| 一级爱爱免费视频| 久久久久久久久久av| 自拍视频一区| 在线a免费观看| 黑人欧美xxxx| 国产色在线观看| 狠狠干一区二区| 久色婷婷小香蕉久久| 国产一级片免费| 一本一本久久a久久精品牛牛影视| vam成人资源在线观看| 97国产在线播放| 日韩理论片在线| 飘雪影院手机免费高清版在线观看| 成人午夜激情网| 亚洲在线免费| 农村黄色一级片| 正在播放欧美视频| 精品在线网站观看| 中文字幕久久av|