国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频

Monorepo 的這些坑,我們幫你踩過了!

共 18691字,需瀏覽 38分鐘

 ·

2021-06-13 21:37

前言

筆者目前所在團(tuán)隊是使用 Monorepo 的方式管理所有的業(yè)務(wù)項(xiàng)目,而隨著項(xiàng)目的增多,穩(wěn)定性以及開發(fā)體驗(yàn)受到挑戰(zhàn),諸多問題開始暴露,可以明顯感受到現(xiàn)有的 Monorepo 架構(gòu)已經(jīng)不足以支撐日漸龐大的業(yè)務(wù)項(xiàng)目。

現(xiàn)有的 Monorepo 是基于 yarn workspace 實(shí)現(xiàn),通過 link 倉庫中的各個 package,達(dá)到跨項(xiàng)目復(fù)用的目的。package manager 也理所當(dāng)然的選擇了 yarn,雖然依賴了 Lerna,由于發(fā)包場景較為稀少,基本沒有怎么使用。

可以總結(jié)為以下三點(diǎn):

  • 通過 yarn workspace link 倉庫中的 package
  • 使用 yarn 作為 package manager 管理項(xiàng)目中的依賴
  • 通過 lerna 在應(yīng)用 app 構(gòu)建前按照依賴關(guān)系構(gòu)建其依賴的 packages

存在的問題

命令不統(tǒng)一

存在三種命令

  1. yarn
  2. yarn workspace
  3. lerna

新人上手容易造成誤解,部分命令之間功能存在重疊。

發(fā)布速度慢

如果我們需要發(fā)布 app1,則會

  1. 全量安裝依賴,app1、app2、app3 以及 package1 至 package6 的依賴都會被安裝;
  2. package 全部被構(gòu)建,而非僅有 app1 依賴的 package1 與 package2 被構(gòu)建。

Phantom dependencies

一個庫使用了不屬于其 dependencies 里的 Package 稱之為 Phantom dependencies(幻影依賴、幽靈依賴、隱式依賴),在現(xiàn)有 Monorepo 架構(gòu)中該問題被放大(依賴提升)。


由于無法保證幻影依賴的版本正確性,給程序運(yùn)行帶來了不可控的風(fēng)險。app 依賴了 lib-a,lib-a 依賴了 lib-x,由于依賴提升,我們可以在 app 中直接引用 lib-x,這并不可靠,我們能否引用到 lib-x,以及引用到什么版本的 lib-x 完全取決于 lib-a 的開發(fā)者。

NPM doppelgnger

相同版本的 Package 可能安裝多份,打包多份。

假設(shè)存在以下依賴關(guān)系


最終依賴安裝可能存在兩種結(jié)果:

  1. lib-x@^1 * 1 份,lib-x@^2 * 2 份
  2. lib-x@^2 * 1 份,lib-x@^1 * 2 份

最終本地會安裝 3 份 lib-x,打包時也會存在三份實(shí)例,如果 lib-x 要求單例,則可能會造成問題。

Yarn duplicate

Yarn duplicate 及解決方案[1]

假設(shè)存在以下依賴關(guān)系

當(dāng) (p)npm 安裝到相同模塊時,判斷已安裝的模塊版本是否符合新模塊的版本范圍,如果符合則跳過,不符合則在當(dāng)前模塊的 node_modules 下安裝該模塊。即 lib-a 會復(fù)用 app 依賴的 [email protected]。

然而,使用 Yarn v1 作為包管理器,lib-a 會單獨(dú)安裝一份 [email protected]。

  • difference between npm and yarn behavior with nested dependencies #3951[2]
  • Yarn installing multiple versions of the same package[3]
  • yarn-deduplicate-Cleans up yarn.lock by removing duplicates.[4]
  • Yarn v2 supports package deduplication natively[5]

peerDependencies 風(fēng)險

Yarn 依賴提升,在 peerDependencies 場景下可能導(dǎo)致 BUG。

  1. app1 依賴 [email protected]
  2. app2 依賴 [email protected]
  3. [email protected][email protected] 作為 peerDependency,故 app2 也應(yīng)該安裝 [email protected]

若 app2 忘記安裝 [email protected],那么結(jié)構(gòu)如下

--apps
    --app1
    --app2
--node_modules
    [email protected]
    [email protected]

此時 [email protected] 會錯誤引用 [email protected]。

Package 引用規(guī)范缺失

目前項(xiàng)目內(nèi)存在三種引用方式:

  1. 源碼引用:使用包名引用。需要配置宿主項(xiàng)目的構(gòu)建腳本,將該 Package 納入構(gòu)建流程。類似于直接發(fā)布一個 TypeScript 源碼包,引用該包的項(xiàng)目需要做一定的適配。
  2. 源碼引用:使用文件路徑引用。可以理解“宿主在自身 src 之外的源文件”,即宿主項(xiàng)目源代碼的一部分,而非 Package。宿主需要提供該所有依賴,在 Yarn 依賴提升的前提下達(dá)到了跨項(xiàng)目復(fù)用,但存在較大風(fēng)險。
  3. 產(chǎn)物引用。打包完成,直接通過包名引用產(chǎn)物。

Package 引用版本不確定性

假設(shè)一個 Monorepo 中的 package1 發(fā)布至了 npm 倉庫,那么 Monorepo 中的 app1 應(yīng)當(dāng)如何在 package.json 中編寫引用 package1 的版本號?

package1/packag.json

{
  "name""package1",
  "version""1.0.0"
}

app1/package.json

{
  "name""app1",
  "dependencies": {
    "package-1""?" // 這里的版本號應(yīng)該怎么寫?`*` or `1.0.0`
  }
}

在處理 Monorepo 中項(xiàng)目的互相引用時,Yarn 會進(jìn)行以下幾步判斷:

  1. 判斷當(dāng)前 Monorepo 中,是否存在匹配 app1 所需版本的 package1;
  2. 若存在,執(zhí)行 link 操作,app1 直接使用本地 package1;
  3. 若不存在,從遠(yuǎn)端 npm 倉庫拉取符合版本的 package1 供 app1 使用。

需要特別注意的是:* 無法匹配 prerelease 版本 ?? Workspace package with prerelease version and wildcard dep version #6719[6]。

假設(shè)存在以下場景:

  1. package1 此前已經(jīng)發(fā)布了 1.0.0 版本,此時遠(yuǎn)端倉庫與本地 Monorepo 中代碼一致;
  2. 產(chǎn)品同學(xué)提了一個只服務(wù)于 Monorepo 內(nèi)部應(yīng)用的需求;
  3. package1 在 1.0.0 版本下迭代,無需變更版本號發(fā)布;
  4. Yarn 判斷 Monorepo 中的 package1 版本滿足了 app1 所需版本(*1.0.0);
  5. app1 順利使用上 package1 的最新特性。

