1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        螞蟻前端研發(fā)最佳實(shí)踐

        共 5856字,需瀏覽 12分鐘

         ·

        2019-12-08 23:29

        (給前端大學(xué)加星標(biāo),提升前端技能.

        作者:云謙

        https://github.com/sorrycc/blog/issues/90

        本文是阿里高級(jí)前端技術(shù)專家云謙在 2019.11.15 成都全棧大會(huì)分享的文字稿,介紹了螞蟻前端研發(fā)的最佳實(shí)踐,其中提取了三個(gè)比較重要的點(diǎn),每個(gè)點(diǎn)都是螞蟻實(shí)踐和深入思考后的結(jié)果,希望能對(duì)大家有所啟發(fā),歡迎探討。

        開篇

        e0a59b0bfe5cc6817ccf615fb8ba70a3.webp

        準(zhǔn)備這個(gè)題目時(shí)我 google 了下前端最佳實(shí)踐,排在前面的是講前端代碼規(guī)范,語意、可讀性、編碼規(guī)范、空格還是 Tab 等等,我覺得這是我們第一代的最佳實(shí)踐。

        而現(xiàn)在都 9012 年了,最佳實(shí)踐也經(jīng)歷了很多代的變更,下面是我們?cè)谶@方面的思考和實(shí)踐。

        自我介紹

        a3806d7136335400fc7f05bcfe0ffa10.webp

        目錄

        7319935bcfb808cb2a556a9e9db9e6b9.webp

        為什么要有最佳實(shí)踐?

        5a4b98d92730f762f0d7cdccf8cd10c9.webp

        cb01e2eee11eb976690780a6ee577a90.webp


        不知大家在這些方面是否有疑惑?

        • 前端發(fā)展快,每次發(fā)布 Umi 版本時(shí),除了點(diǎn)贊,還有人求別發(fā),表示實(shí)在學(xué)不動(dòng)了。右邊這張圖是之前的朋友圈看到的,轉(zhuǎn)到公司群里,有共鳴的人不少,說明一定程度反應(yīng)了現(xiàn)在前端社區(qū)的情況。

        • 面對(duì)海量“輪子”,我應(yīng)該學(xué)哪些,不學(xué)哪個(gè)?,我的前端知識(shí)點(diǎn)學(xué)習(xí)列表已經(jīng)是完全學(xué)不完的狀態(tài),比如社區(qū)上光數(shù)據(jù)流方案就有幾百個(gè),其中值得一看的也有四五十個(gè)吧。

        • 然后,大家在創(chuàng)建項(xiàng)目時(shí),是否也有過選擇困難?




        607605a94d459c140e22ec0db857926a.webp


        這里舉一個(gè)具體的例子,

        • 框架

        • 基于 React 的框架

        • 語言

        • CSS 方案

        • 數(shù)據(jù)流

        • 請(qǐng)求庫

        • 等等

        可以發(fā)現(xiàn),每個(gè)點(diǎn)都會(huì)有不少選擇,并且有時(shí)還真的很難選,因?yàn)槊總€(gè)人看待它的角度不同。所以,對(duì)于開發(fā)者來說,真的有點(diǎn)太難了!他只是想完成需求,然后回家睡覺,為啥需要選這么多,就不能給個(gè)默認(rèn)的嗎?

        ad1cfe2e261f968ffe1dc7ee02fd7d16.webp


        然后,

        • 如果每個(gè)項(xiàng)目都要選,我覺得會(huì)很難。當(dāng)然,也有人可能會(huì)覺得是一種樂趣。

        • 而對(duì)于團(tuán)隊(duì)而言,如果每個(gè)項(xiàng)目的選擇還都不一樣,那么團(tuán)隊(duì)的研發(fā)成本和效率都會(huì)是問題。想象一下,如果一個(gè)同學(xué)換個(gè)項(xiàng)目組,需要接觸完全不同的技術(shù)棧。

        所以,對(duì)于團(tuán)隊(duì)而言,保持一致非常重要。

        202e38375d15daf11bdb322b2bc0ad4d.webp

        那么,如何保持一致?不同團(tuán)隊(duì)會(huì)有不同的選擇,通常有這幾類,

        • 文檔

        • 腳手架

        • 框架

        約束能力和迭代能力也是逐步遞增。

        我們最早應(yīng)該是用的文檔。比如做一些代碼約定,用 Tab 還是空格,用兩個(gè)空格還是 4 個(gè)空格,行尾要不要加分號(hào)等等,這一類主要靠開發(fā)者自覺,所以我覺得不太靠譜,這也是為啥后來有 eslint。

        腳手架比文檔好點(diǎn),但也依賴開發(fā)者的自覺性,因?yàn)檫€是可以隨便改。前幾年 React 社區(qū)上有不少做的很好的腳手架,但現(xiàn)在基本上都沒有活躍的了。

        第三種方式是框架,他的約束性可以做的比較強(qiáng)。比如約定用 less,如果開發(fā)者用了 sass,就給他報(bào)個(gè)錯(cuò)。同時(shí)相比其他兩種方式,還有迭代能力。腳手架交給用戶之后是很難更新的,框架則是自己更新后,開發(fā)者的項(xiàng)目自動(dòng)生效。

        當(dāng)然,這三者不是互斥關(guān)系,可以都用嘛。

        9432c395deee89c0542f3a89c07045c4.webp


        然后如何決定用啥方案,用 SASS 還是 LESS,要不要用 TypeScript,甚至目錄用復(fù)數(shù)還是單數(shù)這種極其無聊的事情。

        不同團(tuán)隊(duì)會(huì)有不同的選擇,

        • STAR 數(shù),大家通常會(huì)選 STAR 數(shù)多的,社區(qū)認(rèn)同感很重要,比如 DVA 在螞蟻的推廣就是先從社區(qū)做起的

        • 簡單 vs. 規(guī)范,有人會(huì)選擇概念少而簡單的,有人會(huì)選擇概念多但看起來更規(guī)范的

        • 先入為主,先占坑的往往具有優(yōu)勢(shì)

        • 老板喜歡,?

        老板喜歡其實(shí) “很重要”。有些大家吵很久但決定不了的事,往往會(huì)很自覺地找老板或者德高望重的同學(xué)進(jìn)行拍板,我們也是如此。

        螞蟻前端的選擇

        1a9fc0bfaf46287568d1d2599c0183e9.webp

        e39ad657c9e4938693ed89a9099ec6a8.webp


        我們?cè)诓煌瑫r(shí)期的最佳實(shí)踐是不同的,曾經(jīng)還開發(fā)過 spm,不自量力地試圖挑戰(zhàn) npm + webpack 組合,雖然失敗了,但敢想也是一種勇氣。(做 spm 時(shí),webpack 還沒出來)

        c2ea6b7f6d7980f2a448d267a1fa35dd.webp


        我們有很多方向,然后每個(gè)方向又有很多選擇,圖上是我們目前的選擇。

        從這里可以看到幾點(diǎn),

        • 選擇的內(nèi)容基本上是社區(qū)主流的,不脫離社區(qū)是基本原則

        • 很多子方向都選擇了自研或者正在考慮自研

        為啥要自研呢?

        30186d2ec506c09c49ba777139d00fc6.webp


        我覺得自研會(huì)帶來一些好處,

        • 自主權(quán) vs. 成本,在擁有自主權(quán)的時(shí)候,需要評(píng)估其帶來的成本,以及潛在的棄坑可能

        • 定制化,

        • 需求滿足,社區(qū)方案有時(shí)并不能很好地契合我們的需求,尤其當(dāng)我們很深入地去使用的時(shí)候

        • 售后服務(wù),出錯(cuò)是能找到 owner 的同學(xué)是非常重要的一點(diǎn)

        有些開源庫看起來美好,但真正用下來會(huì)發(fā)現(xiàn)坑不少。比如組件的文檔工具,目前是選擇的 docz 和 storybook,但兩者用地都有些說不出來的不舒服,并且和 umi 是兩個(gè)生態(tài)的東西,所以我們正考慮基于 umi 開發(fā)自己的文檔工具,可能叫 umipress 或者 father-doc 。

        677a0b3118a11b2c00324506248ecb96.webp


        沉淀的方式是以框架為主,文檔、腳手架、資產(chǎn)市場(chǎng)為輔。

        • 框架具有更強(qiáng)大的約束性和迭代能力,這也是我們所需要的

        • 對(duì)外是 Umi,面向社區(qū)

        • 對(duì)內(nèi)是 Bigfish,在 Umi 的基礎(chǔ)上解決流程和業(yè)務(wù)問題

        插件和插件集

        8336d23f94a06ba8a81ec9409cd11eb2.webp

        5603e505d097e9b921f4d3461acbd797.webp


        我們把使用到的技術(shù)都沉淀到框架(Bigfish)里。框架像是一個(gè)魔法球,把各種技術(shù)棧吸到一起,加工后吐給用戶,以此來支撐業(yè)務(wù)。

        對(duì)于用戶來說,Bigfish 框架是唯一依賴。唯一依賴會(huì)帶來一些實(shí)際的好處,這也是我們一直在內(nèi)部堅(jiān)持這一點(diǎn)的原因,

        • 技術(shù)收斂,保持團(tuán)隊(duì)開發(fā)模式的一致性

        • 無痛升級(jí),我們既要保持對(duì)社區(qū)的技術(shù)跟進(jìn),又要讓業(yè)務(wù)項(xiàng)目跟上步伐,這些中間的屎只能讓框架吃掉,讓開發(fā)者盡可能地?zé)o痛升級(jí)

        • 應(yīng)用治理,相比散落的遍地開花的依賴,唯一依賴可以讓我們更好地推動(dòng)用戶升級(jí)框架,因?yàn)橹灰芤粋€(gè)點(diǎn)即可

        唯一依賴的問題就是大而全,雖然看起來挺不優(yōu)雅,但實(shí)際用過之后會(huì)發(fā)現(xiàn)還蠻香的,除了一開始安裝他會(huì)有點(diǎn)慢。(這一點(diǎn)我們后續(xù)會(huì)通過啟動(dòng)器解決)


        3b37d12ebe6c48f38b1c99193b2bf301.webp


        做了技術(shù)棧收斂之后,我覺得對(duì)外可能夠了,但對(duì)內(nèi)還遠(yuǎn)遠(yuǎn)不夠。

        1. 接流程,讓開發(fā)者能更順暢地跑通創(chuàng)建、本地開發(fā)、聯(lián)調(diào)、部署、發(fā)布和統(tǒng)計(jì)

        2. 接后端框架,后端可能是 Java、Node 或者 PHP(?),不同后端對(duì)于前端產(chǎn)物的要求會(huì)不同,在框架里做好對(duì)接,開發(fā)者就不用費(fèi)心思了

        3. 接場(chǎng)景,場(chǎng)景有很多種,在框架層也需做好對(duì)接。舉一些例子

        • SPA 應(yīng)該是目前用地最多的一種應(yīng)用類型,但有時(shí)也會(huì)不滿足需求

        • 比如運(yùn)營頁面,多個(gè)頁面之間沒有一點(diǎn)點(diǎn)關(guān)系,也不需要互相跳轉(zhuǎn),用 SPA 就沒有意義,這時(shí)候 MPA 可能更適合

        • 比如語雀,我們的文檔平臺(tái),他有前臺(tái)、有后臺(tái)、有 PC 端、有無線端,如果整體是一個(gè) SPA,不僅尺寸大,公共依賴的提取是個(gè)問題,不同場(chǎng)景之間可能還會(huì)相互影響,這時(shí)候,多 SPA 的組合會(huì)更適合他

        • 微前端前面已經(jīng)提過

        • SSR 和 Prerender 則是為了更好的瀏覽器性能,順便解決 SEO 的問題

        接服務(wù),比如登錄服務(wù),統(tǒng)計(jì)服務(wù),問卷服務(wù),評(píng)論服務(wù)等等

        實(shí)現(xiàn)方式是一“件”接入,這里的件是插件,一個(gè)插件實(shí)現(xiàn)一個(gè)功能。然后,我們就有了很多插件。

        f256f920089214cac804e5a92579d3ee.webp


        有了插件之后,我們可以篩選一些插件出來形成插件集,以滿足某個(gè)業(yè)務(wù)的需求,類似 babel 的 plugin 和 preset,或者 eslint 的 rule 和 config。

        **這種方式首先可以滿足不同業(yè)務(wù)的需求。**比如無線業(yè)務(wù),會(huì)比較關(guān)注性能,所以可能會(huì)選一個(gè)切 preact 到 react 的插件、極速版補(bǔ)丁插件、高清方案、fastclick 等等,形成一個(gè)插件集。

        **然后還可以滿足一個(gè)技術(shù)的不同實(shí)現(xiàn),**在一個(gè)業(yè)務(wù)類型豐富的大團(tuán)隊(duì)中,是允許有不同的選擇的。比如數(shù)據(jù)流,大家的選擇可能不同,有些用 dva,有些用 hooks,有些用 mobx,有些自研一套;比如補(bǔ)丁方案,有常規(guī)版、極限版,還有終極版。

        0ac1022ddf9e321dfafcde11d6cfab60.webp


        這是 umi 的插件三態(tài),講過好多次了,文字稿里就不重復(fù)了。

        fff8dd19deb0c63de19e64915222c56d.webp


        這是 umi 插件的示例。想提一點(diǎn)的是,會(huì)用 umi 和會(huì)寫 umi 插件是兩個(gè)完全不同的狀態(tài),會(huì)寫 umi 插件,你基本可以魔改 umi 內(nèi)部 70% 的功能,可以此來達(dá)到滿足需求業(yè)務(wù)需求的目的。

        836bd34759ccb56bcf8f85f05e903185.webp

        46a55030b80e37b6f0faf6a43321d79c.webp

        資產(chǎn)市場(chǎng)和場(chǎng)景市場(chǎng)

        1f551f73a9ad1bf088183bc59e149ccf.webp

        8e6630127e610f5069355ae11ff14a8d.webp


        先來看下開發(fā)者的時(shí)間都去哪了。這是我咨詢了一些同事拍腦袋整理的,不太準(zhǔn)確。

        • 20% 流程相關(guān),從創(chuàng)建到發(fā)布和發(fā)布后統(tǒng)計(jì)

        • 40% 組件使用和開發(fā),如果有合適組件,直接使用;如果沒有,花時(shí)間開發(fā)

        • 30% 交互場(chǎng)景,解決遇到某個(gè)交互場(chǎng)景如何處理,以及處理來自后臺(tái)的請(qǐng)求,把數(shù)據(jù)和視圖串起來

        • 10% 其他

        知道了時(shí)間分配后,大家應(yīng)該知道投時(shí)間去解決哪部分的問題,才能真正達(dá)到提效的目的了吧。

        ea114f0ff6819d92f03a327e4ad6eeff.webp


        資產(chǎn)市場(chǎng)用于解決 40% 的開發(fā)者時(shí)間,非常重要。分為四個(gè)概念,

        • 基礎(chǔ)組件,antd

        • 業(yè)務(wù)組件,基于 antd 封裝的具有業(yè)務(wù)屬性的組件,不對(duì)外

        • 區(qū)塊,組件的使用片段,區(qū)塊是為了方便地把代碼片段加到項(xiàng)目代碼中

        • 模板,多個(gè)區(qū)塊組成的頁面

        655056317105b895e8377f461fbe708b.webp


        而資產(chǎn)市場(chǎng)要真正達(dá)到提效的目的,我覺得還需要解決一些關(guān)鍵的點(diǎn),才能讓整個(gè)流程跑起來。

        • 資產(chǎn)質(zhì)量,組件參考 antd,區(qū)塊和模板是實(shí)實(shí)在在要被添加到用戶項(xiàng)目的代碼,我覺得比組件更難,需要形成對(duì)什么是好代碼的共同認(rèn)識(shí),誰都不希望自己的項(xiàng)目變臟

        • 打通上下游,包括組件的生產(chǎn)和消費(fèi)。生產(chǎn)方是設(shè)計(jì)師和前端,需要保證組件的本地開發(fā)、文檔、打包、發(fā)布等環(huán)節(jié);消費(fèi)方也是設(shè)計(jì)師和前端,資產(chǎn)市場(chǎng)不僅是給前端用的,設(shè)計(jì)師也得用,只有前端拿到的設(shè)計(jì)稿有大量可以對(duì)應(yīng)的資產(chǎn)時(shí),前端開發(fā)才能真正提效,所以,設(shè)計(jì)師是否有能力讓資產(chǎn)市場(chǎng)覆蓋 50% 甚至 80% 的場(chǎng)景非常重要

        bbf145166f2bfc453645bcf1d2ad60a9.webp


        這是內(nèi)部的資產(chǎn)市場(chǎng)和外部開源的 antd。

        83d8f3eeb7d7d70b1664cf79af6e82dd.webp

        91cc93a16508e122bd22332cb2bac60c.webp


        這是資產(chǎn)市場(chǎng)通過 umi ui 的方式使用,支持區(qū)塊、模板以及布局區(qū)塊。

        05214366ed3dcfa366ae8e7a6302bc8e.webp

        右圖來自開源庫 Friend-List,這是一個(gè) suggestion 的實(shí)現(xiàn),他可以簡單做,也可以復(fù)雜做。復(fù)雜做的話,細(xì)節(jié)點(diǎn)就會(huì)很多,比如:

        • 每次輸入都要做請(qǐng)求

        • 快速輸入的時(shí)候,要使用最后的請(qǐng)求,并且取消前面的請(qǐng)求

        • 輸入需要同步到 url

        • 輸入還需要同步到 history,支持前進(jìn)后退

        • 請(qǐng)求加緩存

        • 請(qǐng)求出錯(cuò)處理

        • ...

        而如果每個(gè)開發(fā)者都要去關(guān)心這些細(xì)節(jié),會(huì)很難,成本也很高。那么如何讓開發(fā)者做到又快,產(chǎn)品體驗(yàn)又好,我覺得可能需要場(chǎng)景市場(chǎng),用于解決 30% 的交互場(chǎng)景需求

        沉淀方式可以用 hooks + 文檔的方式;覆蓋面從最簡單的 CURD 開始,到各種復(fù)雜場(chǎng)景。


        902e4e8073862cf1453169e978c4a981.webp


        這里是部分的場(chǎng)景舉例。ae026d6517293d70d42e8ac75210466e.webp

        理想的工作流圖。

        強(qiáng)約束的垂直領(lǐng)域框架

        c1242c53c4fe0402fce222537d4c7c2d.webp


        基于前面講的插件和插件集的方式,我們已經(jīng)能夠滿足各種豐富的業(yè)務(wù)場(chǎng)景,但是仍然給予了用戶很多選擇,選擇包括選擇插件,以及 umi 自身的大量配置項(xiàng)。

        對(duì)于一些垂直領(lǐng)域,其實(shí)還可以做到更好,所以我們最近一直在思考“螞蟻前端應(yīng)該如何寫中臺(tái)代碼”。

        1141c61db692e0bdc35ff6a2b12aa51c.webp


        有幾個(gè)關(guān)鍵的思路,

        • 專治,不提供自由的技術(shù)棧選擇一定程度上會(huì)限制開發(fā)者的,但是效率高的,就看你要哪個(gè)了

        • 極簡,不僅僅是簡單,還要優(yōu)雅;不僅要寫地少,還要寫地好

        然后就強(qiáng)約束配置化約定化展開聊下。

        5beab6ad5e088f91e0f935702448e16d.webp


        前面我們已經(jīng)了解了一致性的重要性,所以何不把這一點(diǎn)做到底呢?

        • 只能用 TypeScript,用 JavaScript 會(huì)報(bào)錯(cuò)

        • 只能用 less + css modules,用 sass、stylus、css in js 會(huì)報(bào)錯(cuò)

        • 只能用內(nèi)置的數(shù)據(jù)流方案,用 redux、mobx 等等會(huì)報(bào)錯(cuò)

        • 等等

        圖上只列了一部分。

        這里的有些約束甚至?xí)行┓慈祟?,但我覺得約束越強(qiáng),越能保持大家的一致性,如果我們已經(jīng)把這條路探地很清楚了,少給選擇或許是更好的選擇。有些限制還不確定是不是好的方式,但是第一版會(huì)盡量把規(guī)則收攏地緊一些。

        d0ceccd32f547cdfed57c35be3cf2091.webp


        配置化不僅是框架和插件的配置,還包括 UI 。

        右圖是 ant-design-pro 的圖,其中 LOGO、導(dǎo)航、菜單對(duì)于 90% 的每個(gè)頁面來說都是固定的,變化的只有右下的頁面區(qū),所以我們何不把固定的部分做成配置呢?

        比如:

        export?default?{
        ??layout:?{
        ????logo:?string;
        ????title:?string;
        ????renderRender:?function;
        ????logout:?function;
        ??},
        ??routes:?[
        ????{
        ??????path,
        ??????//?菜單配置
        ??????menu:?{?name,?icon,?showBreadcrumb?},
        ??????//?權(quán)限配置
        ??????access,
        ????},
        ??],
        }


        Layout 是其中一個(gè)例子,還可以有更多 UI 的配置化。這也是在一定程度在像 low code 的模式靠,我覺得某些研究地很透的垂直場(chǎng)景下,low code 能讓研發(fā)更高效。

        所以我們把適合做成配置的全部配置化,而不能配置的,則會(huì)走約定化。

        4e24a6dc4705dbe8124d6845de4026eb.webp


        之前有用過 ruby on rails 框架,特別喜歡那種約定化的編碼方式,所以我們希望把他也搬到前端研發(fā)流程里。

        • 建一個(gè) locales 目錄,就擁有了國際化

        • 建一個(gè) models 目錄,就擁有了數(shù)據(jù)流

        • 建一個(gè) mock 目錄,就擁有了數(shù)據(jù) mock

        • 建一個(gè) access.ts 文件,就擁有了權(quán)限策略

        • ...

        看起來很黑盒,按照我們約定的方式編碼,并且只能這樣編碼,然后他就能 run 起來。

        0fdb87a600a0faca7783d19201baa6d2.webp


        這是之前在朋友圈看到的圖,大家體會(huì)下,但這就是我們想要實(shí)現(xiàn)的樣子。

        76412b2aaf0cc861fcc0cb6a708214aa.webp


        極簡數(shù)據(jù)流是整體方案的其中一環(huán)。

        右邊是之前做數(shù)據(jù)流調(diào)研時(shí)做的整理,發(fā)現(xiàn)那么多數(shù)據(jù)流方案基本都是在這些方案上的差異,而要選哪個(gè)就看你對(duì)哪些方面比較關(guān)心。這部分展開聊比較長,之后會(huì)額外寫一篇文章介紹。

        然后我們還調(diào)研了下公司內(nèi)部的中臺(tái)項(xiàng)目,發(fā)現(xiàn)大部分是簡單的 CURD,并且全局?jǐn)?shù)據(jù)使用較少,比如通知、登錄、當(dāng)前用戶信息等。所以,我們可能是需要一個(gè)不那么復(fù)雜的,用起來又很簡單的數(shù)據(jù)流方案。

        6c4f4292530b3ed0dc4d9ac381e413cc.webp


        最終討論下來的方案有幾個(gè)特點(diǎn),

        • 基于 hooks,在看到?swr?之后,我開始有點(diǎn)覺得在數(shù)據(jù)流里用 hooks 可能是未來的趨勢(shì),因?yàn)榇罅康慕换?chǎng)景都可以通過 hook 沉淀,但也有一點(diǎn)點(diǎn)擔(dān)心

        • 和框架強(qiáng)綁,脫離框架我們可能沒有優(yōu)勢(shì),但是有框架加持,就能做到比社區(qū)大量的 hooks 數(shù)據(jù)流都“好用”,因?yàn)橹虚g復(fù)雜的事情可以交給框架處理,比如手寫 Provider,比如自動(dòng)處理 model 依賴等等

        • 約定式 model 定義,在 models 目錄下建文件導(dǎo)出 hooks 就是一個(gè) model

        • 單一 API,在組件層或者 model 層通過?useModel?來使用

        總結(jié)

        66525f11e3d3a47f264504bf1f9c3f60.webp


        文字就不復(fù)述了。

        這里和大家分享了螞蟻前端研發(fā)實(shí)踐中三個(gè)重要的點(diǎn),但其實(shí)還有更多的點(diǎn),比如說 UMI UI,如果感興趣,可以來聽我在 12 月 GMTC 深圳的演講。

        分享前端好文,點(diǎn)個(gè)?在看?ecc018e75504e436eea60d591779d607.webp

        瀏覽 79
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            日本r在线 | www.91九色 | 黑人大鸡巴 | 毛片软件在线观看 | 国产真实交换夫妇视频 | 色色网视频 | 啊啊啊轻点视频 | 日本黄色电影免费网站 | 成人网站免费无码视频在线观看 | 国产免费a级片 |