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

ts-migrate:大規(guī)模遷移到 TypeScript 的工具

開(kāi)發(fā) 前端
在ts大量應(yīng)用在新項(xiàng)目,而對(duì)于js老項(xiàng)目維護(hù)卻日益艱難,在前端行業(yè)有很多人做過(guò)很多嘗試將js項(xiàng)目遷移到ts代碼。ts-migrate的出現(xiàn)在一定程度上,能夠幫助我們漸進(jìn)式遷移到ts,減少使用和開(kāi)發(fā)成本。

文章信息

原文地址:https://medium.com/airbnb-engineering/ts-migrate-a-tool-for-migrating-to-typescript-at-scale-cd23bfeb5cc

原文作者:Sergii Rudenko

本文譯者:一川

寫(xiě)在前面

TypeScript 是 Airbnb 前端 Web 開(kāi)發(fā)的官方語(yǔ)言。然而,采用 TypeScript 和遷移包含數(shù)千個(gè) JavaScript 文件的成熟代碼庫(kù)的過(guò)程并非一日之功。TypeScript 的采用經(jīng)歷了初始提議、多個(gè)團(tuán)隊(duì)采用、測(cè)試階段以及最終成為 Airbnb 前端開(kāi)發(fā)的官方語(yǔ)言的過(guò)程。您可以在 Brie Bunge 的這次演講中了解更多關(guān)于我們?nèi)绾未笠?guī)模采用 TypeScript 的信息。

遷移策略

大規(guī)模遷移是一項(xiàng)復(fù)雜的任務(wù),我們探索了從 JavaScript 遷移到 TypeScript 的幾個(gè)選項(xiàng):

混合遷移策略

逐個(gè)文件部分遷移,修復(fù)類型錯(cuò)誤,然后重復(fù),直到遷移完整項(xiàng)目。allowJS 配置選項(xiàng)允許我們讓 TypeScript 和 JavaScript 文件并排共存于項(xiàng)目中,這使得這種方法成為可能!

在混合遷移策略中,我們不必暫停開(kāi)發(fā),可以逐個(gè)文件逐步遷移。雖然,在大規(guī)模上,這個(gè)過(guò)程可能需要很長(zhǎng)時(shí)間。此外,還需要對(duì)來(lái)自組織不同部門的工程師進(jìn)行培訓(xùn)和入職培訓(xùn)。

全面遷移

獲取 JavaScript 或部分 TypeScript 項(xiàng)目并將其完全轉(zhuǎn)換。我們需要添加一些 any 類型和 @ts-ignore 注釋,以便項(xiàng)目編譯時(shí)不會(huì)出錯(cuò),但隨著時(shí)間的推移,我們可以用更具描述性的類型替換它們。

選擇 all-in 遷移策略有幾個(gè)顯著優(yōu)勢(shì):

  • 跨項(xiàng)目的一致性:整體遷移將保證每個(gè)文件的狀態(tài)相同,工程師無(wú)需記住他們可以在哪里使用 TypeScript 功能以及編譯器將在何處防止基本錯(cuò)誤。
  • 只修復(fù)一種類型比修復(fù)文件容易得多:修復(fù)整個(gè)文件可能非常復(fù)雜,因?yàn)槲募赡苡卸鄠€(gè)依賴項(xiàng)。使用混合遷移,很難跟蹤遷移的實(shí)際進(jìn)度和文件的狀態(tài)。

看起來(lái)整體遷移是這里的明顯贏家!

但是,對(duì)大型成熟代碼庫(kù)執(zhí)行全面遷移的過(guò)程是一個(gè)沉重而復(fù)雜的問(wèn)題。為了解決這個(gè)問(wèn)題,我們決定使用代碼修改腳本——codemods!通過(guò)我們最初手動(dòng)遷移到 TypeScript 的過(guò)程,我們認(rèn)識(shí)到可以自動(dòng)化的重復(fù)操作。我們?yōu)檫@些步驟中的每一個(gè)都制作了代碼模塊,并將它們組合到總體遷移管道中

根據(jù)我們的經(jīng)驗(yàn),并不能 100% 保證自動(dòng)遷移會(huì)產(chǎn)生完全沒(méi)有錯(cuò)誤的項(xiàng)目,但我們發(fā)現(xiàn)下面概述的步驟組合為我們提供了最終遷移到無(wú)錯(cuò)誤 TypeScript 的最佳結(jié)果項(xiàng)目。使用 codemods,我們能夠在一天內(nèi)將包含 50,000 多行代碼和 1,000 多個(gè)文件的項(xiàng)目從 JavaScript 轉(zhuǎn)換為 TypeScript!

