成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

實(shí)施微前端的六種方式,值得你看!

開發(fā) 前端
微前端架構(gòu)是一種類似于微服務(wù)的架構(gòu),它將微服務(wù)的理念應(yīng)用于瀏覽器端,即將 Web 應(yīng)用由單一的單體應(yīng)用轉(zhuǎn)變?yōu)槎鄠€(gè)小型前端應(yīng)用聚合為一的應(yīng)用。

微前端架構(gòu)是一種類似于微服務(wù)的架構(gòu),它將微服務(wù)的理念應(yīng)用于瀏覽器端,即將 Web 應(yīng)用由單一的單體應(yīng)用轉(zhuǎn)變?yōu)槎鄠€(gè)小型前端應(yīng)用聚合為一的應(yīng)用。

由此帶來的變化是,這些前端應(yīng)用可以獨(dú)立運(yùn)行、獨(dú)立開發(fā)、獨(dú)立部署。以及,它們應(yīng)該可以在共享組件的同時(shí)進(jìn)行并行開發(fā)——這些組件可以通過 NPM 或者 Git Tag、Git Submodule 來管理。

注意:這里的前端應(yīng)用指的是前后端分離的單應(yīng)用頁(yè)面,在這基礎(chǔ)才談?wù)撐⑶岸瞬庞幸饬x。

結(jié)合我最近半年在微前端方面的實(shí)踐和研究來看,微前端架構(gòu)一般可以由以下幾種方式進(jìn)行:

  1. 使用 HTTP 服務(wù)器的路由來重定向多個(gè)應(yīng)用
  2. 在不同的框架之上設(shè)計(jì)通訊、加載機(jī)制,諸如 Mooa 和 Single-SPA
  3. 通過組合多個(gè)獨(dú)立應(yīng)用、組件來構(gòu)建一個(gè)單體應(yīng)用
  4. iFrame。使用 iFrame 及自定義消息傳遞機(jī)制
  5. 使用純 Web Components 構(gòu)建應(yīng)用
  6. 結(jié)合 Web Components 構(gòu)建

不同的方式適用于不同的使用場(chǎng)景,當(dāng)然也可以組合一起使用。那么,就讓我們來一一了解一下,為以后的架構(gòu)演進(jìn)做一些技術(shù)鋪墊。

基礎(chǔ)鋪墊:應(yīng)用分發(fā)路由 -> 路由分發(fā)應(yīng)用

在一個(gè)單體前端、單體后端應(yīng)用中,有一個(gè)典型的特征,即路由是由框架來分發(fā)的,框架將路由指定到對(duì)應(yīng)的組件或者內(nèi)部服務(wù)中。微服務(wù)在這個(gè)過程中做的事情是,將調(diào)用由函數(shù)調(diào)用變成了遠(yuǎn)程調(diào)用,諸如遠(yuǎn)程 HTTP 調(diào)用。而微前端呢,也是類似的,它是將應(yīng)用內(nèi)的組件調(diào)用變成了更細(xì)粒度的應(yīng)用間組件調(diào)用,即原先我們只是將路由分發(fā)到應(yīng)用的組件執(zhí)行,現(xiàn)在則需要根據(jù)路由來找到對(duì)應(yīng)的應(yīng)用,再由應(yīng)用分發(fā)到對(duì)應(yīng)的組件上。

后端:函數(shù)調(diào)用 -> 遠(yuǎn)程調(diào)用

在大多數(shù)的 CRUD 類型的 Web 應(yīng)用中,也都存在一些極為相似的模式,即:首頁(yè) -> 列表 -> 詳情:

  • 首頁(yè),用于面向用戶展示特定的數(shù)據(jù)或頁(yè)面。這些數(shù)據(jù)通常是有限個(gè)數(shù)的,并且是多種模型的。
  • 列表,即數(shù)據(jù)模型的聚合,其典型特點(diǎn)是某一類數(shù)據(jù)的集合,可以看到盡可能多的數(shù)據(jù)概要(如 Google 只返回 100 頁(yè)),典型見 Google、淘寶、京東的搜索結(jié)果頁(yè)。
  • 詳情,展示一個(gè)數(shù)據(jù)的盡可能多的內(nèi)容。

