99精品久久精品一区二区-亚洲熟妇无码?v在线播放-日本国产精品无码字幕在线观看-久久久亚洲永夜AV-亚洲一级无码一区二区一-免费国产成高清人在线视频-中文字幕乱码免费观看-国产毛片精品妇女久久久

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

React老項(xiàng)目打包優(yōu)化實(shí)戰(zhàn):用webpack-bundle-analyzer降低65%體積

React老項(xiàng)目打包優(yōu)化實(shí)戰(zhàn):用webpack-bundle-analyzer降低65%體積 最近接手了一個(gè)維護(hù)了三年的 React 老項(xiàng)目用戶反饋首屏白屏?xí)r間越來(lái)越離譜我隨手 build 一次產(chǎn)物里光 JS 就有接近 6MB。團(tuán)隊(duì)之前一直用換個(gè)網(wǎng)絡(luò)環(huán)境試試來(lái)掩蓋問(wèn)題直到要發(fā)新版本連本地開(kāi)發(fā)都明顯卡頓這才決定認(rèn)真做一次打包優(yōu)化。整個(gè)分析和動(dòng)手的過(guò)程核心工具就是 webpack-bundle-analyzer前后花了一周多時(shí)間產(chǎn)物體積降了約 65%首屏加載從 4 秒多壓到了 1.8 秒左右。這篇文章把我這次的完整思路、操作步驟和踩過(guò)的坑記錄下來(lái)如果你手上也有一個(gè)能跑但越來(lái)越慢的 React 老項(xiàng)目正打算做打包優(yōu)化可以直接照著這條路線走。1. 老項(xiàng)目動(dòng)刀之前的三個(gè)準(zhǔn)備工作先看清現(xiàn)狀再想怎么優(yōu)化很多同學(xué)拿到老項(xiàng)目就直接裝 webpack-bundle-analyzer、生成個(gè)報(bào)告然后對(duì)著報(bào)告一頓亂拆拆完發(fā)現(xiàn)構(gòu)建報(bào)錯(cuò)、線上白屏、緩存全失效。我這次學(xué)乖了動(dòng)手前先做了三件事這幾步幾乎決定了后續(xù)優(yōu)化能不能順利落地。1.1 鎖定項(xiàng)目當(dāng)前的構(gòu)建工具鏈版本老項(xiàng)目最麻煩的地方在于你不知道它在哪一年突然停更過(guò)。所以第一步不是裝插件而是先確認(rèn) webpack 和 React 的版本這兩個(gè)版本直接決定你能用哪些優(yōu)化手段。我一般這樣排查看package.json里的devDependencies確認(rèn)webpack主版本執(zhí)行webpack --version確認(rèn)命令行實(shí)際使用的版本在package.json里確認(rèn)react和react-dom版本這關(guān)系到能不能用React.lazy做路由懶加載檢查 webpack 配置里有沒(méi)有DllPlugin、CommonsChunkPlugin這類(lèi)歷史遺留方案。這里有個(gè)容易忽略的點(diǎn)webpack 3 時(shí)代流行的CommonsChunkPlugin在 webpack 4 里已經(jīng)廢掉了如果你項(xiàng)目里還有這個(gè)配置同時(shí)又想用optimization.splitChunks運(yùn)行時(shí)會(huì)有沖突或者直接報(bào)錯(cuò)。我接手這個(gè)項(xiàng)目時(shí)配置文件里就同時(shí)存在CommonsChunkPlugin和一堆手寫(xiě)的externals這些都是早年用 CDN 方式引第三方庫(kù)留下的需要先理清楚哪些還生效哪些其實(shí)已經(jīng)是死代碼。另外React 版本決定了懶加載方案。React 16.6 之前沒(méi)有React.lazy只能用react-loadable或者自己寫(xiě)高階組件做異步加載。我的項(xiàng)目是 React 16.8后來(lái)用React.lazy Suspense比較順。如果你手里的老項(xiàng)目還在 React 15.x別急著抄后面的代碼得先解決 React 版本升級(jí)或者改用react-loadable。1.2 建立優(yōu)化前的數(shù)據(jù)基線沒(méi)有基線后面所有優(yōu)化都沒(méi)有說(shuō)服力第二件事是在任何優(yōu)化動(dòng)作之前把優(yōu)化前的各項(xiàng)數(shù)據(jù)記錄下來(lái)。這不是走形式而是整個(gè)優(yōu)化工程里最重要的參照物。沒(méi)有基線你拆完包之后說(shuō)感覺(jué)快了很多那跟換個(gè)網(wǎng)絡(luò)環(huán)境試試有什么區(qū)別我用 Chrome DevTools 調(diào)成 Slow 3G 網(wǎng)絡(luò)用無(wú)痕窗口打開(kāi)線上頁(yè)面記錄以下幾項(xiàng)指標(biāo)記錄值說(shuō)明首屏請(qǐng)求的 JS 資源總大小通過(guò) Network 面板的 Transfer Size 合計(jì)這是用戶真實(shí)下載的字節(jié)數(shù)首屏請(qǐng)求數(shù)Network 面板統(tǒng)計(jì)老項(xiàng)目常見(jiàn)二三十個(gè)請(qǐng)求DOMContentLoaded 時(shí)間Performance 面板粗略反映 HTML腳本執(zhí)行完的時(shí)間FCP首次內(nèi)容繪制Lighthouse 或 Performance用戶感知到頁(yè)面有東西了的時(shí)刻構(gòu)建產(chǎn)物體積總和webpack --profile或 build 輸出本地產(chǎn)物總大小我當(dāng)時(shí)記錄的基線數(shù)據(jù)是這樣的首屏 JS 資源 transfer 大小約 1.9MBgzip 后請(qǐng)求數(shù) 27 個(gè)FCP 在 Slow 3G 下是 4.2 秒。這些數(shù)字寫(xiě)下來(lái)之后后面每做一步優(yōu)化都可以對(duì)照著看是否真的有效避免自我感覺(jué)良好。這里要額外提醒一句測(cè)量工具本身會(huì)帶來(lái)干擾。比如 Chrome DevTools 的 Network 面板如果開(kāi)著緩存禁用測(cè)出來(lái)的數(shù)字會(huì)偏大。建議統(tǒng)一用無(wú)痕窗口并且固定設(shè)備模擬檔位保證前后對(duì)比在同一個(gè)環(huán)境下進(jìn)行。1.3 別急著清依賴先整體過(guò)一遍 package.json 的重復(fù)依賴?yán)享?xiàng)目的依賴幾乎都是能用就行堆出來(lái)的。我在優(yōu)化前先執(zhí)行了npm ls --depth0和npm ls lodash發(fā)現(xiàn)項(xiàng)目里同時(shí)存在lodash和lodash-es還有兩套版本相差很大的moment一個(gè)是業(yè)務(wù)代碼直接用另一個(gè)是被某個(gè)內(nèi)部組件庫(kù)間接依賴的。這種重復(fù)依賴如果不提前發(fā)現(xiàn)優(yōu)化到一半很容易被為什么拆了這個(gè)庫(kù)包還是這么大卡住。這一步不需要把依賴全部理清但至少要回答三個(gè)問(wèn)題項(xiàng)目里有沒(méi)有同名不同版本的庫(kù)有沒(méi)有功能重疊的庫(kù)moment和dayjs同時(shí)存在有沒(méi)有通過(guò)externals從 CDN 引入的庫(kù)這三個(gè)問(wèn)題的答案會(huì)直接影響后面 splitChunks 的 cacheGroups 怎么設(shè)計(jì)。2. 接入 webpack-bundle-analyzer兩種方式各有利弊工具接入本身不難難的是選對(duì)方式。我在這個(gè)項(xiàng)目里兩種方式都試過(guò)一種是在 webpack 配置里直接掛插件另一種是用stats.json配合命令行獨(dú)立分析。下面把細(xì)節(jié)和適用場(chǎng)景都講清楚。2.1 方式一作為 webpack 插件集成構(gòu)建完自動(dòng)打開(kāi)報(bào)告最直接的方式就是在 webpack 配置文件里加一個(gè)插件實(shí)例。我通常不會(huì)直接寫(xiě)死在生產(chǎn)配置里而是用一個(gè)環(huán)境變量控制避免團(tuán)隊(duì)每次構(gòu)建都彈出瀏覽器窗口。const { BundleAnalyzerPlugin } require(webpack-bundle-analyzer); module.exports { // ... 其他配置 plugins: [ process.env.ANALYZE ? new BundleAnalyzerPlugin({ analyzerMode: server, // server 模式會(huì)啟動(dòng)本地服務(wù)并自動(dòng)打開(kāi)瀏覽器 analyzerHost: 127.0.0.1, analyzerPort: 8888, reportFilename: bundle-report.html, openAnalyzer: true, generateStatsFile: false, // 如果只需要報(bào)告不必生成 stats.json }) : null, ].filter(Boolean), };然后在package.json里加一條腳本{ scripts: { build:analyze: cross-env ANALYZE1 webpack --config webpack.prod.config.js } }這樣執(zhí)行npm run build:analyze就會(huì)啟動(dòng)一個(gè)本地服務(wù)瀏覽器自動(dòng)打開(kāi)127.0.0.1:8888展示可視化的依賴樹(shù)形圖treemap。每個(gè)方塊代表一個(gè)模塊方塊越大說(shuō)明該模塊占用的體積越大顏色深淺則代表是否為 gzip 壓縮后的大小。插件方式的好處是集成簡(jiǎn)單適合團(tuán)隊(duì)里所有人都能一鍵跑分析的場(chǎng)景。但它的缺點(diǎn)也很明顯BundleAnalyzerPlugin會(huì)作為 webpack 插件參與構(gòu)建雖然不影響產(chǎn)物但會(huì)在構(gòu)建過(guò)程中增加額外的統(tǒng)計(jì)開(kāi)銷(xiāo)構(gòu)建時(shí)間會(huì)長(zhǎng)一些。而且如果 webpack 配置特別復(fù)雜比如有多個(gè)環(huán)境配置文件你需要確保插件加在了正確的那個(gè)配置文件里。2.2 方式二用 stats.json 配合命令行不污染業(yè)務(wù)配置第二種方式是我比較推薦的尤其適合老項(xiàng)目——因?yàn)樗耆粍?dòng) webpack 配置。webpack 本身就支持導(dǎo)出整個(gè)構(gòu)建過(guò)程的 stats 信息導(dǎo)出成 JSON 文件后用webpack-bundle-analyzer這個(gè)命令行工具直接分析。# 先構(gòu)建并導(dǎo)出 stats 數(shù)據(jù) webpack --config webpack.prod.config.js --json --profile stats.json # 再啟動(dòng)分析器 npx webpack-bundle-analyzer stats.json這種方式有幾個(gè)實(shí)際好處不需要在項(xiàng)目代碼里引入任何插件不影響正常構(gòu)建stats.json是構(gòu)建的完整快照包含模塊依賴、體積、耗時(shí)等信息后續(xù)做對(duì)比分析時(shí)可以直接復(fù)用可以配合 CI 流程把每次構(gòu)建的stats.json歸檔形成體積趨勢(shì)圖。要注意的是--json輸出的文件很大我這個(gè)項(xiàng)目大概 40 多 MB所以用完記得從項(xiàng)目目錄里刪掉或者用.gitignore排除。另外如果.babelrc或tsconfig里配置了緩存--json導(dǎo)出的是實(shí)際構(gòu)建結(jié)果不受緩存影響這點(diǎn)可以放心。2.3 拿到報(bào)告之后先看這四個(gè)地方再動(dòng)手報(bào)告生成后很多人的第一反應(yīng)是盯著最顯眼的那個(gè)大色塊準(zhǔn)備開(kāi)始拆它。我的建議是先快速過(guò)四個(gè)關(guān)鍵點(diǎn)這樣你腦子里對(duì)項(xiàng)目整體的構(gòu)成能有一個(gè)完整的圖景看parsed size還是gzip size。雙擊某個(gè)色塊可以切換展示模式。parsed size是未壓縮的原始大小gzip size是壓縮后的傳輸大小。判斷是否值得優(yōu)化時(shí)應(yīng)該以 gzip 為主要參考因?yàn)榫€上服務(wù)器通常開(kāi)了 gzip??慈肟?chunk 的大小分布。把報(bào)告左側(cè)的 chunk 列表展開(kāi)關(guān)注哪些 chunk 是首屏加載時(shí)就要請(qǐng)求的entry chunk哪些是路由懶加載之后才會(huì)請(qǐng)求的async chunk??从袥](méi)有異常大的單模塊。有些庫(kù)本身不算大但因?yàn)橐肓怂姓Z(yǔ)言包、所有主題體積會(huì)成倍膨脹這類(lèi)問(wèn)題非常適合定向處理??粗貜?fù)模塊。如果同一個(gè)庫(kù)名出現(xiàn)在多個(gè) chunk 里說(shuō)明業(yè)務(wù)代碼對(duì)它的引用方式有問(wèn)題可能是按需引入沒(méi)生效也可能是 cacheGroups 沒(méi)有正確聚合。我當(dāng)時(shí)看完報(bào)告最直觀的感受就是這個(gè)項(xiàng)目不是某一個(gè)庫(kù)太大而是每一個(gè)庫(kù)都沒(méi)被好好控制。這也為后面的優(yōu)化定下了基調(diào)——不是做一兩個(gè)大改動(dòng)而是系統(tǒng)性地把每一類(lèi)依賴都重新過(guò)一遍。3. 報(bào)告暴露出來(lái)的問(wèn)題React 老項(xiàng)目的五個(gè)典型通病我的項(xiàng)目報(bào)告里vendor.js這一個(gè) chunk 的 parsed size 就達(dá)到了 4.6MB。如果你現(xiàn)在也正對(duì)著一份類(lèi)似的報(bào)告發(fā)愁不用慌下面這五個(gè)問(wèn)題在 React 老項(xiàng)目里幾乎是標(biāo)配而且都有成熟的解法。3.1 全量引入 UI 組件庫(kù)和圖表庫(kù)我的項(xiàng)目里antd的 parsed size 是 1.8MB 左右。為什么這么大因?yàn)闃I(yè)務(wù)代碼里寫(xiě)的是import { Button } from antd看似是按需引入但如果 babel 沒(méi)有配babel-plugin-import這條語(yǔ)句最終會(huì)被編譯成var Button require(antd)也就是把整個(gè)antd全部加載進(jìn)來(lái)。本質(zhì)原因就是import { Button } from antd這個(gè)語(yǔ)法本身具備 tree-shaking 的可能但前提是antd的 package.json 里配置了sideEffects: false或module入口而且 babel 轉(zhuǎn)譯時(shí)不能把模塊系統(tǒng)直接轉(zhuǎn)成 CommonJS。圖表庫(kù)也是這樣。項(xiàng)目里用了echarts業(yè)務(wù)代碼是import * as echarts from echarts這等于把 echarts 全部圖表類(lèi)型、渲染器和組件都帶上了parsed size 超過(guò) 1MB。正確做法是echarts/core按需引入需要的圖表和渲染器這個(gè)在后面 4.3 節(jié)詳細(xì)講。3.2 moment.js 把所有語(yǔ)言包都打進(jìn)來(lái)了moment是 React 老項(xiàng)目里最典型的體積元兇之一。默認(rèn)情況下moment會(huì)打包全部 locale 語(yǔ)言文件即便你只需要中文。報(bào)告里你會(huì)看到moment的 parsed size 超過(guò) 700KB但其中真正用的只有一小部分。專(zhuān)門(mén)的 locale 文件全部打進(jìn)包里屬于典型的用不到的體積。這類(lèi)庫(kù)的優(yōu)化思路有兩個(gè)方向用IgnorePlugin剔除 locale 文件或者干脆換dayjs這種體積小一個(gè)數(shù)量級(jí)的替代庫(kù)。我最后選擇了后者細(xì)節(jié)在后面單獨(dú)說(shuō)。3.3 lodash 全量引入導(dǎo)致 tree-shaking 失效老項(xiàng)目里幾乎不可能沒(méi)有l(wèi)odash。我的項(xiàng)目里lodash的 parsed size 是 400KB 左右原因是大量代碼里直接import _ from lodash。lodash主包是 CommonJS 格式現(xiàn)代打包工具很難對(duì)它做 tree-shaking所以最佳習(xí)慣是改為import debounce from lodash/debounce這樣的按需路徑引入或者配置babel-plugin-lodash自動(dòng)轉(zhuǎn)換。如果你在報(bào)告里看到lodash-es而不是lodash那又是另一種情況lodash-es是 ES module 版本理論上可以被 tree-shaking但前提是你的業(yè)務(wù)代碼沒(méi)有被 babel 轉(zhuǎn)成 CommonJS。很多老項(xiàng)目的.babelrc里配置了babel/preset-env默認(rèn)會(huì)把 ES module 轉(zhuǎn)成 CommonJS這會(huì)導(dǎo)致lodash-es的 tree-shaking 優(yōu)勢(shì)完全喪失。所以排查時(shí)不能只看庫(kù)本身還要看 babel 的配置鏈。3.4 polyfill 全量引入導(dǎo)致基礎(chǔ)工具函數(shù)被重復(fù)打包React 老項(xiàng)目里babel/polyfill或core-js全量引入的情況非常多。babel/polyfill本質(zhì)上是core-js和regenerator-runtime的合集全量引入會(huì)讓每個(gè)用到新 API 的頁(yè)面都背上幾百 KB 的 polyfill 成本。正確的做法是按需要的特性引入core-js中的具體模塊或者用babel/preset-env配合useBuiltIns: usage實(shí)現(xiàn)按需 polyfill。老項(xiàng)目之所以容易踩這個(gè)坑是因?yàn)楫?dāng)年寫(xiě)import babel/polyfill的時(shí)候覺(jué)得省事后面就再也沒(méi)人記得去改。同時(shí)如果 babel 配置里沒(méi)有采用babel/plugin-transform-runtimebabel 轉(zhuǎn)譯時(shí)會(huì)在每個(gè)文件里都內(nèi)聯(lián)一部分輔助函數(shù)造成大量重復(fù)。這個(gè)在報(bào)告里不容易一眼看到因?yàn)槊總€(gè)重復(fù)模塊都很小但積少成多后總效果非常明顯。3.5 所有的路由頁(yè)面都打包進(jìn)了首屏入口 chunkReact 老項(xiàng)目普遍沒(méi)有做路由懶加載。如果你的 App 里有十幾個(gè)路由頁(yè)面它們會(huì)全部打包進(jìn)一個(gè)入口 chunk 里用戶訪問(wèn)首頁(yè)時(shí)所有頁(yè)面的代碼都要先下載完。報(bào)告里體現(xiàn)為入口 chunk 特別大async chunk 數(shù)目為零。這是優(yōu)化優(yōu)先級(jí)最高的一項(xiàng)因?yàn)樗氖找鎺缀趿⒏鸵?jiàn)影。4. 按優(yōu)先級(jí)動(dòng)手我實(shí)際執(zhí)行的五步優(yōu)化下面按我執(zhí)行的順序把每一步的具體操作和理由講清楚。這個(gè)順序不是隨便排的每一步都會(huì)影響下一步的方案選擇所以建議大家按順序來(lái)。4.1 第一步用 splitChunks 把 node_modules 里的公共依賴統(tǒng)一抽離這是 webpack 4 之后最基礎(chǔ)、也是收益最大的一步。把第三方依賴統(tǒng)一抽成獨(dú)立的 chunk一方面減少了模塊在多個(gè) chunk 之間的重復(fù)打包另一方面利用瀏覽器緩存讓用戶升級(jí)業(yè)務(wù)代碼時(shí)不用重新下載體積龐大的第三方庫(kù)。我當(dāng)時(shí)的 splitChunks 配置大致是這樣optimization: { splitChunks: { chunks: all, maxInitialRequests: 4, maxAsyncRequests: 6, cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10, name: vendors }, antd: { test: /[\\/]node_modules[\\/]antd[\\/]/, priority: 10, name: antd }, echarts: { test: /[\\/]node_modules[\\/]echarts[\\/]/, priority: 10, name: echarts }, common: { minChunks: 2, minSize: 30000, priority: -20, name: common } } } }這里有幾個(gè)細(xì)節(jié)值得展開(kāi)。chunks: all表示同步引入和異步引入的代碼都參與拆包。如果你只寫(xiě)chunks: initial那么動(dòng)態(tài)import()引入的模塊不會(huì)被拆分可能導(dǎo)致懶加載的 chunk 里又重復(fù)打了一遍 React 或 antd。這個(gè)參數(shù)是最容易配錯(cuò)的點(diǎn)。priority決定多個(gè) cacheGroup 匹配時(shí)誰(shuí)優(yōu)先。antd 和 echarts 的體積大我希望它們能單獨(dú)成 chunk這樣它們的 hash 只會(huì)在自身內(nèi)容變化時(shí)才變化業(yè)務(wù)代碼更新不會(huì)導(dǎo)致這兩個(gè)大 chunk 重新下載。如果不給它們單獨(dú)分組的 priority它們會(huì)被并進(jìn)vendors那樣雖然拆包總數(shù)少但 antd 一更新整個(gè) vendors 都失效緩存利用率會(huì)低很多。name字段一定要固定。webpack 4 默認(rèn)會(huì)給自動(dòng)生成的 vendor chunk 按數(shù)字編號(hào)命名當(dāng)依賴順序變化時(shí)編號(hào)會(huì)漂移導(dǎo)致 chunk hash 大面積變化這是明明沒(méi)改代碼hash 卻全變了的經(jīng)典原因。我踩過(guò)這個(gè)坑后所有 cacheGroup 都顯式指定 name。如果你是從 webpack 3 升級(jí)上來(lái)一定要先刪掉原來(lái)配置里的CommonsChunkPlugin否則它和splitChunks會(huì)同時(shí)生效產(chǎn)生大量重復(fù)的小 chunk。這一步做完我的vendor.js從 4.6MB 拆成了antd、echarts、vendors三個(gè) chunk加起來(lái)反而比原來(lái)小了不少因?yàn)槔锩娴闹貜?fù)模塊被剝離了。4.2 第二步路由級(jí)代碼分割讓首屏只加載當(dāng)前頁(yè)面需要的代碼拆完公共依賴后入口 chunk 依然很大因?yàn)槭畮讉€(gè)路由頁(yè)面全都打包在里面。這一步的目標(biāo)是把所有頁(yè)面的代碼變成當(dāng)前頁(yè)面的代碼 運(yùn)行時(shí)按需加載的代碼。如果你的 React 版本在 16.6 以上直接用React.lazy加Suspenseimport { lazy, Suspense } from react; import { BrowserRouter as Router, Route, Switch } from react-router-dom; import Loading from ./components/Loading; const Dashboard lazy(() import(/* webpackChunkName: dashboard */ ./pages/Dashboard)); const UserManage lazy(() import(/* webpackChunkName: user */ ./pages/UserManage)); const Settings lazy(() import(/* webpackChunkName: settings */ ./pages/Settings)); function App() { return ( Router Suspense fallback{Loading /} Switch Route exact path/ component{Dashboard} / Route path/user component{UserManage} / Route path/settings component{Settings} / /Switch /Suspense /Router ); } export default App;關(guān)鍵點(diǎn)在于import(/* webpackChunkName: dashboard */ ./pages/Dashboard)里的webpackChunkName注釋它給動(dòng)態(tài)生成的 chunk 起了一個(gè)有意義的文件名否則你會(huì)在報(bào)告里看到一堆0.js、1.js完全沒(méi)法定位是哪個(gè)頁(yè)面。如果你項(xiàng)目還在 React 15.x用react-loadableimport Loadable from react-loadable; const Dashboard Loadable({ loader: () import(./pages/Dashboard), loading: Loading, delay: 200, });這一步做完優(yōu)化效果非常直觀。首屏入口 chunk 從一個(gè) 近5MB 的龐然大物變成了只包含 React 運(yùn)行時(shí)、路由、布局框架等公共代碼的 200KB 左右 chunk。每個(gè)路由頁(yè)面獨(dú)立成 chunk用戶訪問(wèn)哪個(gè)頁(yè)面就加載哪個(gè)頁(yè)面的代碼。這里有一個(gè)反直覺(jué)的坑不要對(duì)首屏默認(rèn)進(jìn)入的那個(gè)頁(yè)面做懶加載。如果首頁(yè)本身就是落地頁(yè)把首頁(yè)也做成動(dòng)態(tài) import首屏?xí)喟l(fā)起一個(gè) HTTP 請(qǐng)求反而增加延遲。我在項(xiàng)目里把登錄頁(yè)和首頁(yè)放在了入口 chunk 里其余頁(yè)面懶加載。4.3 第三步UI 庫(kù)和圖表庫(kù)按需引入讓 tree-shaking 真正生效路由拆分解決了整體過(guò)大的問(wèn)題接下來(lái)要解決單個(gè)庫(kù)過(guò)大的問(wèn)題。先是 antd配置babel-plugin-import后import { Button } from antd會(huì)被自動(dòng)轉(zhuǎn)換為import Button from antd/es/button連同樣式也會(huì)按需加載。.babelrc里這樣配{ presets: [babel/preset-react, [babel/preset-env, { modules: false }]], plugins: [ [import, { libraryName: antd, libraryDirectory: es, style: css }] ] }注意preset-env里的modules: false這個(gè)配置讓 babel 保留 ES module 語(yǔ)法不轉(zhuǎn)成 CommonJS這樣打包工具才能在后續(xù)做 tree-shaking。如果你項(xiàng)目里同時(shí)用了 TSbabel/preset-typescript也要注意同樣的設(shè)置。style: css表示按需加載組件對(duì)應(yīng)的 css 文件。如果你的項(xiàng)目用的是 less 定制主題可以把style改成trueantd 會(huì)加載 less 文件。這個(gè)改動(dòng)需要注意全局樣式覆蓋如果你之前靠antd/dist/antd.css引入的全局 reset 樣式改成按需后要在公共入口處手動(dòng)引一次。echarts 的處理也類(lèi)似但思路不同。echarts 5 開(kāi)始支持echarts/core方式按需注冊(cè)import * as echarts from echarts/core; import { BarChart, LineChart } from echarts/charts; import { GridComponent, TooltipComponent } from echarts/components; import { CanvasRenderer } from echarts/renderers; echarts.use([BarChart, LineChart, GridComponent, TooltipComponent, CanvasRenderer]);這一步實(shí)際上是把 echarts 從一個(gè) 1MB 的大包縮小到只包含你用到的那幾種圖表。我項(xiàng)目里主要用柱狀圖和折線圖配完工具提示和網(wǎng)格gzip 后只有原來(lái)的三分之一左右。lodash 的處理我選了最保守的方式不換庫(kù)直接把全量引入改成按路徑引入。import _ from lodash改成import debounce from lodash/debounce。如果你的代碼里用了大量 lodash API可以在 babel 里加babel-plugin-lodash自動(dòng)轉(zhuǎn)換省得手動(dòng)改幾十個(gè)文件。但是要留意這個(gè)插件對(duì)lodash-es和 CommonJS 混用的情況處理得不夠理想所以我最后還是手動(dòng)改了一部分關(guān)鍵模塊。4.4 第四步對(duì) moment.js 這種頑固分子下手先裁剪再替換moment 的問(wèn)題前面說(shuō)過(guò)了默認(rèn)打包全部 locale體積大。最省事的操作是先用IgnorePlugin把 locale 文件剔除掉const webpack require(webpack); module.exports { plugins: [ new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), ], };這個(gè)正則的意思是匹配包名以moment開(kāi)頭、導(dǎo)入路徑是./locale的模塊直接忽略。配置之后 moment 的 parsed size 大概能從 700KB 降到 300KB 左右因?yàn)楹诵膸?kù)本身還是保留的。別小看這個(gè)正則IgnorePlugin的resourceRegExp和contextRegExp兩個(gè)參數(shù)的順序很容易寫(xiě)反寫(xiě)反后可能導(dǎo)致整個(gè) moment 都被忽略運(yùn)行時(shí)報(bào)錯(cuò)。如果你希望體積縮得更狠就把 moment 整體替換成 dayjs。dayjs 的核心只有 2KB 左右API 和 moment 高度一致。我的替換步驟是這樣的在package.json里加入dayjs暫時(shí)保留 moment先用 webpack alias 把所有import xxx from moment指向 dayjsresolve: { alias: { moment: dayjs, }, },全局搜索業(yè)務(wù)代碼里所有moment用法逐個(gè)處理 API 差異最典型的差異是moment().format(YYYY-MM-DD)在兩者中寫(xiě)法一致moment().startOf(day)在 dayjs 里行為基本一致moment.locale(zh-cn)需要改成import dayjs/locale/zh-cn加上dayjs.locale(zh-cn)moment.isMoment()在 dayjs 里要改成dayjs.isDayjs()。處理完所有業(yè)務(wù)代碼后最后再看報(bào)告確認(rèn)項(xiàng)目里還有沒(méi)有其他包比如某個(gè)老版本 antd 或業(yè)務(wù)組件庫(kù)依賴 moment。我當(dāng)時(shí)發(fā)現(xiàn)一個(gè)內(nèi)部統(tǒng)計(jì)組件間接依賴了 moment 2.x但它只是用它格式化日期于是我把那個(gè)組件也改了。這一步做完moment 相關(guān)體積從 700KB 變成了 dayjs 的 7KB。甚至比很多同學(xué)在第一步做的拆包效果更明顯。4.5 第五步輸出文件加上 ContentHash讓之前拆出來(lái)的緩存真正生效前面拆了那么多 chunk如果輸出文件名還是固定的bundle.js那瀏覽器永遠(yuǎn)不知道這些文件更新了會(huì)一直使用舊緩存。這次優(yōu)化的最后一步就是把輸出文件改成帶內(nèi)容 hash 的形式。output: { filename: [name].[contenthash:8].js, chunkFilename: [name].[contenthash:8].js, },[contenthash]是根據(jù)文件內(nèi)容生成的 hash文件內(nèi)容變化時(shí) hash 才變化。加上這個(gè)之后業(yè)務(wù)代碼更新時(shí)只有業(yè)務(wù) chunk 的 hash 會(huì)變antd、echarts、vendors 這些第三方 chunk 的 hash 保持不變?yōu)g覽器可以直接走緩存。但這里有一個(gè) webpack 4 特有的坑模塊的 id 默認(rèn)是自增數(shù)字只要新增或刪除一個(gè)模塊所有模塊的 id 都可能變化導(dǎo)致許多本來(lái)沒(méi)變的 chunk 的 hash 跟著變。解決方式是加上optimization.moduleIds: hashed讓模塊 id 基于模塊路徑生成內(nèi)容路徑不變 id 就不變。webpack 5 已經(jīng)默認(rèn)用deterministic方案不需要手動(dòng)配。optimization: { moduleIds: hashed, },這個(gè)配置本身其實(shí)也是優(yōu)化的一部分。很多人只加了[contenthash]卻漏了moduleIds發(fā)現(xiàn) hash 還是到處變以為配置無(wú)效其實(shí)問(wèn)題就出在模塊 id 不穩(wěn)定。另外如果服務(wù)器還沒(méi)開(kāi) gzip這一步建議一并處理。最穩(wěn)妥的方式是讓運(yùn)維在 Nginx 層開(kāi)啟 gzip 或 brotli如果不方便改服務(wù)器配置也可以用compression-webpack-plugin在構(gòu)建時(shí)直接生成.gz文件讓服務(wù)器直接返回壓縮文件。開(kāi)啟 gzip 后JS 體積大概能再縮小 60% 到 70%效果非??捎^。5. 拆包優(yōu)化之后的隱藏坑緩存穩(wěn)定性、請(qǐng)求數(shù)與驗(yàn)證方式優(yōu)化做完不等于萬(wàn)事大吉。我這次在收尾階段又踩了幾個(gè)坑都是拆包之后才會(huì)暴露出來(lái)的問(wèn)題專(zhuān)門(mén)寫(xiě)一節(jié)提醒后來(lái)的同學(xué)。5.1 拆包的穩(wěn)定性直接決定緩存命中率拆包方案確定之后最重要的一件事是保證每次構(gòu)建相同的代碼生成相同的 chunk 和 hash。否則哪怕你沒(méi)改代碼重新構(gòu)建出來(lái)的 hash 也變了緩存全部失效優(yōu)化等于白做。保證穩(wěn)定性的關(guān)鍵有三個(gè)cacheGroup 里的name必須顯式指定不要用 webpack 自動(dòng)生成的數(shù)字編號(hào)配置optimization.moduleIds讓模塊 id 穩(wěn)定動(dòng)態(tài)import()必須在代碼里用靜態(tài)字符串路徑不要用變量拼接路徑否則 webpack 沒(méi)法確定 chunk 邊界可能生成不可預(yù)測(cè)的 chunk。我建議在優(yōu)化完成后連續(xù)構(gòu)建兩次對(duì)比兩次dist目錄里的文件名是否完全一致。如果兩次 hash 不同說(shuō)明配置里還有不穩(wěn)定因素不要急著上線。5.2 拆得太碎首屏請(qǐng)求數(shù)反而拖累加載拆包有個(gè)陷阱不是越細(xì)越好。HTTP/1.1 時(shí)代瀏覽器對(duì)同域名的并發(fā)請(qǐng)求數(shù)限制在 6 個(gè)左右如果你把業(yè)務(wù)代碼拆成三十個(gè)小 chunk首屏要排隊(duì)下載反而更慢。即便現(xiàn)在普遍用 HTTP/2每個(gè)請(qǐng)求也有 header 和連接開(kāi)銷(xiāo)請(qǐng)求數(shù)過(guò)多依然會(huì)拖慢首屏。我在這個(gè)項(xiàng)目里嘗試過(guò)把每個(gè)頁(yè)面里的業(yè)務(wù)模塊進(jìn)一步拆成細(xì)粒度 chunk結(jié)果首屏請(qǐng)求數(shù)從十幾個(gè)變成三十幾個(gè)FCP 反而從 1.8 秒漲回 2.1 秒。后來(lái)我把maxInitialRequests設(shè)置為 4把首頁(yè)相關(guān)的幾個(gè)核心模塊合并到一個(gè) chunk 里才回到理想狀態(tài)。如果你的服務(wù)器不支持 HTTP/2尤其要注意不要拆太碎。老項(xiàng)目有時(shí)還掛著某種內(nèi)網(wǎng)環(huán)境的舊瀏覽器請(qǐng)求并發(fā)限制更嚴(yán)格寧可單個(gè) chunk 大一點(diǎn)也別讓首屏請(qǐng)求數(shù)失控。5.3 優(yōu)化效果的驗(yàn)證同時(shí)看體積數(shù)字和真實(shí)加載表現(xiàn)最后驗(yàn)證階段我又把 webpack-bundle-analyzer 生成了一份新的報(bào)告和優(yōu)化前的報(bào)告對(duì)比。同一份stats.json也可以直接復(fù)用跑一次webpack-bundle-analyzer打開(kāi)舊文件和 新文件看顏色塊的面積變化非常直觀。我優(yōu)化前后的關(guān)鍵數(shù)據(jù)對(duì)比項(xiàng)目?jī)?yōu)化前優(yōu)化后總構(gòu)建產(chǎn)物 parsed size約 6.8MB約 2.4MBgzip 后總傳輸體積約 1.9MB約 700KB首屏 chunk 數(shù)量1 個(gè)所有頁(yè)面都在一起4 個(gè)FCPSlow 3G4.2 秒1.8 秒白屏?xí)r間用戶反饋3 秒以上基本感覺(jué)不到但是要特別注意構(gòu)建產(chǎn)物小了不一定代表線上真實(shí)體驗(yàn)就快了。還要在線上環(huán)境重新測(cè)一遍 FCP、LCP、請(qǐng)求數(shù)用前面同樣的網(wǎng)絡(luò)條件。我見(jiàn)過(guò)有同學(xué)本地構(gòu)建產(chǎn)物很小但上線后因?yàn)榉?wù)器沒(méi)開(kāi) gzip、或者某些 chunk 被錯(cuò)誤的緩存策略緩存了體驗(yàn)反而更差。所以驗(yàn)證一定要以真實(shí)線上環(huán)境為準(zhǔn)?;氐介_(kāi)頭說(shuō)的那個(gè)問(wèn)題老項(xiàng)目不是不能優(yōu)化而是要有方法、有順序、有驗(yàn)證。webpack-bundle-analyzer 的價(jià)值在于把我覺(jué)得項(xiàng)目很慢變成我知道項(xiàng)目慢在哪個(gè)模塊所有決策都建立在數(shù)據(jù)之上。順著報(bào)告暴露的問(wèn)題按順序解決每一步改動(dòng)都能在下一份報(bào)告里看到反饋這才是打包優(yōu)化最踏實(shí)的打開(kāi)方式。最后再分享一個(gè)我在收尾時(shí)保留的習(xí)慣我把 webpack-bundle-analyzer 接進(jìn)了 CI 的一個(gè)可選任務(wù)每次發(fā)版前指定跑一次報(bào)告以 HTML 形式歸檔。幾個(gè)月后回頭翻就能看到項(xiàng)目體積的走勢(shì)。只要新引入的依賴讓體積明顯反彈下一次報(bào)告里立刻能看出來(lái)。這種讓數(shù)據(jù)持續(xù)說(shuō)話的做法比任何一次性的優(yōu)化都更管用。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
一本久久婷婷| ss五月天激情| 这里只有精彩视频| 插插五月天| 丁香五月激情久久麻豆| 色婷婷五月在线| 色99免费视频中文| 996er热| 婷婷在线播放av| 色噜噜狠狠色综无码久久合欧美| 色天天综合成人网| 3p久久| 色综合久久综合中文综合网| 婷婷五月天777| 人妻丰满精品一区二区A片| 99re思思精品视频在线观看| 亚洲日本三级片| 久久视频在线| 91精品无码| 激情五月久久| 欧美狠狠地| 色五月婷婷影视| 激情综合色图| 婷婷五月丁香久久| 九九精品99| 色婷婷成人做爰A片免费看网站| 婷婷五月天色网久| 激情亚洲婷婷| 超碰国产在线播放| 天堂久久精品| 五月综合影院| 色色自拍视频网站| 丁香五月婷婷99| 99精品自拍| 国产古装妇女野外A片| 97韩国久久电影院| 欧美一级色| AA片在线观看视频在线播放| 五月停停999| 免费视频舔| 亚洲av综合在线| 久久婷婷五月综合| 国色天香伊人狠狠色| 在线不卡中文字幕| 亚洲网在线观看| 亚洲无码色色| WWW.桔色成人.COM入口| 日韩操逼大片| 丁香五月婷婷香| 五月色网| 五月丁香五月综合欧美| 精品九九视频在线观看| 综合激情五月丁香| 天堂综合久| 97色色婷婷| 五月天啪啪| 天天日天天添| 狠狠五月激情丁香六月| 色亭亭九月| 丁香久久| 成人一级片| 天天色色婷婷| 婷婷伊在线| 97碰碰人人视频| 思思热在线视频精品| 婷婷五月天综合久久| 26uuu淫色| 狠狠色狠狠爱| 9色操| 丁香五月婷婷啪啪| 国产激情久久久| 婷婷丁香五月综合激情视频| 99热这只有| 国产成人AV在线播放| 国产日产亚洲系列最新| 开心五月激情网| 99综合网| 色综合色综合色综合色综合| 丁香五月天视频在线播放| 五月婷婷黄色| 99激情在线| 久9热插入| 久久这里有精品| 操逼巨乳91| 亚洲婷婷乱乱丁香| 丁香五月婷婷激情蜜桃| 国产婷婷色综合AV蜜臀AV | 午夜成人综合| 99爱精品| 五月天婷婷综合免费| 五月丁香六月激情综合啪啪| 琪琪理论片| 色一情一乱一乱一区91| 色婷婷中文在线| 五月婷婷综合成人| 亚洲岛国电影| 激情六月婷婷啪啪| 在线播放人妻| 亚洲无码 图片区| 婷婷欧美| 97碰在线视频| 538在线精品| 99久热这里只有精品| 99∨VTV| 激情婷婷网| 一根材五月婷成人| 亚洲五月天伊人| 噜噜噜噜婷婷五月天| 91九色精品| 色综啪啪啪啪啪啪| 97在线/日本| 丁香五月婷婷av影院| 伊人婷婷五月天| 婷婷综合精品| 夜夜爽天天爽| 无码日本精品XXXXXXXXX| 99视频自拍| 婷婷五月天伊人网| 婷婷中文字幕| 操大屄五月天视频| 色偷偷人人| 精品99*| 美女久久天堂| 极品九九九九九九| www.婷婷亚洲基地| 超碰成人免费| 色天天狠狠干| 丁香综合网| 婷婷色丁香五月| 五月丁香六月婷精品视频| 亚洲激情五月婷婷日日| 99热99热不卡| 五月婷婷激情性爱| 狠狠干综合| 五月激情综合网| 久热只有精品| www.9操| 狠狠干.com| 色图亚洲91| av在线免费播放观看| 色婷婷无吗| 激情丁香五月AV| 一操久久| 激情五月婷婷免费视频| 99热这里只有精品5| 欧美日韩婷婷五月天| 思思久久99热只有频精品66| 日本在线观看aaa 99| 六月丁香天堂| 人人爱操| 涩涩涩.com| 五月天婷婷在线播放| 婷婷五月天在线观看| 亚洲在线综合| 最近中文字幕在线中文视频| 九九视频在线观看视频在线播放69| 九热视频免费观看| 色五月婷婷中文字幕| 天天操夜夜夜夜爽| 婷婷激情视频欧美视频自拍视频欧美剧 | 日本久久9| 色综合九九色综合88| 99热r| 五月丁香在线国产 | 欧美五月婷婷| 99热这里只有精品8| 青青草免费公开视频| 伊人婷婷大香蕉在线| www.激情五月天.con| 婷婷五月天AV在线| 青青热久精品视频在线观看| 深爱五月激情五月| 99色视频| 婷婷内射视频在线| 五月天婷婷开心| 久久人妻久久| 99热伊人| 91色在线| 五月丁香婷中文字幕| 色婷婷婷婷| 成人av免费观看| 在线播放人妻| 99色综合网| 久久99这里只有精品视频| 开心激情五月天网| 色色网站毛片| 激情综合5| 天天综合网亚洲综合网| 99热这里只有精品16| 色欲五月丁香| 九玖视频这里只有精品| 五月天天视频| 色啦啦视频| 伊人久久大香线蕉av最新| anquye伊人| 天天操屄网| 天天玩夜夜操| 97干在线看| 天天粽合合合合| 女人被男人吃奶到高潮| 性爱激情五月| 亚洲视频在线观看99| 丁香五月电影| 激情五月丁香六月综合AVXXXX| 日日噜噜夜夜狠狠久久丁香六月| 日韩成人电影Av| 婷婷爱在线观看| 99re思思热久久| 丁香五月人妻| 婷婷丁香花五月天| 色色色色色色网站| 大香伊人久色| 五月婷婷丁香伦理网| 99激情| 人妻激情久久| 天天天天天操| 狠狠精品干练久久久无码中文字幕 | 五月婷婷综合激情| 狠狠爱综合网| 五月婷婷久久大香蕉| 五月婷婷激情综合视频| 99干日日干| 久久香蕉影院| 99热e| 婷婷丁香五月在线观看91| 丁香五月综合激情久久潮喷| 久久99网站| 久久一级免费黄色片| 天天操天天操| 图片区 小说区 区 亚洲五月| 丁香六月婷婷开心| 婷婷综合色图| 色综合天堂| 婷婷香五月天| 婷婷五月天首页激情| 天天射天天射一道本日本社区| 五月天婷婷在线观看| 激情综合婷婷久久| 色色日本| 精品亚洲国产成AV人片传媒| 色婷婷日本| 亚洲视频在线网| 日夜夜天天| 欧美人与性动交CCOO| 欧美日韩一a.无| 色色五月天网站| 色色网91| 久久色亭亭五月天| 九九综合色综合| 青青草成人网| 六月丁香狠狠爱| 亚洲AV色婷婷人禽五月天| 青青久久五月| 丁香六月婷婷姐网| 久久性爱激情| 亚洲无码yw| 久久超级碰视频| 亚洲av成人在线| 欧美色色色色色色| 天堂久久精品| 天天噜噜| 综合在线丁香五月| 五月婷婷啪啪啪啪| 亚洲狠狠狠| 伊人丁香在线| 婷香五月激情视频| 丁香五月网址| 伊人激情影院| www.五月婷婷久久.com| 999热在线观看视频| 五月天成人在线播放丁香| 色九月综合| 99热国产这里只有精品| 97香蕉久久超级碰碰高清版 | 懂色av蜜臀av粉嫩av永陈冠希| 日欧大屏操| 99久久精品国产色欲| 婷婷丁香五月网| 玖玖精品婷婷| 996er热| 熟女激情网| 欧类av怡春院| 五月丁香六月婷婷欧美综合| 九九九九综合| 国产午夜精品一区二区三区嫩草| 麻豆五月丁香婷婷| 婷婷性爱视频在线| 99日逼视频| wwccc久久久| 日韩精品AV一区二区三区| 日本天天综合| 久久婷婷综合色丁香| 九九热re99re6在线精品| 婷婷丁香激情综合色情| 少妇性按摩无码中文A片| 国精产品久久| 99这里有精品视频| 激情五月天电影| 538任你爽视频不一样的| 亚洲1区| 五月丁香六月婷婷,婷| 伊人在线视频| 日本丁香五月| 色欲婷婷夜夜| 日本少妇AA一级特黄大片| 久久精品99| 久久这有这里精品| 久久婷婷五月综合色丁香| 色综合网址| 五月婷婷播| 在线亚洲综合网| www.五月天色色.com| 久久五月六月| 天天透天天干| 国产精品成人在线| 亚洲成人五月| se色99| 九九色插| 五月天国产| 五月色丁香激情| 99视频在线观看网址| 久久538| 深爱五月婷| 久久婷婷色情7777网站| 五月丁小婷婷激情四射| 亚洲视频99| 天天爽夜夜爽| 夜夜涩涩涩| 大香蕉久久久久久久久| 国产伦亲子伦亲子视频观看 | 996热| 79色色色色| 五月婷婷成人| 成人精品视频99在线观看免费| 色人久久| 五月天婷婷成人网| 极品人妻videosss人妻| 婷婷激情四射| 九月激情综合婷婷| 色五月丁香91| 人人播| 99热99热在线| 玖玖精品视频99| 婷婷丁香宗合888| 射婷婷中文字幕| 亚洲AV网站在线观看| 天天爽天天透天天爱| 91无码视频| 色婷婷五月天av在线| 色婷婷久久综合| 五月天六月婷| 九九热这里只有精品12| 六月色婷婷色| www色五月| 伊人成综合五月婷婷| 久久98| 亚洲综合草草| 99热97| 3p日韩网站视频| 99无码视频| 丁香婷婷老司机久操| 亚洲亚洲人成综合网络| www.夜夜操.com| 激情丁香五月| 天天干天天干天天干天天干天天干| 久久伊人日日夜夜| 五月婷免费视频久久久| 五月色丁香综合| 91精品婷婷国产综合久久| 亚洲第一影院高清无码网站| 影音先锋男人av资源站| 婷婷五月天桃花网| 密着浓厚中出乚交尾GvG935| 777精品久无码人妻蜜桃| 国产激情久久久| 激情98色婷婷五| 中文av网| 99精品久久| 五日激情综合| 99热在线观看精品| 韩国天天婷婷| 激情五月天在线视频| 热的无码综合视频| 色五月婷婷天天操夜夜操| 婷婷五月激情六月丁香| 欧美日韩大黄| 99热这里只有精品一| 丁香五月亭亭六月综合激情网| 影音先锋按摩| 欧美噜噜久久久XXX| 亚洲99综合| 婷婷欧美激情| 91无码高清| 综合精品99| 九九色情网五月天| 操操熟女| 久草丁香婷婷五月天婷| 9久国产| 丁香五月人妻| 国产精品久久久久久白浆色欲| 9久热在线视频精品| 丁香五月综合激情性爱| 啪啪激情网| 日韩久久视频| 婷婷基地成人五月天| 激情六月下句是什么| 日本色噜| 五月婷婷插一插| 五月天激情日色在线| 色五月涩涩婷婷| 婷婷色五月在线视频| 精品亚洲VA网站| 久久九九免费视频| 丁香五月91| 成人网站在线观看视频| 99熟女| 日日日日日| 蜜臀AV在线观看| 久久er99热精品一区二区| 欧美三9久九观看| 好叼操在线观看| 狠狠爱丁香婷| 97碰碰视频| 五月丁香六月综合基地| 欧亚色色| 色婷婷五月天堂资源| 五月天色婷婷成人| 色色丁香婷婷| 亚洲乱码日产精品BD| 韩国中文字幕91| 九九九九无码| 六月丁香啪啪| 婷婷激情五月综合丁| 丁香六月婷婷综合在线| 婷婷月综合| www.婷婷五月天| 国产JK精品白丝AV在线观看| 婷婷香蕉视频| 欧亚色色| 十月丁香九月婷婷综合| 久99久在线| www.99热| 综久久久| 1024人妻| 99国产小视频| 狠狠干婷婷| 99精品成人无码A片观看金桔| 日碰日| 国产无人区大片| 天天操天天日天天爱| 婷婷六月色情| 在线观看中文字幕亚洲| 亚洲成人在线观看av| 大香蕉欧美在线| 99爱视频精品在线观看| 99在线小视频| 六月激情网| 丁香六月激情国产| 色欲操| 99热首页| 青草视频在线观看视频| 五月丁香激| 米奇激情婷婷| 久久新地址| 中日韩美欧成人一区二区精品在线| 一起草av在线观看| 亚洲AV激情五月综合网| 国产精品美女| www免费在线视频| 91偷拍视频| 99热这里只有精品无码| 色爱亚洲| 五月天之色情综合网| 91se精品国产| 99黄色性生活| 九九性视频| 六月丁香久久| 超碰com| 欧美激情五月| 亚洲色婷婷| 日本久久人| 激情五月色综合国产精品| 人妻激情在线| 久久亭亭电影| 97色色色色色色色色色色色色色| 91狠狠综合久久久| 午夜色丁香| 丁香婷五月天| 丁香六月婷婷色XXXXX| 丁香久久激情俄| 五月天另类综合网| 婷婷丁香五月综合| 久Se视频在线观看| 天天日本夜夜谢| 成人综合网站| 五月天婷婷基地丁香| 超碰97免费在线| 九九精品丁香花| 丁香色啪综合| 五月婷婷久久综合| 91人人操人人| 亚洲网站999| 综合另类激情| 天天综合亚洲综合| 婷婷五月花| 无码激情| 狠狠色狠狠| 丁香激情五月少妇| 五月天久久综合婷婷丁香| 国产精品久久久久久久久久| 99热九九这里只有精品| 在线婷婷| 青青草原亚洲天堂| 99热日| 日韩AV在线电影| 思思精品久久艹| 噼里啪啦在线观看免费完整版视频| 九九久久99| 伊人超碰| 人人97碰| www色婷婷| 991精品在线视频| 涩涩涩五月天| 激情五月综合网最新| 九色地址91视频| av五月天婷婷丁香| 99在线看视频| 五月婷婷说| 丰滿爆乳一区二区三区| 国模淫穴色图| 色啪久 | 海外网站专业操老外| 看久久性爱视频| 青青草大香| 丁香五月狠狠综合欧美| 久久精品一区二区三区四区| 五月婷综合性中心| 伊人婷婷五月天| 亚洲有码在线视频| xx久久| 日本99在线| 99九九在线视频| 国产超碰人人| 五月天久久婷婷| 五月天色色网站| 91ncom.色| 狠狠综合网| 99热综合| 久久性爱视频免费| 亚洲字幕AV一区二区三区四区| 丁香婷婷久久激情| 在线视频色五月| 五月丁香狠狠爱婷婷综合| 五月婷婷激情综合网| 色婷婷丁香五月天| 色一情一乱一伦一区二区三区| 五月婷婷六月丁香综合视频在线| 91 影音先锋| 色5月婷婷| 五月婷av| 97在线/亚洲| 色婷婷电影| 亚洲精品久久久久久久久久吃药 | 激情网第四色| 99热每日| 色婷婷超碰| 婷婷五月天成人导航| 91综合在线| 亚洲性图一区二区| 午夜丁香 婷婷| 99人妻碰碰碰久久久久禁片| 激情欧美婷五月| 久久曰9| 日本色五月婷婷| 久久久ww| 乱精品一区字幕二区| 开心激情网五月| 六月婷婷香蕉| 色婷婷电影网| 九九这里都是精品| 日本精品在线噜噜噜| 少妇性BBB搡BBB爽爽爽视頻| 十月色综合| 天天色图| 成人龟情网丁香五月| 激情六月天| 永久思思热在线| 五月天丁香久久综合| 日韩成人AV在线播放| 99热这里只有精品21| 婷婷丁香精品视频在线观看| 久久99久久久久久| 婷婷精品综合| 色吧五月| 五月天综合在线观看视频| 丁香成人五月天| 开心色色五月天综合| 91干视频| 狠狠色噜噜狠狠狠888了| 久久人人九| 色婷婷丁香五月| 五月婷婷六月丁香在线| 色九月| 久久久GOGO无码啪啪艺术| 色色色色色色色色色色色色色色,网站| 69久久99精品久久久久婷婷| 99久久户外勾搭| 日韩啪| 99视频这里只有久久精品| 婷婷射综合| 日本eVa一区=区视频| 五月婷精品| 五月之婷婷| 久久黄A片| 亚洲天堂有码| 丰满少妇猛烈A片免费看观看| 曰曰久久| 亚洲精品大片| www.伊人天堂偷偷婷婷| 久99久在线| 色婷婷aV四虎| 情欲禁地| A久久| 深爱五月天| 五月天电影网| 丁香五月婷婷亚洲色图| 九九99热| 人操91在线| 国产肥白大熟妇BBBB视频| 五月婷婷影院| 99热这里是精品| 五月丁香欧美| 日韩抽插操逼| 午夜色婷婷| 激情五月婷婷视频一区二区三区| 精品99*| 国产精品a无线| 九九综合久久| 婷婷97碰碰| 日日夜夜狠狠操| 99色1| 婷色人人狠| 婷婷五月丁香综合激情| 婷婷久久图片| 五月婷视频在线观看| 字幕网AV中文字幕| 丰满老熟妇BBBBB搡BBB| 深爱激情五月网| 伊人网大香| www.99热| 天天舔天天爽| 九九在线精点品| 久久五月天色| 天天日,天天射,天天舔| 欧美性爱5月天天天看| 欧美综合激情五月丁香| 日本美女天天日天天爽| 五月丁香久久网| www.久久| 中文网AV| 五月激情五月丁香| 狠色综合网| 99久久综合| 婷婷月综合| 久久九精品| 看黄的网站18禁| 超碰不卡在线| 91疯狂操操操操| 婷婷自拍| www.com色播五月天| 伊人大香久久| 99视频在线啪| 激情伊人网| 久久婷婷丁香五月宗合| 五月丁香久久呀| 丁香 久久| 非洲一级AV| 操操天堂| 五月丁香激情啪啪| 色综合色综合婷婷热| 99这里只有精品视频免费| 五月色视频| 久热2025无码| 国熟女视频| 五月婷婷丁香五月婷婷| 啪到高潮激情丁香五月| 激情综合网五月婷婷| 久久99精品久久久久久三级| 色九月婷婷综合| 中文字幕在线免费观看视频| 日日噜噜夜夜狠狠久久丁香六月| 97色碰| 亚洲国产精品二二三三区| 又大又粗九一在线| 五月婷婷 自拍| 激情图片婷婷丁香五月| av在线观看免费| 亚洲成人色五月天| 久噜久噜| 俺去也五月| 91大神操美女| 91九九| 丰滿爆乳一区二区三区| 久久99久久久| 色色丁香| 婷婷天天综合| 五月婷婷之婷婷| 亚洲六月婷婷| 国产成人片| 91精品久| 中文字幕av在线| 亚洲天天免费| 色爱五月天| 天天色播| 丁香五月天AV在线 | 丁香久月| 色情综合| 中文字幕av网站| 天天操无码| 激情五月丁香色婷婷| 桔色成人在线| 日韩1区2区| 激情五月四色| 26uuu丁香婷婷五月| 爱之国产色情综合| 色中色综合| 婷婷五月天小说网| 狠狠色婷婷综合开心影视| 国产ava| 五月丁香综合伦理片| 激情綜合W W W,激情五月天| 99视频内射三四| 这里只有精品96| 色五月婷婷综合在线| 九九99视频精品| 97色色综合| 婷婷激情综合| 久热天堂| 婷丁五月| 五月丁香六月婷婷色日| 精品夜夜澡人妻无码AV| 91人操人人人操人| 玖久精品视频9| 99热老网站| 91久久国产自产拍夜夜91久久精品文字>91麻豆精品国产 | 超碰丁香五月| 久热这里只有精品在线观看| 天天做天天爱天天综合网| 99综合视频| 91久久国产综合久久| 色久婷婷五月| 五月天天久久香| 欧美成人AAA片一区国产精品| 五月丁香成年黄色| 久久久区区一久久久久久| 亚洲高清在线| 久久码久久无清| 97久久香草精品视频| 亚洲综合色色| 色色综合院| www.日韩艹| 婷婷色情网| www91色网站| 婷婷色播色五月五色五月天色妇| 97色色网| 色婷婷五月丁香色| 五月丁香亭亭成人电影| 丁香五月天黄色片| 91亚洲免费片| 国产精品蜜臀99| 精品乱码久久久久| 久久视频婷婷| 色五开心五月五月深深爱| 亚洲第一综合| 97碰在线视频| 国产无人区大片| 超碰A V在线| 亚洲十月婷婷综合| 狠狠干综合| 久热伊人| 超碰在线人人| 婷婷五月丁香欧洲| 五月激情婷婷在线| 五月婷A V在线| 都市激情蜜桃婷婷五月天| 91男同| 婷婷五月天黄色网址| 岛国AV网| chaopeng在线人人| 色婷婷五月婷婷五月婷婷五月| 五月天婷婷久久| 精品成人久久久久久久_一二三四视| 色五月婷婷色五月婷婷色五月婷婷| 成人国产综合| 婷婷五月天开心激情网| 亚洲乱码日产精品BD| .操區COm| 狠狠干夜夜干| 久久婷婷五月| 操91| 久久久999精品| 丁香五月人妻| 97色啪| 婷婷五月天基地| 色欲色香综合网站| 狠狠色噜噜| 色五月丁香com| 996er在线观看| 91视频一起草| 91精品久久久久久久久| 精品人妻久久久久久| 玖玖综合玖玖| 五月丁香六月婷婷姐| 一级黄色操B| 色五月天成人| 碰人人操| 婷婷五月天视频| 久七香蕉| 亚洲人人操| 日韩99视频| 色噜噜97视频在线观看| 久久婷婷网站| 激情综合区| 久久伊人婷婷| 能看的av网站| 六月婷婷狠狠| 色色欧美色色| 丁香五月欧美激情| 国产成人亚洲综合亚洲| 激情五月婷黄版| 欧美色色色色色色色| 丝袜大香蕉| 最新日本A片| 亚洲亚洲人成综合网络| 激情五月天网页| 激情久久丁香| 棕合影院色色| 欧美日韩成人| 五月六月丁香婷婷在线观看| yazhoujiqingav| 亚洲色婷婷视频| 亚洲无码激情| 超碰99久久| 99国产er热视频| AA片在线观看视频在线播放 | 97伊人综合婷婷| 国产九九一区二区三区| 超碰成人在线观看| 五月激情天| 玖玖资源天天无码| 日本天堂免费99| 99re免费精品视频| 五月色丁香综合| 五月丁香婷婷色啪| 久久久久久人妻| 九九伊人网| 先锋影音av色五月天资源站| 欧美Va日本Va| 男女99免费视频| 欧类av怡春院| 综合网亚洲| 婷婷色导航| 9色91视频| 激情五月天小说网| 欧美激情丁香五月| 国内一级片| 日日干日日| 天天射夜夜爽| 久久月天堂| 欧美日朝成人| 色99综合视频| 婷婷五月天综合久久| 五月丁香色综合| 婷婷伊人五月天| 另类在线| 96精品久久久久久久久| 久久99视频| 欧美一区二区三区不卡影视| 中文在线成人| 99热这里只有精品9| www五月天激情com| 热久久91| 91九九九色在| 日韩久热| 三级大香蕉网| 亚洲五月天婷婷| 成人中文网| 色噜噜狠狠色综合网| 伊人天天色| 婷婷六月视频| 香蕉久久国产AV一区二区| 深爱五月婷婷| 日本婷婷丁香五月| 亚洲 视频 导航 一区| 国产古装妇女野外A片| 色九九九九| 亚洲色小说在线综合| 色女人久久| 婷婷.com| 可以直接看的av| 欧美成人网99网| 狠狠狠婷婷五月综合| 色99婷婷五月天| 黑人糟蹋人妻HD中文字幕| 综合XX网| 丁香五月综合在线播放| 日本 欧美在线| 在线亚洲综合网| 五月天综合在线| 熟女网站久久| 色婷五月天综合网| 激情婷婷五月女| 成人在线综合| 久久丁香综合精品综合| 天天干,噜噜色,狠狠色| 视频一二区| 国产性av| 99无码| www.yw色| 国产精品五月天婷婷| 色五月激情问网站| 996热re视频精品视频| 婷婷综合天堂| 丁香六月综合激情| 狠狠色婷婷777| 婷婷久久草| 丁香五月天堂网| 婷婷色狠狠| 激情丁香五月婷婷| 九月激情网| 久久色亭亭五月天| 久久人妻人人槡| 99在线观看视频精品| 日韩超碰在线| 色99无码| 成人AV片播放| 欧类av怡春院| 玖玖色综合| 婷婷亚洲天堂| 最新久久网址| 在线观看婷婷5月| 99视频在线精品免费观看2| 99re这里有精品手机在线| 99热日韩这里只有精品| 99超级碰免费视频| 亚洲无码成人| 色偷偷色婷婷| 婷婷爱五月| 色色色9 9 9| 婷婷五月日本| 久热99中文字幕| 精品久久久中文字幕大豆网推荐理由| 婷婷激情五月| 99无码视频| 国产欧洲欧洲精品久久| 情色五月天网站| 色婷久九| 色五月五月婷婷| 99热资源在线| 激情深爱五月天| 九九这里都是精品| www激情婷婷com| 色狠狠综合入口| 性生活久久人妻| www,婷婷五月天,com| 热久久66| 日日做天天操夜夜爽| 开心五月婷婷激情网| www.五月婷婷久久.com| 五月天自拍视频| 99热精品综合| 丁香五月av在线| 六月丁香五月激情婷婷| 久久精彩视频99| 色丁香久久久| 婷婷色爱| 六月色播| 天天爱综合网| 久久精品99久久久久久| 91成人视频| 丁香五月影院| 激情综合五| 婷婷精品视频| 五月色综合| 国产精品久久久爽爽爽麻豆色哟哟| 免费看欧美成人A片无码| 日韩精品视频中文字幕| 色婷婷中文| 久久久噜噜噜操操操| 婷婷之玖玖| 玖玖婷婷五月| 97操碰| 天天狠天天狠| 啄木鸟黑丝一区二区| 五月丁香六月停停停| 久久精品99久久久久久久久| www.97干视频| 新97人人上人人| 色婷婷婷av| 亚洲热综合网在线观看| 五月天六月婷| 99精品在线观看视频| 日日.c| 99热在线观看| 超级碰 久久9| 大香蕉中文| 人妻狠狠操| 视频这里只有精品16| 天天婷婷色六月| 色婷婷88| 久热9| 潘金莲AAAAAAAAAA| 97热九九| 久久最新色色色| 最新亚洲色色网| 六月丁香五月天| 99日韩| 国产婷婷色综合AV蜜臀AV| 色婷婷狠狠久久综合五月 | 欧美激情丁香五月天久久婷婷一区| 色婷婷五月婷婷五月婷婷五月| 婷婷五月天欧美| 狠狠丁香| 国产毛片精品一区二区色欲黄A片| 亚洲a片免费观看| 五月天激情久久| 99re思思精品视频在线观看| 五月激情久久综合网| 日本久热| 日本不卡一区二区三区| 日本专区久久| 久久婷婷丁香五月一二三| 性生活视频98791| 99九九精品视频| 精品夜夜澡人妻无码AV| 久久五月天激情婷婷| 色色操| 亚洲综合婷婷六月丁香五月| 超碰二区| 一级黄在线| 日韩欧美成人片| 色五月开心五月激情五月| 综合激情视频| 六月丁香久久| 色月丁| 亚洲性爱干干| 草综合14| 99无码视频| 97碰碰人人视频| 天天做综合| 夜夜爱网站| 99热这里都是精品| 99re热在线视频观看| www。88热在线视频免费观看| 亚洲视频99| 亚洲视频一区| 五月天三级久久| 天天做天天要天天爽| 丁香五月激情综合| 变态 另类 在线 | 久久伊人五月天| 综合九色| 色综合天天网| 噜噜噜狠狠色综| 亚洲在线网站| 激情q青青草在线婷婷| 丁香五月激情五月| 天天揷综合网| 国产伦理精品高清在线观看网站一区二区| 丁香六月无码播放| 天天天天操| www.久久久久久久| 色色综合网络| 亚洲V国产V欧美V久久久久久| 五月婷婷六月丁香| www.99热精品| 五月婷婷六月基地| 五月天色色色| 综合久久久| 综合一本道| 人妻体体内射精一区二区| 综合久久影院| 天天干天天干天天干天天干天| www.婷婷| 久99久视频| 久久这里只精品| 五月丁香六月激情| 99re在线观看视频| 激情综合五月| 久久加勒比| 九九亚洲视频| 99年操人人爽| 噜综合| 五月天色综合| 丁香九色不卡aaa| 在线A色| 五月丁香啪啪网| 五月丁香久久综合| www.色婷婷| 91亚洲视频| 五月婷婷伊人久久| 被男人添B超爽视频| 色噜噜狠狠色综| 婷婷五月大香蕉| 日韩成人综合| 操射国产日本| 激情九月婷婷九月| 色欲丁香久久| 无码少妇高潮喷水A片免费| 精品思思久久| 色婷婷综合视频| 天天色中文字幕女优AV| 丁香五色月婷婷网| 99精品热| 色八月婷婷| 九九热免费| 丁香五月欧美激情| 婷婷久久丁香五月| 玖玖婷婷色五月| 这里只有精品久久| 九九综合图片网| 亚洲视色| 婷婷六久久| 久久亚洲婷婷| 99只有精品9| 久久久久久综合五月婷婷| 中文字幕一色哟哟哟哟| 亚洲激情丁香五月基地| 亚洲精品国产熟女久久久| 色五月婷婷在线视频| 天天干天天做| ji'qing'luan'ren'lun| 国产精品久久久久久久久久免费| 天天综合干| 91色呦哟| 五月精品免费XXX| 婷婷五月激情基地| 天天夜夜六月丁香五月婷婷老师| 99九九这里有免费视频| A网在线欧洲| 中文字幕成人版| 色吧五月婷婷| 99er热精品视频| 日91高清无玛| 国产精品操| 91干| 性爱AV天堂| 搡BBBB搡BBB搡18| 伦99热| 九九热内射| 99热这里只有精品3| 精品亚洲日韩99欧美片| www.jiujiujiu| 九九色精品| 色色婷婷五月| 色婷婷丁香五月天激情综合网| 久久婷婷六月综合国际| 性色视频| 色播五月天婷婷老师| 丁香五月综合婷婷| 五月丁香在线视频观看| 黑人巨粗进入警花疼哭A片| 五月丁香婷婷中文网| 五月激情婷婷四射| 综合一区二区三区| 乱岳熟女50岁| 久久成人天| 日本九九九九九九| 欧美99热| 日韩狠狠色婷婷| 久碰久| 天天综合网网欲色| 91丁香婷婷综合资源| aaa久久| site:xmssd.com| 色伊人91在线视频| 成人无码髙潮喷水A片| 天堂婷婷五月在线| 男同91| 夜夜骑夜夜撸| 久天综合| 激情婷婷五月天| 丁香成人色情五月天| 九热视频在线精品15| 狠狠操综合| 丁香五月天激情网| 成人电影AV在线观看| 99爱在线视频| 亚洲日韩欧美综合VA| 久久九区| 超碰日韩人妻在线| 亚洲成人无码网站| 国内裸舞二区| 潮汕成人AV片在线| 久99视频| 五月天精品综合在线| 99精品视频在线| 久久综合丁香激情五月| 丁香六月中文| 色色网91| 五月天婷婷影院| 伊人久久五月天综合| 九色91视频| 疯狂做受XXXX高潮A片动画| 五月天色丁香| 丁香六月色香蕉视频| 日本A片一区| 五月丁香色婷婷| 综合久久人妻| 欧美日本VA| 1024在线观看免费视频| 婷婷五月综合在线| 99热中国| 综合玖玖性爱免费视频| 婷婷视频在线碰| 亚洲中文字幕网| 六月久久狠狠| 99色综合| 天天综合网色欲香| 中文字幕在线观看视频www| 99久久玖玖| 综合在线网| 伊人玖玖婷婷| 久久精品A片777777| 五月婷婷三级| 精品无码99| 五月色婷婷亚洲| 久婷自拍视频| 国产精品久久久久久久久久免费 | 婷婷五月丁香香蕉| 亚洲欧美一区二区三区四区爱爱动图| 丁香五月1页| 激情av网| 成人午夜天| 久久激情综合| 婷婷色正月| 天天爱天天做天天舔| 影音先锋91| 超碰操日| 婷婷99狠狠躁天天躁| 丁香五月最新地址| 青青草原福利在线| 日本的α片xxxwww| 99热在线精品观看| 亚洲一区二区 成人网站戴套| 亚洲婷婷五月天| 99在线热| 亚洲热热视频| 玖玖精品资源| 新久久五月天激情| 色综合中文| 婷婷五月色花丁香社区| 欧洲电影在线观看免费版英语版| 婷婷伊人网| 欧美性爱五月天| 成人色色视频| WWW.桔色成人.COM入口| 一起草av| 婷婷爱爱蜜臀天天操| 久久久色情| 六月婷综合| 亚洲V国产V欧美V久久久久久| 99精品在线观看| 99九九视频| 天天色天天操天天射| 色J香五月天|