基于這個(gè)管道,我們創(chuàng)建了一個(gè)名為“ts-migrate”的工具:

圖片

在 Airbnb,我們將 React 用于我們前端代碼庫(kù)的重要部分。這就是為什么 codemods 的某些部分與基于 React 的概念相關(guān)。ts-migrate 可以通過(guò)額外的配置和測(cè)試與其他框架或庫(kù)一起使用。

遷移過(guò)程的步驟

讓我們來(lái)看看將項(xiàng)目從 JavaScript 遷移到 TypeScript 所需的主要步驟以及這些步驟是如何實(shí)現(xiàn)的:

1、每個(gè) TypeScript 項(xiàng)目的第一部分是創(chuàng)建一個(gè) tsconfig.json 文件,如果需要可以通過(guò)ts-migrate執(zhí)行此操作。有一個(gè)默認(rèn)的配置文件模板和一個(gè)驗(yàn)證檢查,可以幫助我們確保所有項(xiàng)目的配置一致。

這是基本級(jí)別配置的示例:

{
  "extends": "../typescript/tsconfig.base.json",
  "include": [".", "../typescript/types"]
}

2、tsconfig.json 文件就位后,下一步是將源代碼文件的文件擴(kuò)展名從 .js/.jsx 更改為 .ts/.tsx 。此步驟的自動(dòng)化非常簡(jiǎn)單,而且還消除了大量手動(dòng)工作。

3、下一步是運(yùn)行 codemods!我們稱它們?yōu)椤安寮薄s-migrate 的插件是代碼模塊,可以通過(guò) TypeScript 語(yǔ)言服務(wù)器訪問(wèn)其他信息。插件將字符串作為輸入并生成更新的字符串作為輸出。jscodeshift、TypeScript API、字符串替換或其他 AST 修改工具可用于為代碼轉(zhuǎn)換提供動(dòng)力。

在每個(gè)步驟之后,我們檢查 Git 歷史記錄中是否有任何待處理的更改并提交它們。這有助于將遷移拉取請(qǐng)求拆分為更易于理解的提交,還可以跟蹤文件重命名。