如下是一個(gè) Spring 框架,用于返回首頁(yè)的示例:

 

  1. @RequestMapping(value="/" 
  2. public ModelAndView homePage(){  
  3.    return new ModelAndView("/WEB-INF/jsp/index.jsp");  

 

對(duì)于某個(gè)詳情頁(yè)面來說,它可能是這樣的:

 

  1. @RequestMapping(value="/detail/{detailId}" 
  2. public ModelAndView detail(HttpServletRequest request, ModelMap model){  
  3.    ....  
  4.    return new ModelAndView("/WEB-INF/jsp/detail.jsp""detail", detail);  

 

那么,在微服務(wù)的情況下,它則會(huì)變成這樣子:

 

  1. @RequestMapping("/name" 
  2. public String name(){  
  3.     String name = restTemplate.getForObject("http://account/name", String.class);  
  4.     return Name" + name 

 

而后端在這個(gè)過程中,多了一個(gè)服務(wù)發(fā)現(xiàn)的服務(wù),來管理不同微服務(wù)的關(guān)系。

前端:組件調(diào)用 -> 應(yīng)用調(diào)用

在形式上來說,單體前端框架的路由和單體后端應(yīng)用,并沒有太大的區(qū)別:依據(jù)不同的路由,來返回不同頁(yè)面的模板。

 

  1. const appRoutes: Routes = [  
  2.   { path: 'index', component: IndexComponent },  
  3.   { path: 'detail/:id', component: DetailComponent },  
  4. ]; 

 

而當(dāng)我們將之微服務(wù)化后,則可能變成應(yīng)用 A 的路由:

 

  1. const appRoutes: Routes = [  
  2.   { path: 'index', component: IndexComponent },  
  3. ]; 

 

外加之應(yīng)用 B 的路由:

 

  1. const appRoutes: Routes = [  
  2.   { path: 'detail/:id', component: DetailComponent },  
  3. ]; 

 

而問題的關(guān)鍵就在于:怎么將路由分發(fā)到這些不同的應(yīng)用中去。與此同時(shí),還要負(fù)責(zé)管理不同的前端應(yīng)用。

路由分發(fā)式微前端

路由分發(fā)式微前端,即通過路由將不同的業(yè)務(wù)分發(fā)到不同的、獨(dú)立前端應(yīng)用上。其通常可以通過 HTTP 服務(wù)器的反向代理來實(shí)現(xiàn),又或者是應(yīng)用框架自帶的路由來解決。

就當(dāng)前而言,通過路由分發(fā)式的微前端架構(gòu)應(yīng)該是采用最多、最易采用的 “微前端” 方案。但是這種方式看上去更像是多個(gè)前端應(yīng)用的聚合,即我們只是將這些不同的前端應(yīng)用拼湊到一起,使他們看起來像是一個(gè)完整的整體。但是它們并不是,每次用戶從 A 應(yīng)用到 B 應(yīng)用的時(shí)候,往往需要刷新一下頁(yè)面。

在幾年前的一個(gè)項(xiàng)目里,我們當(dāng)時(shí)正在進(jìn)行遺留系統(tǒng)重寫。我們制定了一個(gè)遷移計(jì)劃:

  1. 首先,使用靜態(tài)網(wǎng)站生成動(dòng)態(tài)生成首頁(yè)
  2. 其次,使用 React 計(jì)劃棧重構(gòu)詳情頁(yè)
  3. ***,替換搜索結(jié)果頁(yè)

整個(gè)系統(tǒng)并不是一次性遷移過去,而是一步步往下進(jìn)行。因此在完成不同的步驟時(shí),我們就需要上線這個(gè)功能,于是就需要使用 Nginx 來進(jìn)行路由分發(fā)。

如下是一個(gè)基于路由分發(fā)的 Nginx 配置示例:

 

  1. http {  
  2.   server {  
  3.     listen       80;  
  4.     server_name  www.phodal.com;  
  5.     location /api/ {  
  6.       proxy_pass http://http://172.31.25.15:8000/api;  
  7.     }  
  8.     location /web/admin {  
  9.       proxy_pass http://172.31.25.29/web/admin;  
  10.     }  
  11.     location /web/notifications {  
  12.       proxy_pass http://172.31.25.27/web/notifications;  
  13.     }  
  14.     location / {  
  15.       proxy_pass /;  
  16.     } 
  17.    }  

 

在這個(gè)示例里,不同的頁(yè)面的請(qǐng)求被分發(fā)到不同的服務(wù)器上。

隨后,我們?cè)趧e的項(xiàng)目上也使用了類似的方式,其主要原因是:跨團(tuán)隊(duì)的協(xié)作。當(dāng)團(tuán)隊(duì)達(dá)到一定規(guī)模的時(shí)候,我們不得不面對(duì)這個(gè)問題。除此,還有 Angluar 跳崖式升級(jí)的問題。于是,在這種情況下,用戶前臺(tái)使用 Angular 重寫,后臺(tái)繼續(xù)使用 Angular.js 等保持再有的技術(shù)棧。在不同的場(chǎng)景下,都有一些相似的技術(shù)決策。

因此在這種情況下,它適用于以下場(chǎng)景:

  • 不同技術(shù)棧之間差異比較大,難以兼容、遷移、改造
  • 項(xiàng)目不想花費(fèi)大量的時(shí)間在這個(gè)系統(tǒng)的改造上
  • 現(xiàn)有的系統(tǒng)在未來將會(huì)被取代
  • 系統(tǒng)功能已經(jīng)很完善,基本不會(huì)有新需求

而在滿足上面場(chǎng)景的情況下,如果為了更好的用戶體驗(yàn),還可以采用 iframe 的方式來解決。

使用 iFrame 創(chuàng)建容器

iFrame 作為一個(gè)非常古老的,人人都覺得普通的技術(shù),卻一直很管用。

HTML 內(nèi)聯(lián)框架元素 <iframe> 表示嵌套的正在瀏覽的上下文,能有效地將另一個(gè) HTML 頁(yè)面嵌入到當(dāng)前頁(yè)面中。

iframe 可以創(chuàng)建一個(gè)全新的獨(dú)立的宿主環(huán)境,這意味著我們的前端應(yīng)用之間可以相互獨(dú)立運(yùn)行。采用 iframe 有幾個(gè)重要的前提:

  • 網(wǎng)站不需要 SEO 支持
  • 擁有相應(yīng)的應(yīng)用管理機(jī)制。

如果我們做的是一個(gè)應(yīng)用平臺(tái),會(huì)在我們的系統(tǒng)中集成第三方系統(tǒng),或者多個(gè)不同部門團(tuán)隊(duì)下的系統(tǒng),顯然這是一個(gè)不錯(cuò)的方案。一些典型的場(chǎng)景,如傳統(tǒng)的 Desktop 應(yīng)用遷移到 Web 應(yīng)用:

 

如果這一類應(yīng)用過于復(fù)雜,那么它必然是要進(jìn)行微服務(wù)化的拆分。因此,在采用 iframe 的時(shí)候,我們需要做這么兩件事:

  • 設(shè)計(jì)管理應(yīng)用機(jī)制
  • 設(shè)計(jì)應(yīng)用通訊機(jī)制

加載機(jī)制。在什么情況下,我們會(huì)去加載、卸載這些應(yīng)用;在這個(gè)過程中,采用怎樣的動(dòng)畫過渡,讓用戶看起來更加自然。

通訊機(jī)制。直接在每個(gè)應(yīng)用中創(chuàng)建 postMessage 事件并監(jiān)聽,并不是一個(gè)友好的事情。其本身對(duì)于應(yīng)用的侵入性太強(qiáng),因此通過 iframeEl.contentWindow 去獲取 iFrame 元素的 Window 對(duì)象是一個(gè)更簡(jiǎn)化的做法。隨后,就需要定義一套通訊規(guī)范:事件名采用什么格式、什么時(shí)候開始監(jiān)聽事件等等。

有興趣的讀者,可以看看筆者之前寫的微前端框架:Mooa。

不管怎樣,iframe 對(duì)于我們今年的 KPI 怕是帶不來一絲的好處,那么我們就去造個(gè)輪子吧。

自制框架兼容應(yīng)用

不論是基于 Web Components 的 Angular,或者是 VirtualDOM 的 React 等,現(xiàn)有的前端框架都離不開基本的 HTML 元素 DOM。

那么,我們只需要:

  1. 在頁(yè)面合適的地方引入或者創(chuàng)建 DOM
  2. 用戶操作時(shí),加載對(duì)應(yīng)的應(yīng)用(觸發(fā)應(yīng)用的啟動(dòng)),并能卸載應(yīng)用。

***個(gè)問題,創(chuàng)建 DOM 是一個(gè)容易解決的問題。而第二個(gè)問題,則一點(diǎn)兒不容易,特別是移除 DOM 和相應(yīng)應(yīng)用的監(jiān)聽。當(dāng)我們擁有一個(gè)不同的技術(shù)棧時(shí),我們就需要有針對(duì)性設(shè)計(jì)出一套這樣的邏輯。

盡管 Single-SPA 已經(jīng)擁有了大部分框架(如 React、Angular、Vue 等框架)的啟動(dòng)和卸載處理,但是它仍然不是適合于生產(chǎn)用途。當(dāng)我基于 Single-SPA 為 Angular 框架設(shè)計(jì)一個(gè)微前端架構(gòu)的應(yīng)用時(shí),我***選擇重寫一個(gè)自己的框架,即 Mooa。

雖然,這種方式的上手難度相對(duì)比較高,但是后期訂制及可維護(hù)性比較方便。在不考慮每次加載應(yīng)用帶來的用戶體驗(yàn)問題,其唯一存在的風(fēng)險(xiǎn)可能是:第三方庫(kù)不兼容。

但是,不論怎樣,與 iFrame 相比,其在技術(shù)上更具有可吹牛逼性,更有看點(diǎn)。同樣的,與 iframe 類似,我們?nèi)匀幻鎸?duì)著一系列的不大不小的問題:

  • 需要設(shè)計(jì)一套管理應(yīng)用的機(jī)制。
  • 對(duì)于流量大的 toC 應(yīng)用來說,會(huì)在***加載的時(shí)候,會(huì)多出大量的請(qǐng)求

而我們即又要拆分應(yīng)用,又想 blabla……,我們還能怎么做?

組合式集成:將應(yīng)用微件化

組合式集成,即通過軟件工程的方式在構(gòu)建前、構(gòu)建時(shí)、構(gòu)建后等步驟中,對(duì)應(yīng)用進(jìn)行一步的拆分,并重新組合。

從這種定義上來看,它可能算不上并不是一種微前端——它可以滿足了微前端的三個(gè)要素,即:獨(dú)立運(yùn)行、獨(dú)立開發(fā)、獨(dú)立部署。但是,配合上前端框架的組件 Lazyload 功能——即在需要的時(shí)候,才加載對(duì)應(yīng)的業(yè)務(wù)組件或應(yīng)用,它看上去就是一個(gè)微前端應(yīng)用。

與此同時(shí),由于所有的依賴、Pollyfill 已經(jīng)盡可能地在***加載了,CSS 樣式也不需要重復(fù)加載。

常見的方式有:

  • 獨(dú)立構(gòu)建組件和應(yīng)用,生成 chunk 文件,構(gòu)建后再歸類生成的 chunk 文件。(這種方式更類似于微服務(wù),但是成本更高)
  • 開發(fā)時(shí)獨(dú)立開發(fā)組件或應(yīng)用,集成時(shí)合并組件和應(yīng)用,***生成單體的應(yīng)用。
  • 在運(yùn)行時(shí),加載應(yīng)用的 Runtime,隨后加載對(duì)應(yīng)的應(yīng)用代碼和模板。

應(yīng)用間的關(guān)系如下圖所示(其忽略圖中的 “前端微服務(wù)化”):

 

這種方式看上去相當(dāng)?shù)睦硐耄茨軡M足多個(gè)團(tuán)隊(duì)并行開發(fā),又能構(gòu)建出適合的交付物。

但是,首先它有一個(gè)嚴(yán)重的限制:必須使用同一個(gè)框架。對(duì)于多數(shù)團(tuán)隊(duì)來說,這并不是問題。采用微服務(wù)的團(tuán)隊(duì)里,也不會(huì)因?yàn)槲⒎?wù)這一個(gè)前端,來使用不同的語言和技術(shù)來開發(fā)。當(dāng)然了,如果要使用別的框架,也不是問題,我們只需要結(jié)合上一步中的自制框架兼容應(yīng)用就可以滿足我們的需求。

其次,采用這種方式還有一個(gè)限制,那就是:規(guī)范!規(guī)范!規(guī)范!。在采用這種方案時(shí),我們需要:

  • 統(tǒng)一依賴。統(tǒng)一這些依賴的版本,引入新的依賴時(shí)都需要一一加入。
  • 規(guī)范應(yīng)用的組件及路由。避免不同的應(yīng)用之間,因?yàn)檫@些組件名稱發(fā)生沖突。
  • 構(gòu)建復(fù)雜。在有些方案里,我們需要修改構(gòu)建系統(tǒng),有些方案里則需要復(fù)雜的架構(gòu)腳本。
  • 共享通用代碼。這顯然是一個(gè)要經(jīng)常面對(duì)的問題。
  • 制定代碼規(guī)范。