直到某天,該需求特性需要提供給外部業(yè)務(wù)方使用。

  1. pacakge1 將版本改為 1.0.0-beta.0 并進(jìn)行發(fā)版;
  2. Yarn 判斷當(dāng)前 Monorepo 中的 package1 版本不滿足 app1 所需版本;
  3. 從遠(yuǎn)端拉取 [email protected] 供 app1 使用;
  4. 遠(yuǎn)端 [email protected] 已經(jīng)落后 app1 先前使用的本地 [email protected] 太多;
  5. 準(zhǔn)備事故通報以及復(fù)盤。

這種不確定性,導(dǎo)致引用此類 package 時會經(jīng)常犯嘀咕:我到底引用的是本地版本還是遠(yuǎn)端版本?為什么有時候是本地版本,有時候是遠(yuǎn)端版本?我想用上 package1 的最新內(nèi)容還需要時刻保持與 package1 的版本號保持一致 ,那我干嘛用 Monorepo ?

yarn.lock 沖突

(p)npm 支持自動化解決 lockfile 沖突,yarn 需要手動處理,在大型 Monorepo 場景下,幾乎每次分支合并都會遇到 yarn.lock 沖突。

  • 不解決沖突無腦 yarn,yarn.lock 會直接失效,全部版本更新到 package.json 最新,風(fēng)險太大,失去 lockfile 的意義;
  • 人工解決沖突往往會出現(xiàn) Git conflict with binary files,只能使用 master 的提交再重新 yarn,流程繁瑣。

Automatically resolve conflicts in lockfile · Issue #2036 · pnpm/pnpm[7]

可以發(fā)現(xiàn),現(xiàn)有 Monorepo 管理方式缺陷過多,隨著其內(nèi)項(xiàng)目的不斷增加,構(gòu)建速度會越來越慢,同時程序的健壯性無法得到保證。僅憑開發(fā)人員自覺是不可靠的,我們需要一套解決方案。

推薦閱讀:node_modules 困境[8]

解決方案

pnpm[9]

Fast, disk space efficient package packageManager

在 npm@3 之前, node_modules 的結(jié)構(gòu)是干凈且可預(yù)測的,因?yàn)?node_modules 中的每個依賴項(xiàng)都有其自己的 node_modules 文件夾,其所有依賴項(xiàng)都在 package.json 中指定。

node_modules
└─ foo
   ├─ index.js
   ├─ package.json
   └─ node_modules
      └─ bar
         ├─ index.js
         └─ package.json

但是這樣帶來了兩個很嚴(yán)重的問題:

  1. 依賴層級過深在 Windows 下會出現(xiàn)問題;
  2. 同一 Package 作為其他多個不同 Package 的依賴項(xiàng)時,會被拷貝很多次。

為了解決這兩個問題,npm@3 重新思考了 node_modules 的結(jié)構(gòu),引入了平鋪的方案。于是就出現(xiàn)了下面我們所熟悉的結(jié)構(gòu)。

node_modules
├─ foo
|  ├─ index.js
|  └─ package.json
└─ bar
   ├─ index.js
   └─ package.json

與 npm@3 不同,pnpm 使用另外一種方式解決了 npm@2 所遇到的問題,而非平鋪 node_modules。

在由 pnpm 創(chuàng)建的 node_modules 文件夾中,所有 Package 都與自身的依賴項(xiàng)分組在一起(隔離),但是依賴層級卻不會過深(軟鏈接到外面真正的地址)。

-> - a symlink (or junction on Windows)

node_modules
├─ foo -> .registry.npmjs.org/foo/1.0.0/node_modules/foo
└─ .registry.npmjs.org
   ├─ foo/1.0.0/node_modules
   |  ├─ bar -> ../../bar/2.0.0/node_modules/bar
   |  └─ foo
   |     ├─ index.js
   |     └─ package.json
   └─ bar/2.0.0/node_modules
      └─ bar
         ├─ index.js
         └─ package.json
  1. 基于非扁平化的 node_modules 目錄結(jié)構(gòu),解決 Phantom dependencies。Package 只可觸達(dá)自身依賴。
  2. 通過軟鏈復(fù)用相同版本的 Package,避免重復(fù)打包(相同版本),解決 NPM doppelgnger(順帶解決磁盤占用)。

可以發(fā)現(xiàn),很多與包管理器相關(guān)的問題就此迎刃而解。

  • Why should we use pnpm?[10]
  • 平鋪 node_modules 不是唯一的路[11]

Rush[12]

a scalable monorepo manager for the web

  1. 命令統(tǒng)一。

rush(x) xxx 一把梭,減少新人上手成本。同時 Rush 除了 rush add 以及 rushx xxx 等命令需要在指定項(xiàng)目下運(yùn)行,其他命令均為全局命令,可在項(xiàng)目內(nèi)任意目錄執(zhí)行,避免了在終端頻繁切換項(xiàng)目路徑的問題。


  1. 強(qiáng)大的依賴分析能力。

Rush 中的許多命令支持分析依賴關(guān)系,比如 -t(to) 參數(shù):

$ rush install -t @monorepo/app1

該命令只會安裝 app1 的依賴及其 app1 依賴的 package 的依賴,即按需安裝依賴。

$ rush build -t @monorepo/app1

該命令會執(zhí)行 app1 以及 app1 依賴的 package 的構(gòu)建腳本。

類似的,還有 -f(from) 參數(shù),可以使命令只作用于當(dāng)前 package 以及依賴了該 package 的 package。

  1. 保證依賴版本一致性

Monorepo 中的項(xiàng)目應(yīng)當(dāng)盡量保證依賴版本的一致性,否則很有可能出現(xiàn)重復(fù)打包以及其他的問題。

Rush 則提供了許多能力來保證這一點(diǎn),如rush check、rush add -p package-name -m 以及 ensureConsistentVersions。

有興趣的同學(xué)可以自行翻閱 Rush 的官方文檔,十分詳盡,對于一些常見問題也有說明。

Package 引用規(guī)范


產(chǎn)物引用

傳統(tǒng)引用方式,構(gòu)建完成后,app 直接引用 package 的構(gòu)建產(chǎn)物。開發(fā)階段可以通過構(gòu)建工具提供的能力保證實(shí)時構(gòu)建(如 tsc --watch)

  • 優(yōu)點(diǎn):規(guī)范,對 app 友好。
  • 缺點(diǎn):隨著模塊增多,package 熱更新速度可能變得難以忍受。

源碼引用

package.json 中的 main 字段配置為源文件的入口文件,引用該 package 的 app 需要將該 package 納入編譯流程。

  • 優(yōu)點(diǎn):借助 app 的熱更新能力,自身沒有生成構(gòu)建產(chǎn)物的過程,熱更新速度快
  • 缺點(diǎn):需要 app 進(jìn)行適配, alias 適配繁瑣;

引用規(guī)范

  1. 對于項(xiàng)目內(nèi)部使用的 packages ,稱為 features,不應(yīng)當(dāng)向外發(fā)布,直接將 main 字段設(shè)置為源文件入口并配置 app 項(xiàng)目的 webpack,走后編譯形式。
  2. 對于需要對外發(fā)布的 packages,不應(yīng)該也不允許引用 features,必須要有構(gòu)建過程,如果需要使用源碼開發(fā)增加熱更新速度,可以新增一個自定義的入口字段,app 的 webpack 配置中優(yōu)先識別該入口字段即可。