我們將 ts-migrate 分成 3 個(gè)包:

  • ts-migrate[https://github.com/airbnb/ts-migrate]
  • ts-migrate-server[ter/packages/ts-migrate-server]
  • ts-migrate-plugins[https://github.com/airbnb/ts-migrate/tree/master/packages/ts-migrate-plugins]

通過(guò)這樣做,我們能夠?qū)⑥D(zhuǎn)換邏輯與核心運(yùn)行器分開(kāi),并為不同的目的創(chuàng)建多個(gè)配置。目前,我們有兩個(gè)主要配置:migration 和 reignore 。

雖然遷移配置的目標(biāo)是從 JavaScript 遷移到 TypeScript,但 reignore 的目的是通過(guò)簡(jiǎn)單地忽略所有錯(cuò)誤使項(xiàng)目可編譯。當(dāng)代碼庫(kù)很大并且正在執(zhí)行以下任務(wù)時(shí),Reignore 很有用:

  • 升級(jí) TypeScript 版本
  • 對(duì)代碼庫(kù)進(jìn)行重大更改或重構(gòu)
  • 改進(jìn)一些常用庫(kù)的類型

這樣,即使有一些我們不想立即處理的錯(cuò)誤,我們也可以遷移項(xiàng)目。它使 TypeScript 或庫(kù)的更新變得更加容易。

這兩個(gè)配置都在 ts-migrate-server 上運(yùn)行,它由兩部分組成:

  • TSServer :這部分與 VSCode 編輯器為編輯器和語(yǔ)言服務(wù)器之間的通信所做的非常相似。TypeScript 語(yǔ)言服務(wù)器的新實(shí)例作為單獨(dú)的進(jìn)程運(yùn)行,開(kāi)發(fā)工具使用語(yǔ)言協(xié)議與服務(wù)器通信。
  • 遷移運(yùn)行器:這部分運(yùn)行并協(xié)調(diào)遷移過(guò)程。

它需要以下參數(shù):

interface MigrateParams {
  rootDir: string;          // path to the root directory  
  config: MigrateConfig;    // migration config, including list of       
                            // plugins it contains
  server: TSServer;         // an instance of the TSServer fork
}

它執(zhí)行以下操作:

  1. 解析 tsconfig.json 。
  2. 創(chuàng)建 .ts 源文件。
  3. 將每個(gè)文件發(fā)送到 TypeScript 語(yǔ)言服務(wù)器進(jìn)行診斷。編譯器為我們提供了三種類型的診斷:semanticDiagnostics 、 syntacticDiagnostics 和 suggestionDiagnostics 。我們使用這些診斷來(lái)查找源代碼中有問(wèn)題的地方。基于唯一的診斷代碼和行號(hào),我們可以識(shí)別問(wèn)題的潛在類型并應(yīng)用必要的代碼修改。
  4. 在每個(gè)文件上運(yùn)行所有插件。如果文本因插件執(zhí)行而發(fā)生變化,我們會(huì)更新原始文件的內(nèi)容并通知 TypeScript 語(yǔ)言服務(wù)器文件已更改。

您可以在示例包或主包中找到 ts-migrate-server 用法示例。ts-migrate-example 還包含插件的基本示例。它們分為 3 個(gè)主要類別:

  • 基于js代碼轉(zhuǎn)化
  • 基于 TypeScript 抽象語(yǔ)法樹(shù) (AST)
  • 基于文本

存儲(chǔ)庫(kù)中有一組示例來(lái)演示如何構(gòu)建各種簡(jiǎn)單的插件并將它們與 ts-migrate-server 結(jié)合使用。以下是轉(zhuǎn)換以下代碼的示例遷移管道:

function mult(first, second) {
  return first * second;
}

into:

function tlum(tsrif: number, dnoces: number): number {
  console.log(`args: ${arguments}`);
  return tsrif * dnoces;
}

ts-migrate 在上面的例子中做了 3 次轉(zhuǎn)換:

  • 反轉(zhuǎn)所有標(biāo)識(shí)符 first -> tsrif
  • 添加類型到函數(shù)聲明 function tlum(tsrif, dnoces) -> function tlum(tsrif: number, dnoces: number): number
  • 插入 console.log(‘a(chǎn)rgs:${arguments}’);

生成插件

實(shí)際的插件位于一個(gè)單獨(dú)的包中 — ts-migrate-plugins。讓我們來(lái)看看其中的一些。我們有兩個(gè)基于 jscodeshift 的插件:explicitAnyPlugin 和 declareMissingClassPropertiesPlugin。jscodeshift 是一個(gè)可以使用 recast 包將 AST 轉(zhuǎn)換回字符串的工具通過(guò)使用函數(shù) toSource() ,我們可以直接更新文件的源代碼。

explicitAnyPlugin 背后的主要思想在于從 TypeScript 語(yǔ)言服務(wù)器中提取所有語(yǔ)義診斷錯(cuò)誤以及行號(hào)。然后,我們需要在診斷中指定的行上添加 any 類型。這種方法允許我們解決錯(cuò)誤,因?yàn)樘砑?any 類型可以修復(fù)編譯錯(cuò)誤。

使用前:

const fn2 = function(p3, p4) {}
const var1 = [];

使用后:

const fn2 = function(p3: any, p4: any) {}
const var1: any = [];

declareMissingClassPropertiesPlugin 使用代碼 2339 進(jìn)行所有診斷(你能猜出這段代碼的含義嗎?),如果它可以找到缺少標(biāo)識(shí)符的類聲明,插件將使用 any 類型注釋將它們添加到類主體中。顧名思義,這個(gè) codemod 只適用于 ES6 類。

下一類插件是基于 TypeScript AST 的插件。通過(guò)解析 AST,我們可以在源文件中生成一個(gè)包含以下類型的更新數(shù)組:

type Insert = { kind: 'insert'; index: number; text: string };
type Replace = { kind: 'replace'; index: number; length: number; text: string };
type Delete = { kind: 'delete'; index: number; length: number };

生成更新后,唯一剩下的就是以相反的順序應(yīng)用更改。如果通過(guò)這些操作的結(jié)果,我們收到新文本,我們將更新源文件。讓我們來(lái)看看其中幾個(gè)基于 AST 的插件:stripTSIgnorePlugin 和 hoistClassStaticsPlugin。

stripTSIgnorePlugin 是遷移管道中的第一個(gè)插件。它從文件中刪除所有 @ts-ignore 1 實(shí)例。如果我們將一個(gè) JavaScript 項(xiàng)目轉(zhuǎn)換為 TypeScript,這個(gè)插件將不會(huì)做任何事情。但是,如果它是部分 TypeScript 項(xiàng)目(在 Airbnb,我們有幾個(gè)項(xiàng)目處于這種狀態(tài)),這是必不可少的第一步。只有在刪除 @ts-ignore 注釋后,TypeScript 編譯器才會(huì)發(fā)出所有需要解決的診斷錯(cuò)誤。

const str3 = foo
  ? // @ts-ignore
    // @ts-ignore comment
    bar
  : baz;

轉(zhuǎn)換:

const str3 = foo
  ? bar
  : baz;

刪除 @ts-ignore 評(píng)論后,我們運(yùn)行 hoistClassStaticsPlugin 。該插件遍歷文件中的所有類聲明。它決定了我們是否可以提升標(biāo)識(shí)符或表達(dá)式,并決定一個(gè)賦值是否已經(jīng)被提升到一個(gè)類。

為了能夠快速迭代并防止回歸,我們?yōu)槊總€(gè)插件和 ts-migrate 添加了一系列單元測(cè)試。

React相關(guān)插件

reactPropsPlugin 將類型信息從 PropTypes 轉(zhuǎn)換為 TypeScript 道具類型定義。它基于 Mohsen Azimi 編寫(xiě)的出色工具。我們只需要在包含至少一個(gè) React 組件的 .tsx 文件上運(yùn)行這個(gè)插件。reactPropsPlugin 查找所有 PropTypes 聲明并嘗試使用 AST 和簡(jiǎn)單的正則表達(dá)式(如 /number/ 或更復(fù)雜的情況如 /objectOf$/ )來(lái)解析它們。當(dāng)檢測(cè)到 React 組件(功能組件或類組件)時(shí),它會(huì)轉(zhuǎn)換為具有新屬性類型的組件:type Props = {…}; 。

reactDefaultPropsPlugin 涵蓋了 React 組件的 defaultProps 模式。我們使用一種特殊類型來(lái)表示具有默認(rèn)值的props:

type Defined<T> = T extends undefined ? never : T;
type WithDefaultProps<P, DP extends Partial<P>> = Omit<P, keyof DP> & {
  [K in Extract<keyof DP, keyof P>]:
    DP[K] extends Defined<P[K]>
      ? Defined<P[K]>
      : Defined<P[K]> | DP[K];
};

我們?cè)噲D找到默認(rèn)的 props 聲明并將它們與上一步生成的組件 props 類型合并。

狀態(tài)和生命周期的概念在 React 生態(tài)系統(tǒng)中非常普遍。我們?cè)趦蓚€(gè)插件中解決了這些問(wèn)題。如果組件是有狀態(tài)的,則 reactClassStatePlugin 會(huì)生成一個(gè)新的 type State = any; 并且 reactClassLifecycleMethodsPlugin 會(huì)使用適當(dāng)?shù)念愋妥⑨尳M件生命周期方法。這些插件的功能可以擴(kuò)展,包括用更具描述性的類型替換 any 的能力。

對(duì)于狀態(tài)和道具,還有更多改進(jìn)和更好類型支持的空間。然而,作為一個(gè)起點(diǎn),這個(gè)功能被證明是足夠的。我們也不涉及 hooks,因?yàn)樵谶w移開(kāi)始時(shí)我們的代碼庫(kù)使用的是舊版本的 React。

確保項(xiàng)目編譯成功

我們的目標(biāo)是獲得一個(gè)具有基本類型覆蓋率的編譯 TypeScript 項(xiàng)目,不會(huì)導(dǎo)致應(yīng)用程序運(yùn)行時(shí)行為發(fā)生變化。

在所有轉(zhuǎn)換和代碼修改之后,我們的代碼可能具有不一致的格式并且一些 lint 檢查可能會(huì)失敗。我們的前端代碼庫(kù)依賴于 prettier-eslint 設(shè)置——Prettier 用于自動(dòng)格式化代碼,ESLint 確保代碼遵循最佳實(shí)踐。因此,我們可以通過(guò)從我們的插件運(yùn)行 eslint-prettier 來(lái)快速修復(fù)前面步驟可能引入的任何格式問(wèn)題。

遷移管道的最后一部分確保解決所有 TypeScript 編譯違規(guī)問(wèn)題。為了檢測(cè)和修復(fù)潛在的錯(cuò)誤,tsIgnorePlugin 使用行號(hào)進(jìn)行語(yǔ)義診斷,并插入帶有有用解釋的 @ts-ignore 注釋,例如:

// @ts-ignore ts-migrate(7053) FIXME: No index signature with a parameter of type 'string...
const { field1, field2, field3 } = DATA[prop];
// @ts-ignore ts-migrate(2532) FIXME: Object is possibly 'undefined'.
const field2 = object.some_property;

我們還添加了對(duì) JSX 語(yǔ)法的支持:

{*
// @ts-ignore ts-migrate(2339) FIXME: Property 'NORMAL' does not exist on type 'typeof W... */}
<Text weight={WEIGHT.NORMAL}>
  some text
</Text>
<input
  id="input"
  // @ts-ignore ts-migrate(2322) FIXME: Type 'Element' is not assignable to type 'string'.
  name={getName()}
/>

在注釋中包含有意義的錯(cuò)誤消息可以更輕松地解決問(wèn)題并重新訪問(wèn)需要注意的代碼。這些注釋與 $TSFixMe 2 相結(jié)合,使我們能夠收集有關(guān)代碼質(zhì)量的有用數(shù)據(jù)并識(shí)別代碼中可能存在問(wèn)題的區(qū)域。

最后但同樣重要的是,我們需要運(yùn)行 eslint-fix 插件兩次。在 tsIgnorePlugin 之前給定的格式可能會(huì)影響我們將在何處獲得編譯器錯(cuò)誤。在 tsIgnorePlugin 之后再次出現(xiàn),因?yàn)椴迦?@ts-ignore 注釋可能會(huì)引入新的格式錯(cuò)誤。

總結(jié)

我們的遷移故事正在進(jìn)行中:我們有一些遺留項(xiàng)目仍在使用 JavaScript,我們的代碼庫(kù)中仍然有大量的 $TSFixMe 和 @ts-ignore 評(píng)論。

圖片

然而,使用 ts-migrate 極大地加快了我們的遷移過(guò)程和生產(chǎn)力。工程師們能夠?qū)W⒂诰幋a優(yōu)化,而不是手動(dòng)逐個(gè)文件遷移。目前,我們的 600 萬(wàn)行前端 monorepo 中約有 86% 已轉(zhuǎn)換為 TypeScript,我們有望在年底前實(shí)現(xiàn) 95% 的轉(zhuǎn)換。

您可以查看 ts-migrate 并在 Github 存儲(chǔ)庫(kù)的主包中找到有關(guān)如何安裝和運(yùn)行 ts-migrate 的說(shuō)明。如果您發(fā)現(xiàn)任何問(wèn)題或有改進(jìn)的想法,我們歡迎您的貢獻(xiàn)!

非常感謝 Brie Bunge,他是 Airbnb TypeScript 的推動(dòng)者,也是 ts-migrate 的創(chuàng)建者。感謝 Joe Lencioni 幫助我們?cè)?Airbnb 采用 TypeScript 并改進(jìn)我們的 TypeScript 基礎(chǔ)設(shè)施和工具。特別感謝 Elliot Sachs 和 John Haytko 為 ts-migrate 做出的貢獻(xiàn)。感謝所有提供反饋和幫助的人!

Footnote

我們想記下我們?cè)诖诉^(guò)程中發(fā)現(xiàn)的一些關(guān)于遷移的事情,它們可能會(huì)有用:

  • TypeScript 3.7 版本引入了 @ts-nocheck 注釋,可以將其添加到 TypeScript 文件的頂部以禁用語(yǔ)義檢查。我們沒(méi)有使用這個(gè)注釋,因?yàn)樗安恢С?.ts/.tsx 文件,但它在遷移過(guò)程中也可以成為一個(gè)很好的中間階段幫手。
  • TypeScript 3.9 版本引入了 @ts-expect-error 注釋。當(dāng)一行以 @ts-expect-error 注釋為前綴時(shí),TypeScript 將禁止報(bào)告該錯(cuò)誤。如果沒(méi)有錯(cuò)誤,TypeScript 將報(bào)告不需要 @ts-expect-error 。在 Airbnb 代碼庫(kù)中,我們改用 @ts-expect-error 注釋而不是 @ts-ignore 。
  • @ts-ignore 注釋允許我們告訴編譯器忽略下一行的錯(cuò)誤。
  • 我們?yōu)?any 類型引入了自定義別名 — 和函數(shù)類型TSFixMeFunction = (…args: any[]) => any; 。盡管最佳實(shí)踐是避免使用 any 類型,但使用它可以幫助我們簡(jiǎn)化遷移過(guò)程并明確應(yīng)該重新訪問(wèn)哪些類型。

寫(xiě)在最后

在ts大量應(yīng)用在新項(xiàng)目,而對(duì)于js老項(xiàng)目維護(hù)卻日益艱難,在前端行業(yè)有很多人做過(guò)很多嘗試將js項(xiàng)目遷移到ts代碼。ts-migrate的出現(xiàn)在一定程度上,能夠幫助我們漸進(jìn)式遷移到ts,減少使用和開(kāi)發(fā)成本。

學(xué)而知不足,水平有限,還望諸君多多指教。覺(jué)得文章不錯(cuò)的讀者,不妨點(diǎn)個(gè)關(guān)注,收藏起來(lái)上班摸魚(yú)的時(shí)候品嘗。

責(zé)任編輯:武曉燕 來(lái)源: 宇宙一碼平川
相關(guān)推薦