因此,這種方式看起來更像是一個(gè)軟件工程問題。

現(xiàn)在,我們已經(jīng)有了四種方案,每個(gè)方案都有自己的利弊。顯然,結(jié)合起來會(huì)是一種更理想的做法。

考慮到現(xiàn)有及常用的技術(shù)的局限性問題,讓我們?cè)俅螌⒛抗夥诺瞄L(zhǎng)遠(yuǎn)一些。

純 Web Components 技術(shù)構(gòu)建

在學(xué)習(xí) Web Components 開發(fā)微前端架構(gòu)的過程中,我嘗試去寫了我自己的 Web Components 框架:oan。在添加了一些基本的 Web 前端框架的功能之后,我發(fā)現(xiàn)這項(xiàng)技術(shù)特別適合于作為微前端的基石。

Web Components 是一套不同的技術(shù),允許您創(chuàng)建可重用的定制元素(它們的功能封裝在您的代碼之外)并且在您的 Web 應(yīng)用中使用它們。

它主要由四項(xiàng)技術(shù)組件:

  • Custom elements,允許開發(fā)者創(chuàng)建自定義的元素,諸如 <today-news></today-news>。
  • Shadow DOM,即影子 DOM,通常是將 Shadow DOM 附加到主文檔 DOM 中,并可以控制其關(guān)聯(lián)的功能。而這個(gè) Shadow DOM 則是不能直接用其它主文檔 DOM 來控制的。
  • HTML templates,即 <template> 和 <slot> 元素,用于編寫不在頁(yè)面中顯示的標(biāo)記模板。
  • HTML Imports,用于引入自定義組件。