補(bǔ)充:rush build 命令是支持構(gòu)建產(chǎn)物緩存的,如果 app 拆分粒度夠小,可復(fù)用的包足夠多,同時打包鏡像支持構(gòu)建產(chǎn)物緩存的 set 與 get,就可以做到增量構(gòu)建 app。

Workspace protocol (workspace:)

在 PNPM 和 Yarn 支持 Workspace 能力之前,Rush 就誕生了。Rush 的方法是將所有軟件包集中安裝在 common / temp 文件夾中,然后 Rush 創(chuàng)建從每個項(xiàng)目到 common / temp 的符號鏈接。與 PNPM Workspace 本質(zhì)上是等效的。

開啟 PNPM workspace[13] 能力從而可以使用 workspace:協(xié)議保證引用版本的確定性,使用了該協(xié)議引用的 package 只會使用 Monorepo 中的內(nèi)容。

{
  "dependencies": {
    "foo""workspace:*",
    "bar""workspace:~",
    "qar""workspace:^",
    "zoo""workspace:^1.5.0"
  }
}

推薦引用 Monorepo 內(nèi)的 package 時統(tǒng)一使用該協(xié)議,引用本地最新版本內(nèi)容,保證更改能夠及時擴(kuò)散同步至其他項(xiàng)目,這也是 Monorepo 的優(yōu)勢所在。

若一定要使用遠(yuǎn)端版本,需要在 rush.json 中配置具體 project (增加 cyclicDependencyProjects配置),詳見 rush_json[14]

很幸運(yùn)的是 PNPM workspace 中 workspace:* 可以匹配 prerelease 版本 ?? Local prerelease version of packages should be linked only if the range is \*[15]

問題記錄

Monorepo Project Dependencies Duplicate

這個問題類似于前面提到的 Yarn duplicate,但并不是 Yarn 獨(dú)有的。

假設(shè)存在以下依賴關(guān)系(將 Yarn duplicate 的例子進(jìn)行改造,放在 Monorepo 場景中)

app1 以及 package1 同屬于 Monorepo 內(nèi)部 project。

在 Rush(pnpm)/Yarn 項(xiàng)目中,會嚴(yán)格按照 Monorepo 內(nèi) project 的 package.json 所聲明的版本進(jìn)行安裝,即 app1 安裝 [email protected],package1 安裝 [email protected]。

此時對 app1 進(jìn)行打包,則 [email protected][email protected] 都會被打包。

對這個結(jié)果你也許會有一些意外,但仔細(xì)想想,又很自然。

換一種方式理解,整個 Monorepo 是一個大的虛擬 project,我們所有的 project 都作為這個虛擬 project 的直接依賴存在。

{
  "name""fake-project",
  "version""1.0.0",
  "dependencies": {
    "@fake-project/app1""1.0.0",
    "@fake-project/package1""1.0.0"
  }
}

安裝依賴時,(p)npm 首先下載直接依賴項(xiàng),然后再下載間接依賴項(xiàng),并且在安裝到相同模塊時,判斷已安裝的模塊版本(直接依賴項(xiàng))是否符合新模塊(間接依賴項(xiàng))的版本范圍,如果符合則跳過,不符合則在當(dāng)前模塊的 node_modules 下安裝該模塊。

而 app1 和 package1 的直接依賴關(guān)系 lib-a 是該 fake-project 的間接依賴項(xiàng),無法滿足上述判斷條件,于是按照對應(yīng) package.json 中描述的版本安裝。

解決方案:Rush: Preferred versions[16]

Rush 可以通過手動指定 preferredVersions 的方式,避免兩個可兼容版本的重復(fù)。這里將 Monorepo 中 lib-a 的 preferredVersions 指定為 1.2.0,相當(dāng)于在該虛擬 project 下直接安裝了指定的版本的模塊,作為直接依賴項(xiàng)。

{
  "name""fake-project",
  "version""1.0.0",
  "dependencies": {
    "@fake-project/app1""1.0.0",
    "@fake-project/package1""1.0.0",
    "lib-a""1.1.0"
  }
}

對于 Yarn,由于 Yarn duplicate 的存在,就算在根目錄指定安裝確定版本的 lib-a 也是無效的。但是依舊有兩種方案可以進(jìn)行處理:

  1. 通過 yarn-deduplicate[17] 針對性的修改 yarn.lock;
  2. 使用resolutions 字段。過于粗暴,不像 preferredVersions 可以允許不兼容版本的存在,不推薦。

需要謹(jǐn)記:在 Yarn 下消除重復(fù)依賴,也應(yīng)該一個 Package 一個 Package 的去進(jìn)行處理,小心使得萬年船。

  1. 對于存在副作用的公共庫,版本最好保持統(tǒng)一;
  2. 對于其他的體積?。ɑ蛑С职葱杓虞d)、無副作用的公共庫,重復(fù)打包在一定程度上可以接受的。

prettier

由于根目錄不再存在 node_modules,故需要每個項(xiàng)目安裝一個 prettier 作為 devDependency 并編寫 .prettierrc.js 文件。

本著偷懶的原則,根目錄新建 .prettierrc.js(不依賴任何第三方包),全局安裝 prettier 解決該問題。

eslint

先看一個場景,若在項(xiàng)目中使用 eslint-config-react-app,除了需要安裝 eslint-config-react-app,還需要安裝一系列 peerDependencies 插件。

為什么 eslint-config-react-app 不將這一系列插件作為 dependencies 內(nèi)置,而是作為 peerDependencies?使用者并不需要關(guān)心預(yù)設(shè)配置內(nèi)引用了哪些插件。

具體討論可以查看該 issue,里面有相關(guān)問題的討論:Support having plugins as dependencies in shareable config #3458[18] 。

總而言之:和 eslint 插件的具體查找方式有關(guān),如果因?yàn)橐蕾囂嵘。ǘ喟姹緵_突),導(dǎo)致需要的插件被裝在了非根目錄 node_modules 下,就可能產(chǎn)生問題,而用戶自行安裝 peerDependencies 可以保證不會出現(xiàn)該問題。

當(dāng)然,我們也發(fā)現(xiàn)一些開源的 eslint 預(yù)設(shè)配置不需要安裝 peerDependencies,這些預(yù)設(shè)利用了 yarn 和 npm 的扁平 node_modules 結(jié)構(gòu),也就是依賴提升,裝的包都被提升至根目錄 node_modules,故可以正常運(yùn)作。即便如此,在基于 Yarn 的 Monorepo 中,依賴一旦復(fù)雜起來,就可能出現(xiàn)插件無法被查找到的情況,能夠正常運(yùn)轉(zhuǎn)就像一個有趣的巧合。