2024-07-03 08:19:56

2020-11-30 11:06:30

云計(jì)算云遷移IT

2023-05-10 09:24:10

TypeScript工具

2025-06-10 08:15:00

LLM大語(yǔ)言模測(cè)試

2024-09-26 10:41:31

2023-02-06 10:29:36

CIO首席信息官

2023-05-09 18:45:28

監(jiān)控監(jiān)視工具

2023-11-22 09:27:15

數(shù)據(jù)遷移

2023-07-07 08:02:48

TypeScript編譯器文檔

2023-08-31 19:11:07

2023-06-05 14:09:49

云遷移

2017-05-08 14:56:07

開(kāi)源Prophet預(yù)測(cè)

2017-03-07 13:14:04

深度學(xué)習(xí)

2017-04-26 13:30:24

爬蟲(chóng)數(shù)據(jù)采集數(shù)據(jù)存儲(chǔ)

2016-01-29 20:23:23

華為

2009-04-09 09:32:00

VoWLANWLAN

2010-09-01 15:16:49

WLAN交換機(jī)結(jié)構(gòu)

2023-10-07 08:30:07

B+樹(shù)數(shù)據(jù)庫(kù)管理系統(tǒng)

2025-08-01 01:00:00

2023-06-30 17:59:27

Ray離線推理
點(diǎn)贊
收藏

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