每個(gè)組件由 link 標(biāo)簽引入:

 

  1. <link rel="import" href="components/di-li.html" 
  2. <link rel="import" href="components/d-header.html"

 

隨后,在各自的 HTML 文件里,創(chuàng)建相應(yīng)的組件元素,編寫相應(yīng)的組件邏輯。一個(gè)典型的 Web Components 應(yīng)用架構(gòu)如下圖所示:

 

可以看到這邊方式與我們上面使用 iframe 的方式很相似,組件擁有自己獨(dú)立的 Scripts 和 Styles,以及對(duì)應(yīng)的用于單獨(dú)部署組件的域名。然而它并沒有想象中的那么美好,要直接使用純 Web Components 來構(gòu)建前端應(yīng)用的難度有:

  • 重寫現(xiàn)有的前端應(yīng)用。是的,現(xiàn)在我們需要完成使用 Web Components 來完成整個(gè)系統(tǒng)的功能。
  • 上下游生態(tài)系統(tǒng)不完善。缺乏相應(yīng)的一些第三方控件支持,這也是為什么 jQuery 相當(dāng)流行的原因。
  • 系統(tǒng)架構(gòu)復(fù)雜。當(dāng)應(yīng)用被拆分為一個(gè)又一個(gè)的組件時(shí),組件間的通訊就成了一個(gè)特別大的麻煩。

