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

Webpack 原理系列九:Tree-Shaking 實現原理

開發 前端
Tree Shaking 較早前由 Rich Harris 在 Rollup 中率先實現,Webpack 自 2.0 版本開始接入,至今已經成為一種應用廣泛的性能優化手段。

[[419584]]

一、什么是 Tree ShakingTree-Shaking

是一種基于 ES Module 規范的 Dead Code Elimination 技術,它會在運行過程中靜態分析模塊之間的導入導出,確定 ESM 模塊中哪些導出值未曾其它模塊使用,并將其刪除,以此實現打包產物的優化。

圖片

Tree Shaking 較早前由 Rich Harris 在 Rollup 中率先實現,Webpack 自 2.0 版本開始接入,至今已經成為一種應用廣泛的性能優化手段。

1.1 在 Webpack 中啟動 Tree Shaking

在 Webpack 中,啟動 Tree Shaking 功能必須同時滿足三個條件:

使用 ESM 規范編寫模塊代碼

配置 optimization.usedExports 為 true,啟動標記功能

啟動代碼優化功能,可以通過如下方式實現:

  • 配置 mode = production
  • 配置 optimization.minimize = true
  • 提供 optimization.minimizer 數組

例如:

  1. // webpack.config.js 
  2. module.exports = { 
  3.   entry: "./src/index"
  4.   mode: "production"
  5.   devtool: false
  6.   optimization: { 
  7.     usedExports: true
  8.   }, 
  9. }; 

1.2 理論基礎