国产日韩欧美一区二区| 久久影视免费观看| 一级片视频免费观看| 粗大黑人巨茎大战欧美成人| 国产不卡高清在线观看视频| 青青草精品毛片| 亚洲天堂网av在线| 丝袜美腿综合| 日韩一区二区中文字幕| 丰满人妻中伦妇伦精品app| 色三级在线观看| 成人h精品动漫一区二区三区| 国产精品国产福利国产秒拍| 久久综合综合久久| 日韩大片在线| 日韩国产中文字幕| 色偷偷中文字幕| 成人va天堂| 亚洲成av人在线观看| 伊人久久青草| 色资源在线观看| 国产一区二区在线看| 日本中文字幕久久看| 精品99久久久久成人网站免费| 成人短片线上看| 亚洲国产小视频| 亚洲欧美一区二区三区不卡| 欧美精品高清| 婷婷综合另类小说色区| 黄色录像特级片| 秋霞午夜在线观看| 国产女主播视频一区二区| 国产麻豆乱码精品一区二区三区 | 欧美一区二区三区免费在线看| 777久久久精品一区二区三区 | 五月婷婷狠狠干| 国产99久久久国产精品潘金网站| 国产视频999| 波多野结衣二区三区| 香蕉久久夜色精品国产| 国内精品久久久久久中文字幕 | 老司机午夜免费福利| 亚洲伊人精品酒店| 欧美日韩另类国产亚洲欧美一级| 97公开免费视频| 日韩电影av| 欧美日韩综合视频| 99精品人妻少妇一区二区| 毛片大全在线观看| 亚洲综合久久久| 狠狠干视频网站| 污片视频在线免费观看| 亚洲女子a中天字幕| 香蕉视频免费版| 麻豆影院在线| 亚洲欧美国产毛片在线| 99精品一级欧美片免费播放| 欧美69xxxx| 亚洲视频综合在线| 50度灰在线观看| 黄色大片在线播放| 亚洲欧美日韩在线| 国产91在线亚洲| 国产精品偷拍| 欧美色videos| 日日干夜夜操s8| 欧美高清一级片| 精品盗摄一区二区三区| 日本黄色动态图| 国产一区99| 精品国产网站地址| 久久久综合久久| 99热免费精品| 国产精品久久色| 91禁在线观看| 国产成人欧美日韩在线电影| 国模精品娜娜一二三区| 免费国产在线观看| 国产精品欧美久久久久一区二区| 日本老太婆做爰视频| 极品av在线| 欧美亚洲国产一区二区三区va| 中文字幕中文在线| 国产福利资源一区| 一区二区在线视频| 青青草激情视频| 亚洲一区二区三区高清| 国产精品久久久久久久午夜| 国产视频在线观看免费| xfplay精品久久| 在线国产伦理一区| 大桥未久在线视频| 欧美精品色综合| 91视频在线免费| 日韩久久久久| 国外成人在线视频| 亚洲天堂一二三| a在线欧美一区| 中文字幕色一区二区| 黄色软件视频在线观看| 欧美高清视频在线高清观看mv色露露十八 | 亚洲欧美精品suv| 黑鬼狂亚洲人videos| 另类亚洲自拍| 91手机在线视频| 91精品国产91久久久久游泳池 | 久久中文字幕免费| 国产在线视视频有精品| 日本成人看片网址| 久久一卡二卡| 欧美日韩不卡在线| 亚洲第一香蕉网| 禁久久精品乱码| 91亚洲精华国产精华| 黄色av网址在线免费观看| 夜夜爽夜夜爽精品视频| 超碰成人在线播放| 色综合综合网| 91黑丝高跟在线| www.超碰在线.com| 日韩美女视频19| 午夜免费一区二区| 免费欧美一区| 91精品国产电影| 亚洲精品无遮挡| 亚洲嫩草精品久久| 污色网站在线观看| 国产 福利 在线| 在线观看日本黄色| 亚洲少妇一区| 国产欧美综合精品一区二区| 51xtv成人影院| 欧美日韩精品欧美日韩精品| 丰满少妇一区二区| 亚洲伊人观看| 狠狠色综合欧美激情| 久色国产在线| 日韩欧美123| 欧美毛片在线观看| 国产精品影音先锋| avove在线观看| 国产午夜久久av| 操人视频在线观看欧美| 国产女人爽到高潮a毛片| 国产精品白丝在线| 在线观看免费av网址| 香蕉久久网站| 国产欧美一区二区三区在线| 91高清在线| 欧美久久久影院| 国产va在线播放| 成人一区在线观看| 加勒比成人在线| 欧美丝袜足交| 久久免费视频观看| 午夜国产在线观看| 欧美天堂在线观看| 真实乱视频国产免费观看| 免费视频一区| 日本视频一区二区在线观看| 成人黄色免费观看| 久久精品小视频| 精品人妻久久久久一区二区三区| 一区二区三区日韩欧美| 亚洲视频在线播放免费| 久久婷婷丁香| 正在播放一区| 第四色中文综合网| 欧美亚洲视频在线看网址| 韩国福利在线| 538在线一区二区精品国产| 免费日韩在线视频| 97se亚洲国产综合自在线不卡| 精品www久久久久奶水| 91麻豆国产自产在线观看亚洲| 亚洲自拍欧美色图| 97人澡人人添人人爽欧美| 亚洲欧美另类中文字幕| 一级淫片免费看| 亚洲香肠在线观看| 国产精品扒开腿做爽爽| 久草中文综合在线| 人妻少妇精品久久| 欧美日韩在线网站| 999国产在线| 88xx成人免费观看视频库| 精品国产拍在线观看| 日本激情一区二区三区| 91福利国产精品| 美女福利视频在线观看| 久久亚洲综合av| www.色.com| 欧美一级一区| 成年丰满熟妇午夜免费视频 | 日韩精品视频免费专区在线播放| 欧美在线视频精品| 亚洲一二三专区| 女人黄色一级片| 成人免费观看av| 天天干天天av| 乱码第一页成人| 欧美美女黄色网| 操欧美老女人| 九色一区二区| 日本精品国产| 国产精品视频资源| 桃色av一区二区| 欧美激情18p| 免费高清完整在线观看| 亚洲剧情一区二区| 蜜桃av中文字幕| 91精品国产综合久久蜜臀| 日本久久综合网| 精品国产乱码久久久久久婷婷| 亚洲色图100p| 国产日韩欧美综合在线| 国产xxxxxxxxx| 国产69精品久久久久毛片 | 青青国产在线视频| 香蕉成人伊视频在线观看| 校园春色 亚洲| 中文字幕一区二区在线播放| 色欲AV无码精品一区二区久久| 成人免费观看av| 91精产国品一二三| 国产综合久久久久影院| 538任你躁在线精品免费| 久久久精品网| 国产l精品国产亚洲区久久| 亚洲久久一区二区| 丁香六月激情婷婷| 韩国久久久久| 欧美这里只有精品| 一本一道久久综合狠狠老| 中国成人在线视频| 色777狠狠狠综合伊人| 日韩中文一区| 久久视频在线| 伊人色综合影院| 欧美成人激情| 一区中文字幕在线观看| 99久久精品费精品国产风间由美 | 六十路息与子猛烈交尾| 成人久久视频在线观看| 欧美xxxxx精品| 99精品视频在线免费观看| 久久性爱视频网站| 99国产精品99久久久久久| 久久精品女同亚洲女同13| 91小视频在线免费看| av鲁丝一区鲁丝二区鲁丝三区| av成人免费在线观看| 亚洲国产精品狼友在线观看| 粉嫩一区二区三区性色av| 亚洲图片欧美另类| 99在线精品免费| 人妻一区二区视频| 中国色在线观看另类| 国产jizz18女人高潮| 亚洲欧美日韩久久| 国产无套内射又大又猛又粗又爽| 亚洲成人资源网| 午夜婷婷在线观看| 欧美制服丝袜第一页| 国产精品高潮呻吟AV无码| 日韩片之四级片| 人人妻人人澡人人爽人人欧美一区 | 亚洲一区二区视频在线| 国产在线拍揄自揄拍无码视频| 精品国产乱码久久久久久婷婷| 日韩国产成人在线| 欧美一级黄色大片| 香港一级纯黄大片| 中文字幕亚洲欧美日韩2019| 影音先锋男人在线资源| 韩国精品久久久999| 午夜日韩成人影院| 91精品久久久久久久| 91九色鹿精品国产综合久久香蕉| 精品无码久久久久久久动漫| 成人精品天堂一区二区三区| 麻豆传媒网站在线观看| 亚洲专区在线| 国产女同无遮挡互慰高潮91| 成人毛片老司机大片| 超碰人人干人人| 亚洲sss视频在线视频| 色婷婷久久综合中文久久蜜桃av| 欧美一级片在线| 久久经典视频| 欧美精品www在线观看| 精品免费av一区二区三区| 亚洲在线观看视频网站| 亚洲自拍都市欧美小说| 午夜探花在线观看| 久久精品一区二区国产| 中文字幕无人区二| 中文字幕第一区第二区| 精品无码一区二区三区电影桃花 | 国产精品探花在线观看| 狠狠干视频网站| 免费观看在线综合色| 女同性恋一区二区三区| 亚洲免费色视频| 无码人妻av免费一区二区三区| 日韩欧美视频一区| 中文字幕在线视频区| 91大神福利视频在线| 免费一级欧美片在线观看网站| 日韩.欧美.亚洲| 一区在线播放| 超碰在线超碰在线| 国产精品美日韩| 国产一级淫片a视频免费观看| 精品国产伦一区二区三区观看方式 | 国产一区 二区| 亚洲欧美日韩不卡一区二区三区| 国产亚洲欧洲| 国产精品久久久久久亚洲av| 亚洲视频1区2区| 在线播放一级片| 一本久久综合亚洲鲁鲁| 爱情电影社保片一区| 国产日本一区二区三区| 中文字幕人成人乱码| 日韩高清第一页| 日本一区二区综合亚洲| 无码人妻精品一区二区三区9厂 | www.久久久| 欧美.www| 日本黄色一级网站| 亚洲三级理论片| 97人妻人人澡人人爽人人精品 | 久久99热狠狠色一区二区| 成人做爰69片免网站| 欧洲精品在线观看| 国产综合视频一区二区三区免费| 国产91成人在在线播放| 欧美黄色网视频| 两根大肉大捧一进一出好爽视频| 99久久综合狠狠综合久久| 欧美一区二区激情视频| 日韩二区三区在线| 色尼玛亚洲综合影院| 欧美在线播放一区| 久久先锋影音| 日本欧美一区二区三区不卡视频| 在线观看一区二区视频| 国产在线观看高清视频| 国产精品免费电影| 国产一区二区三区四区五区| 亚洲高清在线免费观看| 国产精品卡一卡二卡三| 国产精品特级毛片一区二区三区| 久久久成人精品视频| 日韩一级淫片| 国产午夜大地久久| 久久蜜桃一区二区| 中文字幕在线观看免费| 久久久成人精品| 精品伊人久久久| 国产一区亚洲二区三区| 中文字幕一区二区三区视频| 国产草草影院ccyycom| 国语自产精品视频在线看一大j8 | 欧美成年网站| 久草热视频在线观看| 国产欧美一区二区三区在线老狼| 亚洲在线精品视频| 欧美国产日韩xxxxx| 欧美18免费视频| 中文字幕第17页| 亚洲午夜三级在线| 激情小视频在线| 91久久极品少妇xxxxⅹ软件| 性久久久久久| 国产天堂av在线| 亚洲精品国产精品久久清纯直播 | 欧美一区二区成人6969| 国产色播av在线| 在线视频91| 99热99精品| 国产色视频在线| 国产成人97精品免费看片| 亚洲精品午夜av福利久久蜜桃| 国产性生活毛片| 欧美日韩精品一区二区天天拍小说| 美女精品视频| 亚洲精品8mav| 99久久精品国产麻豆演员表| 最近中文字幕在线观看| 久久久久久12| 93在线视频精品免费观看| 国产激情第一页| 日韩午夜激情av| 精品肉辣文txt下载| 日韩a∨精品日韩在线观看| 国产精品理伦片| 欧美白人做受xxxx视频| 3d蒂法精品啪啪一区二区免费|