Web Components 中的 ShadowDOM 更像是新一代的前端 DOM 容器。而遺憾的是并不是所有的瀏覽器,都可以完全支持 Web Components。

結(jié)合 Web Components 構(gòu)建

Web Components 離現(xiàn)在的我們太遠(yuǎn),可是結(jié)合 Web Components 來構(gòu)建前端應(yīng)用,則更是一種面向未來演進(jìn)的架構(gòu)。或者說在未來的時(shí)候,我們可以開始采用這種方式來構(gòu)建我們的應(yīng)用。好在,已經(jīng)有框架在打造這種可能性。

就當(dāng)前而言,有兩種方式可以結(jié)合 Web Components 來構(gòu)建微前端應(yīng)用:

  • 使用 Web Components 構(gòu)建獨(dú)立于框架的組件,隨后在對(duì)應(yīng)的框架中引入這些組件
  • 在 Web Components 中引入現(xiàn)有的框架,類似于 iframe 的形式

前者是一種組件式的方式,或者則像是在遷移未來的 “遺留系統(tǒng)” 到未來的架構(gòu)上。

在 Web Components 中集成現(xiàn)有框架

現(xiàn)有的 Web 框架已經(jīng)有一些可以支持 Web Components 的形式,諸如 Angular 支持的 createCustomElement,就可以實(shí)現(xiàn)一個(gè) Web Components 形式的組件:

 

  1. platformBrowser()  
  2.     .bootstrapModuleFactory(MyPopupModuleNgFactory)  
  3.         .then(({injector}) => {  
  4.             const MyPopupElement = createCustomElement(MyPopup, {injector});  
  5.             customElements.define(‘my-popup’, MyPopupElement);  
  6. }); 

 