在 Rush 中,不存在依賴提升(提升也不一定靠譜),裝一系列的插件又過于繁瑣,則可以通過打補(bǔ)丁[19]的方式繞過。

git hooks

通常會在項(xiàng)目中使用 husky 注冊 pre-commitcommit-msg 鉤子,用于校驗(yàn)代碼風(fēng)格以及 commit 信息。

很明顯,在 Rush 項(xiàng)目的結(jié)構(gòu)下,根目錄是沒有 node_modules 的,無法直接使用 husky。

我們可以借助 rush init-autoinstaller[20] 的能力來達(dá)到一樣的效果,本節(jié)主要參考官方文檔 Installing Git hooks[21] 以及 Enabling Prettier[22] 的內(nèi)容。

# 初始化一個名為 rush-lint 的 autoinstaller

$ rush init-autoinstaller --name rush-lint

cd common/autoinstallers/rush-lint

# 安裝 lint 所需依賴

$ pnpm i @commitlint/cli @commitlint/config-conventional @microsoft/rush-lib eslint execa prettier lint-staged

# 更新 rush-lint 的 pnpm-lock.yaml

$ rush update-autoinstaller --name rush-lint

rush-lint 目錄下新增 commit-lint.js 以及 commitlint.config.js,內(nèi)容如下

commit-lint.js

const path = require('path');
const fs = require('fs');
const execa = require('execa');

const gitPath = path.resolve(__dirname, '../../../.git');
const configPath = path.resolve(__dirname, './commitlint.config.js');
const commitlintBinPath = path.resolve(__dirname, './node_modules/.bin/commitlint');

if (!fs.existsSync(gitPath)) {
    console.error('no valid .git path');
    process.exit(1);
}

main();

async function main({
    try {
        await execa('bash', [commitlintBinPath, '--config', configPath, '--cwd', path.dirname(gitPath), '--edit'], {
            stdio'inherit',
        });
    } catch (\_e) {
        process.exit(1);
    }
}

commitlint.config.js

const rushLib = require("@microsoft/rush-lib");

const rushConfiguration = rushLib.RushConfiguration.loadFromDefaultLocation();

const packageNames = [];
const packageDirNames = [];

rushConfiguration.projects.forEach((project) => {
  packageNames.push(project.packageName);
  const temp = project.projectFolder.split("/");
  const dirName = temp[temp.length - 1];
  packageDirNames.push(dirName);
});
// 保證 scope 只能為 all/package name/package dir name
const allScope = ["all", ...packageDirNames, ...packageNames];

module.exports = {
  extends: ["@commitlint/config-conventional"],
  rules: {
    "scope-enum": [2"always", allScope],
  },
};

注意:此處不需要新增 prettierrc.js(根目錄已存在) 以及 eslintrc.js(各項(xiàng)目已存在)。

根目錄新增 .lintstagedrc 文件

.lintstagedrc

{
  "{apps,packages,features}/**/*.{js,jsx,ts,tsx}": [
    "eslint --fix --color",
    "prettier --write"
  ],
  "{apps,packages,features}/**/*.{css,less,md}": ["prettier --write"]
}

完成了相關(guān)依賴的安裝以及配置的編寫,我們接下來將相關(guān)命令執(zhí)行注冊在 rush 中。

修改 common/config/rush/command-line.json 文件中的 commands 字段。

{
  "commands": [
    {
      "name""commitlint",
      "commandKind""global",
      "summary""Used by the commit-msg Git hook. This command invokes commitlint to lint commit message.",
      "autoinstallerName""rush-lint",
      "shellCommand""node common/autoinstallers/rush-lint/commit-lint.js"
    },
    {
      "name""lint",
      "commandKind""global",
      "summary""Used by the pre-commit Git hook. This command invokes eslint to lint staged changes.",
      "autoinstallerName""rush-lint",
      "shellCommand""lint-staged"
    }
  ]
}

最后,將 rush commitlint 以及 rush lint 兩個命令分別與 commit-msg 以及 pre-commit鉤子進(jìn)行綁定。common/git-hooks 目錄下增加 commit-msg 以及 pre-commit 腳本。

commit-msg

#!/bin/sh

node common/scripts/install-run-rush.js commitlint || exit $? #++

pre-commit

#!/bin/sh

node common/scripts/install-run-rush.js lint || exit $? #++

如此,便完成了需求。

避免全局安裝 eslint 以及 prettier

經(jīng)過上一節(jié)的處理,在 rush-lint 目錄下安裝了 eslint 以及 prettier 后,我們便無需全局安裝了,只需要配置一下 VSCode 即可。

{
  // ...
  "npm.packageManager""pnpm",
  "eslint.packageManager""pnpm",
  "eslint.nodePath""common/autoinstallers/rush-lint/node_modules/eslint",
  "prettier.prettierPath""common/autoinstallers/rush-lint/node_modules/prettier"
  // ...
}

附錄

常用命令

yarnrush(x)detail
yarn installrush install安裝依賴
yarn upgraderush updaterush update 安裝依賴,基于 lock 文件
rush update --full 全量更新到符合 package.json 的最新版本
yarn add package-namerush add -p package-nameyarn add 默認(rèn)安裝版本號為 ^ 開頭,可接受小版本更新
rush add 默認(rèn)安裝版本號為 ~ 開頭,僅接受補(bǔ)丁更新
rush add 可通過增加 --caret 參數(shù)達(dá)到與 yarn add 效果一致
rush add 不可一次性安裝多個 package
yarn add package-name --devrush add -p package-name --dev-
yarn remove package-name-rush 不提供 remove 命令
-rush build執(zhí)行文件存在變更(基于 git)的項(xiàng)目的 build 腳本
rush build -t @monorepo/app1 表示只構(gòu)建 @monorepo/app1 及其依賴的 package
rush build -T @monorepo/app1 表示只構(gòu)建 @monorepo/app1 依賴的 package,不包含其本身
-rush rebuild默認(rèn)執(zhí)行所有項(xiàng)目的 build 腳本
yarn xxx(自定義腳本)rushx xxx(自定義腳本)yarn xxx 執(zhí)行當(dāng)前目錄下 package.json 中的 xxx 腳本(npm scripts)
rushx xxx 同理??梢灾苯訄?zhí)行 rushx 查看當(dāng)前項(xiàng)目所支持的腳本命令。

工作流

# 從 git 拉取最新變更
$ git pull

# 更新 NPM 依賴
$ rush update

# 重新打包 @monorepo/app1 依賴的項(xiàng)目(不含包其本身)
$ rush rebuild -T @monorepo/app1

# 進(jìn)入指定項(xiàng)目目錄
cd ./apps/app1

# 啟動項(xiàng)目 
$ rushx start # or rushx dev

參考文章

  • Rush.js[23]
  • node_modules 困境[24]
  • Why should we use pnpm?[25]
  • 平鋪 node_modules 不是唯一的路[26]

參考資料

[1]

Yarn duplicate 及解決方案: https://github.com/worldzhao/blog/issues/10

[2]