在 CommonJs、AMD、CMD 等舊版本的 JavaScript 模塊化方案中,導入導出行為是高度動態,難以預測的,例如:

  1. if(process.env.NODE_ENV === 'development'){ 
  2.   require('./bar'); 
  3.   exports.foo = 'foo'

而 ESM 方案則從規范層面規避這一行為,它要求所有的導入導出語句只能出現在模塊頂層,且導入導出的模塊名必須為字符串常量,這意味著下述代碼在 ESM 方案下是非法的:

  1. if(process.env.NODE_ENV === 'development'){ 
  2.   import bar from 'bar'
  3.   export const foo = 'foo'

所以,ESM 下模塊之間的依賴關系是高度確定的,與運行狀態無關,編譯工具只需要對 ESM 模塊做靜態分析,就可以從代碼字面量中推斷出哪些模塊值未曾被其它模塊使用,這是實現 Tree Shaking 技術的必要條件。

1.3 示例

對于下述代碼:

  1. // index.js 
  2. import {bar} from './bar'
  3. console.log(bar); 
  4.  
  5. // bar.js 
  6. export const bar = 'bar'
  7. export const foo = 'foo'

示例中,bar.js 模塊導出了 bar 、foo ,但只有 bar 導出值被其它模塊使用,經過 Tree Shaking 處理后,foo 變量會被視作無用代碼刪除。

二、實現原理

Webpack 中,Tree-shaking 的實現一是先「標記」出模塊導出值中哪些沒有被用過,二是使用 Terser 刪掉這些沒被用到的導出語句。標記過程大致可劃分為三個步驟:

  • Make 階段,收集模塊導出變量并記錄到模塊依賴關系圖 ModuleGraph 變量中
  • Seal 階段,遍歷 ModuleGraph 標記模塊導出變量有沒有被使用
  • 生成產物時,若變量沒有被其它模塊使用則刪除對應的導出語句

標記功能需要配置 optimization.usedExports = true 開啟

也就是說,標記的效果就是刪除沒有被其它模塊使用的導出語句,比如:

示例中,bar.js 模塊(左二)導出了兩個變量:bar 與 foo,其中 foo 沒有被其它模塊用到,所以經過標記后,構建產物(右一)中 foo 變量對應的導出語句就被刪除了。作為對比,如果沒有啟動標記功能(optimization.usedExports = false 時),則變量無論有沒有被用到都會保留導出語句,如上圖右二的產物代碼所示。

注意,這個時候 foo 變量對應的代碼 const foo='foo' 都還保留完整,這是因為標記功能只會影響到模塊的導出語句,真正執行“「Shaking」”操作的是 Terser 插件。例如在上例中 foo 變量經過標記后,已經變成一段 Dead Code —— 不可能被執行到的代碼,這個時候只需要用 Terser 提供的 DCE 功能就可以刪除這一段定義語句,以此實現完整的 Tree Shaking 效果。

接下來我會展開標記過程的源碼,詳細講解 Webpack 5 中 Tree Shaking 的實現過程,對源碼不感興趣的同學可以直接跳到下一章。

2.1 收集模塊導出

首先,Webpack 需要弄清楚每個模塊分別有什么導出值,這一過程發生在 make 階段,大體流程:

關于 Make 階段的更多說明,請參考前文 [萬字總結] 一文吃透 Webpack 核心原理 。

1.將模塊的所有 ESM 導出語句轉換為 Dependency 對象,并記錄到 module 對象的 dependencies 集合,轉換規則:

  • 具名導出轉換為 HarmonyExportSpecifierDependency 對象
  • default 導出轉換為 HarmonyExportExpressionDependency 對象

例如對于下面的模塊:

  1. export const bar = 'bar'
  2. export const foo = 'foo'
  3.  
  4. export default 'foo-bar' 

對應的dependencies 值為:

2.所有模塊都編譯完畢后,觸發 compilation.hooks.finishModules 鉤子,開始執行 FlagDependencyExportsPlugin 插件回調

3.FlagDependencyExportsPlugin 插件從 entry 開始讀取 ModuleGraph 中存儲的模塊信息,遍歷所有 module 對象

4.遍歷 module 對象的 dependencies 數組,找到所有 HarmonyExportXXXDependency 類型的依賴對象,將其轉換為 ExportInfo 對象并記錄到 ModuleGraph 體系中

經過 FlagDependencyExportsPlugin 插件處理后,所有 ESM 風格的 export 語句都會記錄在 ModuleGraph 體系內,后續操作就可以從 ModuleGraph 中直接讀取出模塊的導出值。

參考資料:

[萬字總結] 一文吃透 Webpack 核心原理

有點難的 webpack 知識點:Dependency Graph 深度解析

2.2 標記模塊導出

模塊導出信息收集完畢后,Webpack 需要標記出各個模塊的導出列表中,哪些導出值有被其它模塊用到,哪些沒有,這一過程發生在 Seal 階段,主流程:

  1. 觸發 compilation.hooks.optimizeDependencies 鉤子,開始執行 FlagDependencyUsagePlugin 插件邏輯
  2. 在 FlagDependencyUsagePlugin 插件中,從 entry 開始逐步遍歷 ModuleGraph 存儲的所有 module 對象
  3. 遍歷 module 對象對應的 exportInfo 數組
  4. 為每一個 exportInfo 對象執行 compilation.getDependencyReferencedExports 方法,確定其對應的 dependency 對象有否被其它模塊使用
  5. 被任意模塊使用到的導出值,調用 exportInfo.setUsedConditionally 方法將其標記為已被使用。
  6. exportInfo.setUsedConditionally 內部修改 exportInfo._usedInRuntime 屬性,記錄該導出被如何使用
  7. 結束

上面是極度簡化過的版本,中間還存在非常多的分支邏輯與復雜的集合操作,我們抓住重點:標記模塊導出這一操作集中在 FlagDependencyUsagePlugin 插件中,執行結果最終會記錄在模塊導出語句對應的 exportInfo._usedInRuntime 字典中。

2.3 生成代碼

經過前面的收集與標記步驟后,Webpack 已經在 ModuleGraph 體系中清楚地記錄了每個模塊都導出了哪些值,每個導出值又沒那塊模塊所使用。接下來,Webpack 會根據導出值的使用情況生成不同的代碼,例如:

重點關注 bar.js 文件,同樣是導出值,bar 被 index.js 模塊使用因此對應生成了 __webpack_require__.d 調用 "bar": ()=>(/* binding */ bar),作為對比 foo 則僅僅保留了定義語句,沒有在 chunk 中生成對應的 export。

關于 Webpack 產物的內容及 __webpack_require__.d 方法的含義,可參考 Webpack 原理系列六:徹底理解 Webpack 運行時 一文。

這一段生成邏輯均由導出語句對應的 HarmonyExportXXXDependency 類實現,大體的流程:

  1. 打包階段,調用 HarmonyExportXXXDependency.Template.apply 方法生成代碼
  2. 在 apply 方法內,讀取 ModuleGraph 中存儲的 exportsInfo 信息,判斷哪些導出值被使用,哪些未被使用
  3. 對已經被使用及未被使用的導出值,分別創建對應的 HarmonyExportInitFragment 對象,保存到 initFragments 數組
  4. 遍歷 initFragments 數組,生成最終結果

基本上,這一步的邏輯就是用前面收集好的 exportsInfo 對象未模塊的導出值分別生成導出語句。

2.4 刪除 Dead Code

經過前面幾步操作之后,模塊導出列表中未被使用的值都不會定義在 __webpack_exports__ 對象中,形成一段不可能被執行的 Dead Code 效果,如上例中的 foo 變量:

在此之后,將由 Terser、UglifyJS 等 DCE 工具“搖”掉這部分無效代碼,構成完整的 Tree Shaking 操作。

2.5 總結

綜上所述,Webpack 中 Tree Shaking 的實現分為如下步驟:

  • 在 FlagDependencyExportsPlugin 插件中根據模塊的 dependencies 列表收集模塊導出值,并記錄到 ModuleGraph 體系的 exportsInfo 中
  • 在 FlagDependencyUsagePlugin 插件中收集模塊的導出值的使用情況,并記錄到 exportInfo._usedInRuntime 集合中
  • 在 HarmonyExportXXXDependency.Template.apply 方法中根據導出值的使用情況生成不同的導出語句
  • 使用 DCE 工具刪除 Dead Code,實現完整的樹搖效果

上述實現原理對背景知識要求較高,建議讀者同步配合以下文檔食用:

  1. [萬字總結] 一文吃透 Webpack 核心原理
  2. 有點難的 webpack 知識點:Dependency Graph 深度解析
  3. Webpack 原理系列六:徹底理解 Webpack 運行時

三、最佳實踐

雖然 Webpack 自 2.x 開始就原生支持 Tree Shaking 功能,但受限于 JS 的動態特性與模塊的復雜性,直至最新的 5.0 版本依然沒有解決許多代碼副作用帶來的問題,使得優化效果并不如 Tree Shaking 原本設想的那么完美,所以需要使用者有意識地優化代碼結構,或使用一些補丁技術幫助 Webpack 更精確地檢測無效代碼,完成 Tree Shaking 操作。

3.1 避免無意義的賦值

使用 Webpack 時,需要有意識規避一些不必要的賦值操作,觀察下面這段示例代碼:

示例中,index.js 模塊引用了 bar.js 模塊的 foo 并賦值給 f 變量,但后續并沒有繼續用到 foo 或 f 變量,這種場景下 bar.js 模塊導出的 foo 值實際上并沒有被使用,理應被刪除,但 Webpack 的 Tree Shaking 操作并沒有生效,產物中依然保留 foo 導出:

造成這一結果,淺層原因是 Webpack 的 Tree Shaking 邏輯停留在代碼靜態分析層面,只是淺顯地判斷:

  • 模塊導出變量是否被其它模塊引用
  • 引用模塊的主體代碼中有沒有出現這個變量

沒有進一步,從語義上分析模塊導出值是不是真的被有效使用。

更深層次的原因則是 JavaScript 的賦值語句并不「純」,視具體場景有可能產生意料之外的副作用,例如:

  1. import { bar, foo } from "./bar"
  2.  
  3. let count = 0; 
  4.  
  5. const mock = {} 
  6.  
  7. Object.defineProperty(mock, 'f', { 
  8.     set(v) { 
  9.         mock._f = v; 
  10.         count += 1; 
  11.     } 
  12. }) 
  13.  
  14. mock.f = foo; 
  15.  
  16. console.log(count); 

示例中,對 mock 對象施加的 Object.defineProperty 調用,導致 mock.f = foo 賦值語句對 count 變量產生了副作用,這種場景下即使用復雜的動態語義分析也很難在確保正確副作用的前提下,完美地 Shaking 掉所有無用的代碼枝葉。

因此,在使用 Webpack 時開發者需要有意識地規避這些無意義的重復賦值操作。

3.2 使用#pure標注純函數調用

與賦值語句類似,JavaScript 中的函數調用語句也可能產生副作用,因此默認情況下 Webpack 并不會對函數調用做 Tree Shaking 操作。不過,開發者可以在調用語句前添加 /*#__PURE__*/ 備注,明確告訴 Webpack 該次函數調用并不會對上下文環境產生副作用,例如:

示例中,foo('be retained') 調用沒有帶上 /*#__PURE__*/ 備注,代碼被保留;作為對比,foo('be removed') 帶上 Pure 聲明后則被 Tree Shaking 刪除。

3.3 禁止 Babel 轉譯模塊導入導出語句

Babel 是一個非常流行的 JavaScript 代碼轉換器,它能夠將高版本的 JS 代碼等價轉譯為兼容性更佳的低版本代碼,使得前端開發者能夠使用最新的語言特性開發出兼容舊版本瀏覽器的代碼。

但 Babel 提供的部分功能特性會致使 Tree Shaking 功能失效,例如 Babel 可以將 import/export 風格的 ESM 語句等價轉譯為 CommonJS 風格的模塊化語句,但該功能卻導致 Webpack 無法對轉譯后的模塊導入導出內容做靜態分析,示例:

示例使用 babel-loader 處理 *.js 文件,并設置 Babel 配置項 modules = 'commonjs',將模塊化方案從 ESM 轉譯到 CommonJS,導致轉譯代碼(右圖上一)沒有正確標記出未被使用的導出值 foo。作為對比,右圖 2 為 modules = false 時打包的結果,此時 foo 變量被正確標記為 Dead Code。

所以,在 Webpack 中使用 babel-loader 時,建議將 babel-preset-env 的 moduels 配置項設置為 false,關閉模塊導入導出語句的轉譯。

3.4 優化導出值的粒度

Tree Shaking 邏輯作用在 ESM 的 export 語句上,因此對于下面這種導出場景:

  1. export default { 
  2.     bar: 'bar'
  3.     foo: 'foo' 

即使實際上只用到 default 導出值的其中一個屬性,整個 default 對象依然會被完整保留。所以實際開發中,應該盡量保持導出值顆粒度和原子性,上例代碼的優化版本:

  1. const bar = 'bar' 
  2. const foo = 'foo' 
  3.  
  4. export { 
  5.     bar, 
  6.     foo 

3.5 使用支持 Tree Shaking 的包

如果可以的話,應盡量使用支持 Tree Shaking 的 npm 包,例如:

  • 使用 lodash-es 替代 lodash ,或者使用 babel-plugin-lodash 實現類似效果

不過,并不是所有 npm 包都存在 Tree Shaking 的空間,諸如 React、Vue2 一類的框架原本已經對生產版本做了足夠極致的優化,此時業務代碼需要整個代碼包提供的完整功能,基本上不太需要進行 Tree Shaking。

本文轉載自微信公眾號「Tecvan」

 

責任編輯:姜華 來源: Tecvan
相關推薦

2021-06-28 07:01:50

Webpack 前端Tree shakin

2022-02-10 14:23:16

WebpackJavaScript

2021-09-13 09:40:35

Webpack 前端HMR 原理

2025-05-13 08:00:00

2021-05-31 05:36:43

WebpackJavaScript 前端

2020-08-05 08:21:41

Webpack

2021-06-28 05:59:17

Webpack 前端打包與工程化

2021-12-20 00:03:38

Webpack運行機制

2021-12-16 22:02:28

webpack原理模塊化

2021-04-19 10:45:52

Webpack熱更新前端

2025-01-13 00:00:00

2022-08-26 13:24:03

version源碼sources

2019-01-23 08:48:50

跨域協議端口

2021-12-15 23:42:56

Webpack原理實踐

2020-12-03 10:40:23

webpack加載原理前端

2023-04-11 08:00:56

Redis類型編碼

2017-07-11 13:58:10

WebSocket

2022-06-01 12:04:02

項目Webpack

2023-03-21 08:31:13

ReconcilerFiber架構

2021-12-19 07:21:48

Webpack 前端插件機制
點贊
收藏

51CTO技術棧公眾號

亚洲免费av片| 色综合视频一区二区三区高清| 成人字幕网zmw| 欧美成人精品欧美一| 欧美日韩一区二区三区四区不卡| 日本精品一区二区三区高清| 日韩人妻精品一区二区三区| 神马电影在线观看| 另类小说视频一区二区| 欧美精品久久久久久久| 级毛片内射视频| 日韩成人久久| 在线亚洲免费视频| 97免费视频观看| 国产精品99999| 国产99精品视频| 国产精品久久久久秋霞鲁丝 | www国产成人| 成人妇女淫片aaaa视频| 成人免费区一区二区三区| 国产精品99一区二区三| 国产午夜精品麻豆| 日本黄色www| 欧美日韩国产网站| 精品久久中文字幕久久av| 黄色a级在线观看| 黄色的视频在线免费观看| 国产成人午夜99999| 国产精品美女午夜av| 欧美福利视频一区二区| 欧美涩涩视频| 不卡av电影在线观看| jizz中文字幕| 亚洲精品无吗| 亚洲国产成人精品久久| 第一页在线视频| 亚洲免费一区| 欧美日韩国产综合一区二区三区| 黄色一级视频片| 不卡av免费观看| 一区二区三区免费网站| 免费观看国产视频在线| 麻豆传媒在线免费看| 国产欧美日韩视频一区二区| 欧美黄色直播| 青青草免费在线视频| www.亚洲国产| 久久99热只有频精品91密拍| 欧美一区二区三区激情| 成人av免费网站| 国产欧美精品一区二区三区| 蜜臀久久精品久久久久| 国产成人精品影视| 99热99热| 欧美一区二区黄片| 99久久国产综合精品色伊| 国产乱码精品一区二区三区中文| www视频在线| 国产成a人无v码亚洲福利| 91青青草免费观看| 亚洲av少妇一区二区在线观看| 国产成人免费网站| 成人在线资源网址| 黄色片一区二区三区| 成年人午夜久久久| 韩国成人一区| 男同在线观看| 欧美激情一区二区三区不卡| 亚洲激情啪啪| caopen在线视频| 亚洲妇熟xx妇色黄| 亚洲乱码中文字幕久久孕妇黑人| 日本精品不卡| 欧美日本一区二区三区四区| 无码人妻少妇色欲av一区二区| 亚洲天堂中文字幕在线观看| 亚洲精品第一国产综合精品| 精品人妻互换一区二区三区| 国产成人手机高清在线观看网站| 最近2019好看的中文字幕免费| 91香蕉一区二区三区在线观看| 国产精品黄色| 日本道色综合久久影院| 夜夜嗨aⅴ一区二区三区| 国产一区二区调教| 国新精品乱码一区二区三区18| 黄色在线播放| 亚洲欧美激情插| 成人性生活视频免费看| 日本肉肉一区| 欧美大片在线观看一区二区| 亚洲精品理论片| 97精品国产福利一区二区三区| 欧美高清电影在线看| 久久国产黄色片| 激情六月婷婷久久| 久久96国产精品久久99软件| 3p视频在线观看| 亚洲一级不卡视频| 国产aaaaa毛片| 7m精品国产导航在线| 亚洲视频在线观看| 日本中文字幕免费在线观看| 老鸭窝91久久精品色噜噜导演| 国产欧美精品在线播放| а√中文在线资源库| 久久久欧美精品sm网站| 91国在线高清视频| 亚洲综合av一区二区三区| 精品国内二区三区| 国产aaaaaaaaa| 一区二区福利| 99九九视频| 91高清在线视频| 亚洲福利视频三区| 中文字幕 欧美日韩| 久久超碰99| 97色在线观看| 亚洲成人第一区| 国产精品二区一区二区aⅴ污介绍| 老太脱裤让老头玩ⅹxxxx| 日韩一区二区三免费高清在线观看| 亚洲激情电影中文字幕| 永久看片925tv| 蜜臀av性久久久久蜜臀aⅴ四虎| 国产一区二区在线网站| 在线午夜影院| 9191久久久久久久久久久| 日韩人妻一区二区三区| 99精品国产99久久久久久福利| 亚洲aa中文字幕| 日本在线视频站| 欧美亚洲日本一区| 国精产品一区一区三区免费视频 | 久久久成人av| 中文字幕久久久久| 国产亚洲一区二区三区在线观看| 青青草视频在线免费播放 | 精品日产卡一卡二卡麻豆| 午夜激情视频在线播放| 日本视频免费一区| 久久久久一区二区| 多野结衣av一区| 精品粉嫩超白一线天av| 激情五月婷婷小说| 国产剧情一区二区| 粉嫩av一区二区三区天美传媒| av一级久久| 久久视频免费观看| 国产精品人人妻人人爽| 亚洲桃色在线一区| 天天影视色综合| 亚洲精品a级片| 91中文在线观看| 少妇av在线| 精品国产一区二区三区不卡| 国产va在线播放| 粉嫩蜜臀av国产精品网站| 人妻少妇精品久久| 红杏aⅴ成人免费视频| 国外色69视频在线观看| 网站黄在线观看| 一本大道久久a久久精二百| 欧美做受高潮6| 免费成人在线观看视频| 一区二区三区|亚洲午夜| 95精品视频| 欧美精品第一页在线播放| 午夜成人免费影院| 在线一区二区视频| 天天做夜夜爱爱爱| 国产成人免费视频网站| 日韩xxxx视频| 欧美精品系列| 亚洲一区二区少妇| 国产亚av手机在线观看| 亚洲三级 欧美三级| 在线观看免费视频a| 亚洲乱码一区二区三区在线观看| 中国特级黄色大片| 久久不射2019中文字幕| 亚洲视频欧美在线| 欧美久久一区二区三区| 91福利视频在线观看| av中文在线| 日韩一二在线观看| 亚洲高清毛片一区二区| 一色桃子久久精品亚洲| 99免费观看视频| 老牛影视一区二区三区| 99亚洲国产精品| 视频福利一区| 91久久在线视频| 欧美aa在线| 久久成人一区二区| 日本福利午夜视频在线| 欧美精品欧美精品系列| www成人在线| 亚洲欧洲色图综合| 亚洲av无码一区二区三区观看| 麻豆精品国产91久久久久久| 777av视频| 91中文字幕精品永久在线| 国产综合精品一区二区三区| 亚洲我射av| 欧美一级视频在线观看| 影音先锋男人在线资源| 亚洲一品av免费观看| 丰满大乳国产精品| 欧美日韩精品欧美日韩精品一| 中文字幕在线字幕中文| 亚洲丝袜精品丝袜在线| 免费a级黄色片| 国产成人日日夜夜| 色一情一区二区三区| 亚洲综合二区| 国产精品国产对白熟妇| 亚洲成人精选| 视频一区二区三| 日韩成人午夜| 国产精品免费一区二区| 亚洲伦理网站| 国产精品美女网站| 免费观看成人性生生活片 | 日韩一区视频在线| 你懂的在线观看| 精品无人国产偷自产在线| 国模无码一区二区三区| 欧美一区二区黄色| 一级α片免费看刺激高潮视频| 色悠久久久久综合欧美99| 日韩伦理在线视频| 一二三区精品福利视频| 国产suv精品一区二区68| 国产精品欧美极品| 日本xxxxxxxxx18| 久久精品人人做人人爽人人| 国产中文字幕一区二区| 成人免费视频播放| 美女流白浆视频| 国产成人鲁色资源国产91色综| 日本少妇激三级做爰在线| 狠狠色综合日日| 午夜免费福利视频在线观看| 免费观看成人av| 免费看涩涩视频| 青草国产精品久久久久久| 校园春色 亚洲色图| 男人的天堂久久精品| 亚洲人成无码www久久久| 日韩黄色在线观看| 天堂av在线网站| 麻豆精品在线播放| 老司机午夜性大片| 韩国毛片一区二区三区| 国产成人在线综合| 国产麻豆午夜三级精品| 久久久久亚洲av无码麻豆| 国产jizzjizz一区二区| 国产精品久久久久久亚洲av| 99精品热视频| 一区二区三区久久久久| 国产精品视频线看| 老司机成人免费视频| 亚洲三级在线看| 国产福利久久久| 一本大道久久a久久精二百| 国产精品成人久久久| 777奇米成人网| 免费观看成年人视频| 精品无码久久久久久国产| 成人免费高清在线播放| 久久夜色精品国产| 久久电影网站| 日韩av免费看网站| 国内自拍亚洲| av蓝导航精品导航| 青草久久视频| 亚洲一区二区自拍偷拍| 欧美视频在线观看| 91av俱乐部| 国产一区999| 不卡一区二区在线观看| 国产精品素人一区二区| 精品无码人妻一区二区三| 韩曰欧美视频免费观看| 一级aaaa毛片| 日韩成人激情在线| 日本网站在线免费观看视频| 欧美精品久久久久久久久| 51一区二区三区| 成人av电影免费| 精品久久久亚洲| 热久久最新网址| 丝袜美腿成人在线| 三级网站免费看| 日本一区二区三级电影在线观看| 久青草免费视频| 欧美午夜免费电影| 国产综合无码一区二区色蜜蜜| 伊人久久精品视频| 99热99re6国产在线播放| 国产精品视频不卡| 久本草在线中文字幕亚洲| 国产精品99久久久久久大便| 欧美资源在线| av av在线| 综合婷婷亚洲小说| 中文字幕在线观看视频免费| 日韩免费在线观看| 在线免费观看的av网站| 18久久久久久| 一区二区三区在线资源| 亚洲女人毛片| 午夜影院日韩| 91精品啪在线观看国产| 最近中文字幕一区二区三区| 日本中文字幕第一页| 欧美videofree性高清杂交| 天堂а√在线资源在线| 日产精品99久久久久久| 国产精品黄网站| 日韩人妻一区二区三区蜜桃视频| 久久综合综合久久综合| 高潮毛片无遮挡| 欧美性猛xxx| 午夜福利理论片在线观看| 久久久午夜视频| 日韩中文字幕| 国产免费xxx| 精品无人码麻豆乱码1区2区| www.日本高清视频| 在线视频国内一区二区| 青青操在线视频| 97超级碰碰碰| 亚洲盗摄视频| 欧美 国产 小说 另类| 成人sese在线| 国产一区二区三区影院| 精品国产123| 91在线三级| 国产一区二区不卡视频| 亚洲国产网站| 黄色国产在线观看| 天天综合日日夜夜精品| 色婷婷av一区二区三区之e本道| 欧美精品电影免费在线观看| 国产精品videossex| 一本久道高清无码视频| 成人午夜电影久久影院| 日本午夜精品理论片a级app发布| 亚洲国产三级网| 亚洲精品一区| 日本一区免费| 久久精品国产久精国产爱| 欧美激情精品久久久久久免费| 3d成人h动漫网站入口| 国产午夜精品久久久久免费视| 91在线高清视频| 亚洲视频久久| 在线观看国产三级| 日本乱人伦一区| 色综合久久影院| 97人人澡人人爽| 亚洲人www| 中国女人特级毛片| 欧美猛男gaygay网站| 亚洲欧美成人影院| 国产精品一区二| 久久天堂精品| 潘金莲一级黄色片| 日韩午夜小视频| 夜鲁夜鲁夜鲁视频在线播放| 亚洲国产精品久久久久婷婷老年| 国产一区二区三区观看| 国产一级做a爰片在线看免费| 精品亚洲国产视频| 欧美黄色a视频| 日本一级黄视频| 久久久精品中文字幕麻豆发布| 在线播放成人av| 国产69精品久久久久9999| 国产99久久| 色黄视频免费看| 日韩欧美中文第一页| 黄色动漫在线观看| 久久久久久九九| 九九精品视频在线看| 日本三级免费看| 日韩亚洲成人av在线| gogo人体一区| 999在线观看| 欧美日韩在线一区| 91亚洲天堂| 日韩精品电影网站| 成人久久18免费网站麻豆 | 久久91精品国产91久久小草| 国产在线观看99| 日韩有码在线视频| 丝袜美腿一区二区三区动态图|