在未來,將有更多的框架可以使用類似這樣的形式,集成到 Web Components 應(yīng)用中。

集成在現(xiàn)有框架中的 Web Components

另外一種方式,則是類似于 Stencil 的形式,將組件直接構(gòu)建成 Web Components 形式的組件,隨后在對(duì)應(yīng)的諸如,如 React 或者 Angular 中直接引用。

如下是一個(gè)在 React 中引用 Stencil 生成的 Web Components 的例子:

 

  1. import React from 'react' 
  2. import ReactDOM from 'react-dom' 
  3. import './index.css' 
  4. import App from './App' 
  5. import registerServiceWorker from './registerServiceWorker' 
  6. import 'test-components/testcomponents' 
  7. ReactDOM.render(<App />, document.getElementById('root'));  
  8. registerServiceWorker(); 

 

在這種情況之下,我們就可以構(gòu)建出獨(dú)立于框架的組件。

同樣的 Stencil 仍然也只是支持最近的一些瀏覽器,比如:Chrome、Safari、Firefox、Edge 和 IE11

復(fù)合型

復(fù)合型,對(duì)就是上面的幾個(gè)類別中,隨便挑幾種組合到一起。

我就不廢話了~~。

結(jié)論

那么,我們應(yīng)該用哪種微前端方案呢?答案見下一篇《微前端快速選型指南》

相關(guān)資料:

責(zé)任編輯:龐桂玉 來源: segmentfault
相關(guān)推薦

2025-01-21 10:04:40

Java并發(fā)阻塞隊(duì)列

2025-02-27 00:00:30

SpringJava方式

2009-02-11 09:46:00

ASON網(wǎng)絡(luò)演進(jìn)

2022-03-28 20:57:31

私有屬性class屬性和方法

2023-10-30 11:53:37

繼承JS父類

2017-06-26 10:35:58

前端JavaScript繼承方式

2021-12-15 23:10:34

JS Debugger 前端開發(fā)

2022-03-23 12:55:50

農(nóng)業(yè)物聯(lián)網(wǎng)

2019-05-16 13:00:18

異步編程JavaScript回調(diào)函數(shù)

2023-04-06 07:02:18

小眾編程語言

2017-07-20 08:47:19

網(wǎng)頁(yè)加載時(shí)間移動(dòng)開發(fā)IT

2023-05-10 13:58:13

服務(wù)限流系統(tǒng)

2021-01-08 10:52:22

物聯(lián)網(wǎng)萬物互聯(lián)IoT,Interne

2022-02-14 10:30:37

Java方式框架

2020-07-31 11:12:39

安全威脅網(wǎng)絡(luò)攻擊網(wǎng)絡(luò)安全

2022-01-14 10:34:50

黑客隱藏蹤跡網(wǎng)絡(luò)安全

2020-04-27 09:00:00

雙因素認(rèn)證身份認(rèn)證生物識(shí)別

2010-09-13 18:02:46

2020-10-14 09:00:00

SAST漏洞攻擊

2021-05-06 08:00:00

人工智能神經(jīng)網(wǎng)絡(luò)深度學(xué)習(xí)
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 欧美日韩成人影院 | 久久久精品 | 精品久久久久久久久久久久 | 韩国精品一区 | 中文字幕一区二区三区日韩精品 | 91久久国产综合久久 | 日韩av在线一区 | 日本精品免费 | 亚洲网站在线播放 | 欧美国产精品 | 91 视频网站 | 欧美在线a | 久热爱 | 国产区一区| 欧美又大粗又爽又黄大片视频 | 免费在线观看一区二区三区 | 日韩精品成人 | 日韩精品免费视频 | 国产精品久久久久久久久免费 | 亚洲午夜av久久乱码 | 91精品久久久久 | 欧美精品在线一区二区三区 | 精品国产91乱码一区二区三区 | 99久久婷婷国产综合精品电影 | 男女视频在线观看免费 | 中文字幕高清一区 | 在线国产精品一区 | 天天av天天好逼 | 日本黄色一级片视频 | 国产网站在线 | 日韩久久久久久久久久久 | 九九激情视频 | 欧美日韩亚洲一区二区 | 精品在线观看一区二区 | 99国产精品久久久久 | 欧美性高潮 | 一级做a爰片性色毛片16 | 日韩五月天 | 国产三区四区 | 羞羞视频在线网站观看 | 久久久久久久久久久久久9999 |