difference between npm and yarn behavior with nested dependencies #3951: https://github.com/yarnpkg/yarn/issues/3951

[3]

Yarn installing multiple versions of the same package: https://stackoverflow.com/questions/49072905/yarn-installing-multiple-versions-of-the-same-package

[4]

yarn-deduplicate-Cleans up yarn.lock by removing duplicates.: https://github.com/atlassian/yarn-deduplicate

[5]

natively: https://github.com/yarnpkg/berry/pull/1558

[6]

Workspace package with prerelease version and wildcard dep version #6719: https://github.com/yarnpkg/yarn/issues/6719

[7]

Automatically resolve conflicts in lockfile · Issue #2036 · pnpm/pnpm: https://github.com/pnpm/pnpm/issues/2036

[8]

node_modules 困境: https://zhuanlan.zhihu.com/p/137535779

[9]

pnpm: https://pnpm.io/

[10]

Why should we use pnpm?: https://www.kochan.io/nodejs/why-should-we-use-pnpm.html

[11]

平鋪 node_modules 不是唯一的路: https://pnpm.io/zh/blog/2020/05/27/flat-node-modules-is-not-the-only-way

[12]

Rush: https://rushjs.io/

[13]

PNPM workspace: https://pnpm.io/zh/workspaces

[14]

rush_json: https://rushjs.io/pages/configs/rush_json/

[15]

Local prerelease version of packages should be linked only if the range is *: https://github.com/pnpm/pnpm/pull/2259

[16]

Rush: Preferred versions: https://rushjs.io/pages/advanced/preferred_versions/

[17]

yarn-deduplicate: https://github.com/atlassian/yarn-deduplicate

[18]

Support having plugins as dependencies in shareable config #3458: https://github.com/eslint/eslint/issues/3458

[19]

補(bǔ)丁: https://www.npmjs.com/package/@rushstack/eslint-patch

[20]

rush init-autoinstaller: https://rushjs.io/pages/commands/rush_init-autoinstaller/

[21]

Installing Git hooks: https://rushjs.io/pages/maintainer/git_hooks/

[22]

Enabling Prettier: https://rushjs.io/pages/maintainer/enabling_prettier/

[23]

Rush.js: https://rushjs.io/

[24]

node_modules 困境: https://zhuanlan.zhihu.com/p/137535779

[25]

Why should we use pnpm?: https://www.kochan.io/nodejs/why-should-we-use-pnpm.html

[26]

平鋪 node_modules 不是唯一的路: https://pnpm.io/zh/blog/2020/05/27/flat-node-modules-is-not-the-only-way


瀏覽 117
點(diǎn)贊
評論
收藏
分享

手機(jī)掃一掃分享

分享
舉報
評論
圖片
表情
推薦
點(diǎn)贊
評論
收藏
分享

手機(jī)掃一掃分享

分享
舉報

感谢您访问我们的网站,您可能还对以下资源感兴趣:

国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频 69毛片| 欧美性性性| AⅤ视频在线观看| 中文字幕无码不卡| www.91久久| 日韩一区二区免费视频| 极品美鮑20p| 日韩无码视频观看| 精品免费在线| 黄色视频在线观看| 91精品国产乱码| 香蕉国产AV| 西西444WWW大胆无| 亚洲视频网| 香蕉91视频| 一级免费A片| 亚洲综合中文字幕在线| 100国产精品人妻无码| av在线小说| 污视频在线免费| 91丝袜一区二区| 成人免费无码婬片在线| 亚洲AV男人天堂| 伊人天天操| 精品久久久国产| 亚洲国产电影| 亚洲砖区区免费| 九七在线视频| 欧美系列在线| 在线免费亚洲| 自拍偷拍一区二区三区| www,操逼| 伊人春色网| 久久精品免费| www深夜成人a√在线| 色伊人| 亚洲精品成人视频| 日本高清无码视频| 婷婷性爱五月天| 精品蜜桃秘一区二区三区在线播放| 人人搞人人操| 日日夜夜精选视频| 亚洲AV无码成人片在线| 四虎亚洲无码| 无码国产精品一区二区性色AV | 精品九九| 国产精品视频久久| 插插视频| 欧美69视频| 国产精品性爱视频| 99综合在线| 中文字幕人妻互换av久久| 天天色天天爱| 熟女嗷嗷叫高潮合集91| 日韩AⅤ| 一二区免费视频| 久久色婷婷| 久久婷婷国产麻豆91天堂| 超碰人人操97| 人妻啪啪视频| 午夜91| 成人免费乱码大片a毛片蜜芽| AV黄色网| 国语一区| 黄色A级视频| 欧美自拍第一页| 人人妻人人操人人干| 免费在线观看黄色网址| 一本色道无码人妻精品| 国产成人小电影| 中文字幕无码免费| 亚洲精品美女视频| 亚洲中文字幕日韩精品| 中文字幕人妻丝袜二区电影| 91成人片| 不卡在线视频| 精品视频在线免费观看| 精品AV| 一区二区三区四区久久| 中文字幕网址在线| 操逼网站免费观看| 欧美成人在线网站| 国产AV不卡| 黄色视频在线观看国产| 你懂的在线网站| 日韩a片在线观看| 国产3区| 午夜蜜桃| 男女视频91| 六月婷婷中文字幕| 国产一级a毛一级a毛观看视频网站www.jn| 日韩精品中文字幕在线观看| 天天舔九色婷婷| A片黄色毛片| 91青青视频| 精品中文视频| 日日夜夜天天综合| 性猛交AAAA片免费观看直播 | 伊人久久大香色综合久久| 免费无码视频一区二区| 国产AV日韩| 日屄视频免费看| 久久思热国产| 日韩视频在线观看一区| 欧美亚洲视频在线观看| 成人免费黄色视频网站| 久久6精品| 久久新视频| 日韩精品三级| 一区二区三区免费看| 色婷婷Av| 欧美久久久久| 黄色在线网站| 精品91美女| 国产在线久久久| 亚洲伦理一区二区| 99视频+国产日韩欧美| 激情自拍偷拍| 日韩中文字幕在线人成网站| 久久国产欧美| 一区二区三区精品视频| 日韩A电影| 日韩天堂在线| 国产精品黄色| 免费一级婬片AA片观看| 美国高清无码| 99r6热只有精品免费观看| 久久久123| 停停六综合| 久草手机视频在线观看| 国产一级A片久久久免费看快餐| 豆花视频成人精品视频| 亚洲免费在线观看视频| AV毛片| 九九热无码| 亚洲一区自拍| 操逼123首页| 亚洲无码一卡二卡| 美女自慰网站免费| 肏屄视频在线| 特级444WWW大胆高清| 97伊人| 91人妻无码一区二区久久| 干欧美女人| 人妻爽爽| 日本一级婬片免费放| 色天使av| 日韩无码A片| 成人免费毛片AAAAAA片| 亚洲AV无码一区二区三竹菊| 亚洲精品国产成人| 亚洲黄色小电影| 在线aaa| 国产原创精品| 99久久99久久精品免费看蜜桃| 黄色片网站| www天天操| 午夜成人黄色电影| 色综合久久88色综合| 成人AV一区二区三区| 免费一级A片在线播放| 精品偷拍视频| 无码精品一区| 2025天天操夜夜操| 懂色av懂色av粉嫩av| 午夜福利视频网站| 国产精品a久久久久| 无码精品人妻一区二区三刘亦菲| 人人看人人干| 成人毛片在线大全免费| 嫩BBB槡BBBB槡BBBB百度| AV网站在线免费观看| 色色毛片| 日韩人妻丰满无码区A片| 丁香婷婷五月综合影院| 秋霞午夜福利影院| 五月天乱伦小说| 一级在线| 99热久| 精品一区二区三区av| 国产一区二区在线播放| 99黄片| 大鸡吧在线视频| 黄色大片免费看| 超碰在线观看2407| 91色在线视频| 国产亚洲欧美精品综合在线| 欧美日韩精品久久久免费观看| 国产成人精品视频| 免费黄色小视频在线观看| 五月丁香欧美综合| 超碰天天操| 西西444www| 午夜精品18视频国产17c| 亚洲AV永久无码国产精品久久| 久久婷婷在线| 中文字幕免费视频在线观看| 欧美91| 中文字幕一二三| H网站在线观看| 日本视频一区二区三区| www.麻豆网91成人久久久| 天天爽夜夜爽AA片免费| 久久综合无码内射国产| 亚洲AV网址| 亚洲无码AV电影| av大片免费看| 国产对白视频| 无套免费视频欧美| 激情六月婷婷| 粉嫩小泬BBBB免费看| 青青操视频在线| 一级片视频在线观看| 人人插人人| 亚洲午夜AV| 怡春院视频| 九九精品国产| 国产免费黄色| 91丨精品丨国产丨丝袜| 亚州一区| 中文无码熟妇人妻AV在线| 日韩AV无码高清| 国产aaaa| 色综合综合色| 色天堂在线观看| 久久久久亚洲AV成人片乱码| 天天无码视频| 一本一道久久| 久久日韩操| www激情| 国产无套免费网站69| 亚洲色诱| 精品无码一区二区三区四区五区| 韩国三级HD中文字幕的背景音乐| 操逼五月天| 短发半推半就AV| 成人18视频| 成年人黄色电影| 国产精品揄拍一区二区| 97免费在线视频| 亚州视频在线| 午夜福利片| 黄色九九| 无码伦理| 91在线视频精品| www99国产| 美女做爱视频网站| 狠狠操综合| 五月六月丁香激情视频| 精品黄色视频| 欧美成人在线观看视频| 熟女人妻一区二区三区| 免费无码在线视频| 亚洲精品视频在线播放| 日韩中文字幕一区二区三区| 91麻豆精品在线观看| 俺去听听婷婷| 日韩视频一二三| 日韩一级片网站| 婷婷丁香五月激情| 成人一二区| 亚洲免费一级片| 日本精品一区二区三区四区的功能 | 性性性性性XXXXX| 亚洲精品无码a片| 亚洲午夜剧场| 天天日天天日天天操| 午夜成人视频在线观看| 中文无码在线| 在线观看无码高清视频| 囯产精品久久久久久久久| 一级黄色视频日逼片| 女人18片毛片90分钟免费明星| 狠狠操综合| 抠逼网站| 免费无码av| 亚洲骚妇| 高潮毛片| 亚洲无码制服| 欧美视频在线免费| 中文字幕日韩成人| 中文字幕精品在线| 亚洲AV国产| 亚洲成人AV在线观看| 牛牛成人在线视频| 天堂在线观看av| 麻豆啪啪| 在线不卡无码| 91无码在线视频| 特黄特黄免费看| 91人人妻人人操| 国产1区2区| 免费观看成人毛片A片直播千姿| 免费看一级黄色片| 人妻精品一卡二卡| 爆操网站| 一区二区三区四区五区在线| 日日操天天操| AV免费在线播放| 日本不卡一区二区三区四区| 欧美三级片网| 蜜桃视频一区二区三区| 免费成人视频在线观看| 韩国无码免费| 996热re视频精品视频这里| 在线看国产| 99极品视频| 大香蕉大香蕉视频网| 北条麻妃久久| 在线播放亚洲无码| 亚洲自拍偷拍视频| 操逼三级片| www.91在线| 国产无遮挡又黄又爽在线观看 | 中文字幕一区在线| 国产亚洲中文字幕| 操屄网| 四川少妇搡BBBB搡BBB视频网| 西西4444www无码精品| 亚洲精品白浆高清久久久久久 | 99成人国产精品视频| 又a又黄高清无码视频| 成人黄网站在线观看| ww毛片| 日本不卡中文字幕| 黄工厂精品视频在线播| 97播播| 超碰女人| 97在线观看视频| 婷色五月| 国产卡一卡二| 俺来也俺也去| 日韩va亚洲va欧美va高清| av无码精品一区| 亚洲精品97久久中文字幕| 高清无码1区| 日韩vA| 中文无码在线观看中文字幕av中文 | 天天操网址| 国内自拍视频在线观看| 亚洲成人福利在线| 亚洲在线观看中文字幕| 爱爱视频欧美| 久久大香蕉视频| 五月婷婷视频在线观看| 中文字幕欧美视频| 国产久久久久| 亚洲欧美日本在线| 亚洲无码黄片| 日韩女人性爱| 欧美亚洲视频在线观看| 女人18片毛片60分钟黃菲菲| 无码人妻一区二区三区| 大香蕉在线视频75| 男人天堂婷婷| 日韩在线小视频| 六月综合激情| 国产视频一区二区在线观看| 亚洲成人av在线| 国产,亚洲91| 午夜无码影院| 欧美日韩在线播放| 中文字幕av网站| 超碰97老师| 内射国产| 午夜成人黄色| 日韩欧美国产精品综合嫩V| 国产午夜精品一区二区三区嫩A | 亚洲第一成人网站| 亚洲天堂成人在线| 国产人成一区二区三区影院| 午夜无码久久| 精品久久久久久久久久久| 欧美视频在线免费| 四川少妇BBBB| 男女操逼视频网站免费| 国产精品不卡一区二区三区| 国产精品999| 91麻豆精品无码人妻| 伊人亚洲| 国产91在线一区| 免费看一级无码成人片| 最近最火中文字幕mv歌词| 欧美亚洲成人在线| AV电影在线免费观看| 亚洲三级在线播放| 悠悠色导航| 一区二区三区在线免费观看| 9l蝌蚪PORNY中文| 日韩另类视频| 亚洲无码一区二区三| A片视频免费看| 人妻少妇精品视频一区二区三区 | 日韩精品| 日韩成人无码免费视频| 国外成人视频| 999大香蕉| 在线免费小黄片| 人妻体内射精一区二区三区| 鸡巴在线观看| 无码人妻一区二区三区免费n鬼沢| 久久99精品久久久久| 亚洲精品国产精品国自产曰本| 一区二区小视频| 在线观看欧美日韩| 国语一区| 影音先锋一区二区三区| 丁香激情五月少妇| 国产十欧洲十美国+亚洲一二三区在线午夜 | 开心五月色婷婷综合开心网| 玩弄人妻少妇500系列视频| 91亚洲精品国产成人| 天天天操| 国产美女在线播放| 偷拍视频网站北条麻妃| 日韩中文字幕免费| 91麻豆国产在线| 亚洲第一天堂| 中文字幕VA| 懂色av| ww久久| 青青精品| 国产成人AⅤ| 久草青| 欧美成人精品a| 日韩欧美一| 欧洲亚洲无码| 韩国AV在线| 性无码一区二区三区在线观看 | 日韩中文字幕av在线| 久久嫩草在线影院| 黃色级A片一級片| 麻豆熟妇乱妇熟色A片在线看| 欧美黄色电影网站| 午夜69成人做爱视频网站| 在线观看免费视频无码| 亚洲,制服,综合,中文| 国产人妖AV| 亚洲va综合va国产va中文| 夜夜嗨AV一区二区三区| 欧美性猛交ⅩXXX乱大交| 日韩精品| 色五月婷婷综合| 久久黄色视屏| 精品國產一區二區三區久久蜜月 | 日本三级片网站在线观看| 北京熟妇槡BBBB槡BBBB| 亚洲五月丁香婷婷| 99美女精品视频| A视频在线观看| 久久精品国产亚洲AV成人婷婷| 成人午夜A片免费看| 欧美成人精品一区二区三区| h片在线免费观看视频| 一级黄色影院| 麻豆91麻豆国产传媒| 国产精品久久久精品cos| 国产视频精品一区二区三区| 91欧美| 一级黄色电影免费看| 波多野结衣在线观看一区二区| 九九久久国产精品| 成人免费a片| 91蝌蚪在线观看| 婷婷五月色播| 亚洲午夜久久久之蝌蚪窝| 性久久久久久| 亚洲40p| 久久亚洲AV成人无码国产野外| 操极品美女| 99在线视频免费观看| 天天爽天天日| 尻屄视频免费| 无码乱伦AV| 欧美色图在线视频| 国产看片网站| 国产精品乱子伦| 操逼去| 国产免费黄色av| av无码高清| 中文乱伦视频| 欧美成人视频网| 黄色片亚洲| 免费一级电影| 国产精品1区2区| 学生妹一级片内射视频| 小泽玛利亚一区二区免费| 亚洲中文字幕码mv| 亚洲男人的天堂视频网在线观看+720P| 精品视频在线免费| 国产免费无码一区二区| 免费A网站| 三级片亚洲无码| 乱伦91视频| 国产精品国产自产拍高清AV| 一级大片| 国产无套内射视频| 婷婷五月综合中文字幕| 女女女女女女BBBBBB手| 中文字幕无码在线观看| 在线观看国产黄色| 中文字幕乱码中文字幕| 91亚洲国产精品| 欧美精品无码一区二区| 一区二区高清无码| 91福利导航| 欧美中文字幕在线播放| 日韩欧美在线一区| 777性爱| 少妇高潮视频| 欧美性爱免费网站| 国产精品s色| 中文字幕五码| 久久久久久久久久久国产精品 | wwwA片| 操逼亚洲| AAAAA毛片| 国产午夜精品一区二区| 人人夜夜人人| 躁BBB躁BBB躁BBBBBB日视频 | 操逼的视频| 最新中文字幕777私人在线| 国产一| 日韩一级无码特黄AAA片| 日韩黄色免费电影| 青青青青青操| 久久国产亚洲| 国产A片大全| 久久久久久久久毛片| 黄网站欧美内射| 免费观看高清无码视频| 蜜臀激情| 乌克兰xxxx| 天堂在线最新资源| 韩日无码| 91精品国产成人观看| 黑人一级片| AV电影在线观看| 亚洲理论电影| 青春草免费视频| 毛片三级片| 欧美在线黄片| 国产综合婷婷| 欧美精品一级片| 国产精品国产三级国产AⅤ原创| 中国免费XXXX18| 欧洲性爱视频| 免费日韩毛片| 日韩AV一级| 欧美成人在线免费视频| 视频二区| 婷婷五月无码| 国产成人无码免费| 婷婷五月六月丁香| 天堂а√在线中文在线新版| 免费91视频| 视频二区中文字幕| 国产一级片免费看| 人妻无码专区| 中国操逼视频| 97国产在线视频| 中文字幕无码在线视频| 免费黄色在线视频| 欧美日韩黄片| 狠狠的操| 亚洲国产精品成人va在线观看| 在线观看av中文字幕| 亚洲伊人在线| 久久你懂的| 北条麻妃九九九在线视频| 蜜桃人妻无码AV天堂二区| 69自拍视频| 亚洲人成电影网| 91视频在线网站| 撸一撸AV| 大地影院资源官网| 日本丰满老熟妇乱子伦| 青春草在线| 欧美老妇性猛交| 青娱AV| 麻豆艾秋MD0056在线| 欧美日韩一区二区三区视频| 一起操在线视频| 亚洲熟妇AV日韩熟妇在线| 特级西西444WWW高清| 成人小说亚洲一区二区三区| 摸BBB搡BBB搡BBBB| 围产精品久久久久久久| 亚洲制服在线观看| 撸一撸在线视频| 国产熟妇搡BBBB搡BBBB毛片 | 俺来也俺去也www色官| 日本AA片视频| 久久超碰精品| 中文字幕AV无码| 操逼在线视频| 一区二区三区精品婷婷| 91在线成人视频| 免费一区视频| 一本色道无码道| 日韩成人无码人妻| 无码国产精品一区二区免费96| 人人爱人人摸| 一本色道久久综合熟妇人妻| 日韩在线国产| 日韩爆乳在线| 人人爱人人操人人干| 国产成人精品一区二区三区视频 | 东京热久久综合| 天堂俺去俺来也www久久婷婷| 靠逼免费视频| 欧美精品性爱| 91久久久裸身美女| 色草视频| www.俺去| 欧美日韩精品久久久免费观看| 精品日韩| 无码网站内射| 翔田千里中文字幕无码| 亚洲精品不卡| www.伊人| 日韩视频一二三| 国产美女免费视频| 五月天激情小说网| 色色热| 日本久久久久久久久视频在线观看| 人人操人人看人人干| av久操| 夜夜夜撸| 国产精品电影| 国产精品一级A片| 艹逼网站| 国产一级a毛一级a做免费高清视频| AV黄色| 日韩天堂在线播放| 免费操逼电影| 99热99精品| 免费观看色情视频| 亚洲高清毛片一区二区| 婷婷丁香一区二区三区| 综合无码| 人妻无码蜜桃视频| 一区二区三区无码区| 天天综合天天做天天综合| 插菊花综合| 国产熟女自拍| 刘玥无码| 69久蜜桃人妻无码精品一区| 成人免费无码激情AV片| 啪一啪操一操| 久久人妻熟女中文字幕av蜜芽 | 一本色道综合久久欧美日韩精品| 中文字幕一区二区三区四区五区六区 | 色色视频免费看| 人人超碰在线| 国产成人在线免费视频| 三级片在线看片AV| 天堂资源站| 亚洲自拍电影| 国产美女一级特黄大片| 亚洲高清电影| 91狠狠综合久久久久久| 在线操B视频| 欧美日韩亚洲天堂| 欧美草逼视频| 日本色五月| 国产无遮挡又黄又爽| 三级片自拍| 欧美一级三级| 极品av| 久久久国产精品黄毛片| 91视频在线免费观看app| 中文无码第一页| 黄色在线免费| 亚洲无码三级片在线观看| 精品人伦一区二区三区| 欧美A片视频| 亚洲中文无码在线观看| 久草福利网| 99精品视频在线| 九一久色| 在线看片你懂的| 日韩在线观看网站| 三级91| 五月天婷婷视频| 日本天堂网在线观看| 亚洲视频免费在线播放| 亚洲中文字幕久久日| 四虎影成人精品A片| 丁香五月婷婷综合| 1024手机在线视频| 成人超碰| 影音先锋人妻资源| 精品国产重口乱子伦| 成人三级片在线观看| 91日韩视频在线| 欧美日韩一区在线| 色国产视频| 操B网址| 国偷自产视频一区二区久| 好男人WWW一区二区三区| 亚洲中字幕新| 久久精品久| GOGO人体做爰大胆视频| www激情| 乌克兰毛片| 人人操人人妻人人| 91欧美日韩综合| 3D动漫精选啪啪一期二期三期| 69视频免费观看| 青青草资源站| 中日韩特黄A片免费视频| 操逼视频在线观看| 成人毛片18女人毛片真水| 欧美大香蕉视频| 毛片网站视频| 在线播放亚洲| 日本婷婷| 无码视频免费| 日韩精品无码电影| 午夜精品久久久久久久99老熟妇| 骚逼影视| 殴美色色网| 成人黄色性爱视频| 国产日韩性爱视频| 特级婬片A片AAA毛片AA做头| 欧美不卡在线视频| 中文字幕天天干| 西西西444www无码视频| 无码视频一区二区三区| 2020人妻中文字幕| 色婷婷一区二区| 日韩无码视频播放| 強姦婬片A片AAA毛片Mⅴ| www免费视频| 亚洲成人黄色电影| 日韩精品免费在线观看| 草久精品| 97精品在线视频| 最新中文字幕无码| 久久婷婷国产| 亚洲69v久久久无码精品| 天天肏| 26uuu亚洲| 国产免看一级a一片成人aⅴ| 嫩草AV| 精品91在线视频| 欧美在线播放| 中文子幕免费毛片| 免费欧美三级片| 亚洲天堂视频在线| 久久久久亚洲AV无码网影音先锋| 国产AV影院| 婷婷五月天色色| 成年人视频在线观看免费| 嫩草在线观看| 久久午夜无码鲁丝| 99re6热在线精品视频功能| 中文字幕在线观看高清| 久艹AV| 西西人体大胆ww4444| 欧美69p| 亚洲vs天堂vs成人vs无码| 97人妻人人揉人人躁人人| 国产成人片在线观看| 男女爱爱动态图| 拍真实国产伦偷精品| 婷婷成人综合网| 日韩三级视频| 伊人狠狠蜜桃亚洲综合| 日本免费在线黄色视频| 在线观看无码视频| 欧美日韩视频在线播放| 免费看黄色的网站| 日韩女人性爱| 免费AA片| 亚洲大片在线观看| 免费在线国产| 国产三级无码| 99re免费视频| www.97cao| 激情片AAA| 久久男人网| 日韩欧美在中文| 国产精品免费人成网站酒店| 久草社区| 欧美一区不卡| 91中文字幕网| 久久久国产一区二区三区| 日本成人视频| 成人欧美精品区二区三| 五月激情婷婷网| 浮力影院久久| 国产成人AⅤ| 亚洲调教| 欧美日韩字幕| 少妇搡BBBB搡BBB搡打电话| 婷婷久久五月| 久久久久久久网站| 无码av网| 免费性爱视频| 2014天堂网| 国产作爱| 国产高清无码福利| 蜜芽av在线观看| 欧美一卡二卡| 亚洲无码一二三区| 免费在线黄色视频| 超碰97人人爱| 青青草99热| 久久免费精品| 黄a网站| 激情免费视频| 亚洲偷拍视频| 人妻体体内射精一区二区| 91网站18| 亚洲无码在线免费观看视频| 一区二区三区免费在线| 91欧美性爱| 在线A片免费观看| 天天日很很日| 日本无码一区二区三三| 特黄aaaaaaaa真人毛片| 黄色免费看| 免费看黄色视频的网站| 无码激情18激情视频| 老司机无码| 无码秘蜜桃一区二区| 日韩城人免费| 免费黄片网站在线观看| 欧美午夜无码| 91人人妻人人操| 91免费成人视频| 青青草大香蕉在线| 欧美视频免费操逼图。| 99无码秘蜜桃人妻一区二区三区| 西西人体大胆ww4444多少集 | www.伊人| 蜜桃av色偷偷av老熟女| 亚洲视频黄色| 九九自拍视频| 国产九九九视频| AV成人无码| 日韩无码破解| 最新免费毛片| 狠狠的操| 午夜国产视频| 色婷婷丁香五月天| 一级特黄大片录像i| 天天干天天日天天色| 欧美级毛片一进一出夜本色| 久久久久极品| a网站在线| 中文无码影院| 岛国无码AV在线观看| 大逼影院| 91久久久久久久91| 超碰中文在线| 亚洲s在线| 无码av无码AV| 久久精品大屁股| 91综合在线| 自拍偷拍第一页| 无码电影网站| 国产乱码一区二区三区四区在线| 久久无码一区二区三区| 免费看的黄色视频| 99精品视频免费看| 午夜电影福利| 蜜桃视频一区二区三区四区使用方法 | 国产色无码网站www色视频| 小黄片免费在线观看| 亚洲性爱一区二区| 午夜成人视频在线观看| 蜜桃网站在线观看| 北条麻妃99精品| 国产日韩欧美在线播放| 91视频国产精品| 探花视频在线观看| 看黄片网站| 欧美色视频在线观看| 在线免费观看无码| 欧美日韩第一页| 无码爱爱视频| 内射极品美女| 91久久国产性奴调教| 婷婷精品国产a久久综合| 欧美日批| 一本道高清无码视频| 91乱子伦国产乱子伦!| 激情五月天成人| 久久黄色网| 免费一级黄色片| 99热在线观看| 午色婷婷国产无码| 高清无码不卡AV| 国产一二三区在线| 精品久久久无码| 欧美日韩在线观看中文字幕| 蜜桃视频日韩|