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

也來盤盤前端腳手架的那些事兒

開發(fā) 前端
在上半年的一個項目中需要自定義一個腳手架,來幫助小伙伴們提高開發(fā)效率,統(tǒng)一代碼輸出質(zhì)量,并解決一些使用上的問題。

[[286793]]

本來早就想寫這篇文章的,由于有其他事情耽擱了(可能還是因?yàn)樘珣校屯系搅爽F(xiàn)在,如果再不記下來,估計會拋到九霄云外了。

NodeJs的出現(xiàn),讓前端工程化的理念不斷深入,正在向正規(guī)軍靠近。先是帶來了Gulp、Webpack等強(qiáng)大的構(gòu)建工具,隨后又出現(xiàn)了vue-cli和create-react-app等完善的腳手架,提供了完整的項目架構(gòu),讓我們可以更多的關(guān)注業(yè)務(wù),而不必在項目基礎(chǔ)設(shè)施上花費(fèi)大量時間。

但是,這些現(xiàn)成的腳手架未必就能滿足我們的業(yè)務(wù)需求,也未必是最佳實(shí)踐,這時我們就可以自己來開發(fā)一個腳手架。當(dāng)然,這其實(shí)很簡單,利用npm上現(xiàn)成的輪子就可以搞定,這里做個記錄,僅當(dāng)備忘,以拋磚引玉。

緣起

在上半年的一個項目中需要自定義一個腳手架,來幫助小伙伴們提高開發(fā)效率,統(tǒng)一代碼輸出質(zhì)量,并解決一些使用上的問題,當(dāng)然也是為了裝裝逼。

在使用腳手架方式構(gòu)建之前,我們遇到了這幾個問題:

  •  每個項目創(chuàng)建的時候,需要去Git倉庫拉取項目模板或者拷貝之前的項目,這樣做有兩個問題
    •   從Git拉取項目后,由于部分人員是有推送權(quán)限的,如果他誤操作將私有項目中的修改推送到了模板倉庫,可能會破壞Git上的項目模板
    •   從之前項目拷貝就無法獲取最新的項目模板,這就導(dǎo)致有些問題明明在最新的模板中已經(jīng)修復(fù),卻在新項目中依然存在
  •  項目模板需要填寫一些配置信息,開發(fā)人員很容易忘記填寫

所以我們來解決這些問題,思路如下:

  •  從Git上拉取最新模板,最后干掉Git倉庫信息,切斷和遠(yuǎn)程倉庫的關(guān)聯(lián)
  •  在初始化時,通過問答方式強(qiáng)制讓使用者輸入配置信息,再根據(jù)配置信息生成配置文件,有點(diǎn)類似VueCli初始化項目那樣。

當(dāng)然,除了上述需求,我們還可以再做些額外工作:

  •  拉取完成后自動安裝項目依賴,并打開編輯器
  •  提供幫助信息及常用命令查看
  •  發(fā)布到NPM,所有人員都可以直接全局安裝使用
  •  ...

急急如律令

實(shí)現(xiàn)可執(zhí)行模塊

首先,我們需要創(chuàng)建一個項目,這里就叫yncms-template-cli, 項目結(jié)構(gòu)如下: 

  1. - commands  // 此文件夾用于放置自定義命令  
  2. - utils  
  3. - index.js  // 項目入口  
  4. - readme.md 

為了測試,我們先在index.js放點(diǎn)內(nèi)容: 

  1. #!/usr/bin/env node  
  2. // 必須在文件頭添加如上內(nèi)容指定運(yùn)行環(huán)境為node  
  3. console.log('hello cli'); 

對于一般的nodejs項目,我們直接使用node index.js就可以了,但是這里是腳手架,肯定不能這樣。我們需要把項目發(fā)布到npm,用戶進(jìn)行全局安裝,然后就可以直接使用我們自定義的命令,類似yncms-template這樣。

所以,我們需要將我們的項目做下改動,首先在packge.json中添加如下內(nèi)容: 

  1. "bin": {  
  2.    "yncms-template": "index.js"  
  3.  }, 

這樣就可以將yncms-template定義為一個命令了,但此時僅僅只能在項目中使用,還不能作為全局命令使用,這里我們需要使用npm link將其鏈接到全局命令,執(zhí)行成功后在你的全局node_modules目錄下可以找到相應(yīng)文件。然后輸入命令測試一下,如果出現(xiàn)如下內(nèi)容說明第一步已經(jīng)成功一大半了: 

  1. PS E:\WorkSpace\yncms-template-cli> yncms-template  
  2. hello cli 

但是,目前這個命令只有我們自己電腦可以用,要想其他人也能安裝使用,需要將它發(fā)布到npm,大致流程如下:

  1.  注冊一個npm賬戶,已有賬戶的可以跳過這一步
  2.  使用npm login登錄,需要輸入username、password、email
  3.  使用npm public發(fā)布

這一步比較簡單,不多說,但是請注意如下幾點(diǎn):

  •  使用了nrm的需要先將源切換到npm官方源
  •  package.json中有幾個字段需要完善:
    •   name為發(fā)布的包名,不能和npm已有的包重復(fù)
    •   version為版本信息,每次發(fā)布都必須要比線上的版本高
    •   homepage、bugs、repository也可以添加上,對應(yīng)如下頁面   

  • 在readme.md加入腳手架介紹及使用方法,方便他人使用。如果需要在文檔中加入徽標(biāo),展示腳手架的下載次數(shù)之類的,可以在這里生成。

發(fā)布成功后,需要等待一會兒才可以在npm倉庫搜索到。

創(chuàng)建命令

既然是腳手架,肯定不能只讓它輸出一段文字吧,我們還需要定義一些命令,用戶在命令行輸入這些命令和參數(shù),腳手架會做出對應(yīng)的操作。這里不需要我們自己去解析這些輸入的命令和參數(shù),有現(xiàn)成的輪子(commander)可以使用,完全可以滿足我們的需要。

幫助(--help)

安裝好commander后,我們將index.js中內(nèi)容改為如下: 

  1. #!/usr/bin/env node  
  2. const commander = require('commander');  
  3. // 利用commander解析命令行輸入,必須寫在所有內(nèi)容最后面  
  4. commander.parse(process.argv); 

這時,雖然我們沒有定義任何命令,但是commander內(nèi)部給我們定義了一個幫助命令--help(簡寫-h): 

  1. PS E:\WorkSpace\yncms-template-cli> yncms-template -h  
  2. Usage: index [options]  
  3. Options:  
  4.   -h, --help  output usage information 

版本(--version)

接下來,我們再創(chuàng)建一個查詢版本的命令參數(shù),在index.js增加如下內(nèi)容: 

  1. // 查看版本號  
  2. commander.version(require('./package.json').version); 

這樣,我們在命令行就可以查看版本號了: 

  1. PS E:\WorkSpace\yncms-template-cli> yncms-template -V  
  2. 1.0.10  
  3. PS E:\WorkSpace\yncms-template-cli> yncms-template --version  
  4. 1.0.10 

默認(rèn)參數(shù)是大寫V,如果需要改成小寫,將上面內(nèi)容做如下改動即可: 

  1. // 查看版本號  
  2. commander  
  3.     .version(require('./package.json').version)  
  4.     .option('-v,--version', '查看版本號');  
  1. PS E:\WorkSpace\yncms-template-cli> yncms-template -h  
  2. Usage: index [options]  
  3. Options:  
  4.   -V, --version  output the version number  
  5.   -h, --help     output usage information 

init子命令

接下來,我們來定義一個init命令,如yncms-template init test。

在index.js中增加如下內(nèi)容: 

  1. commander  
  2.     .command('init <name>') // 定義init子命令,<name>為必需參數(shù)可在action的function中接收,如需設(shè)置非必需參數(shù),可使用中括號  
  3.     .option('-d, --dev', '獲取開發(fā)版') // 配置參數(shù),簡寫和全寫中使用,分割  
  4.     .description('創(chuàng)建項目') // 命令描述說明  
  5.     .action(function (name, option) { // 命令執(zhí)行操作,參數(shù)對應(yīng)上面的設(shè)置的參數(shù)  
  6.         // 我們需要執(zhí)行的所有操作,都在這里完成  
  7.         console.log(name);  
  8.         console.log(option.dev);  
  9.     }); 

現(xiàn)在測試一下: 

  1. PS E:\WorkSpace\yncms-template-cli> yncms-template init test -d  
  2. test  
  3. true 

commander具體的用法,請自行查看官方文檔

如此,一個自定義命令雛形就算完成了,然還有幾件事情要做:

  •  實(shí)現(xiàn)init命令具體執(zhí)行的操作,下面會有單獨(dú)部分來說。
  •  為了方便維護(hù),將命令action拆分到commands文件夾中

拉取項目

上面,我們定義了init命令,但是并沒有達(dá)到初始化項目的目的,接下來我們就實(shí)現(xiàn)一下。

一般來說,項目模板有兩種處理方式:

  •  將項目模板和本腳手架放在一起,好處是用戶安裝腳手架后,模板在本地,初始化會比較快;缺點(diǎn)是項目模板更新比較麻煩,因?yàn)楹湍_手架耦合在一起了
  •  將項目放置到單獨(dú)的GIT倉庫,好處是模板更新比較簡單,因?yàn)槭窍嗷オ?dú)立的,只需要維護(hù)模板自己的倉庫即可,另外可以控制拉取權(quán)限,因?yàn)槿绻撬接许椖浚敲礇]有權(quán)限的人員是無法拉取成功的;缺點(diǎn)就是每次初始化都要去GIT拉取,可能會慢點(diǎn),不過影響不大,所以建議選擇此種方式

首先,我們利用download-git-repo封裝一個clone方法,用于從git拉取項目。 

  1. // utils/clone.js  
  2. const download = require('download-git-repo');  
  3. const symbols = require('log-symbols');  // 用于輸出圖標(biāo)  
  4. const ora = require('ora'); // 用于輸出loading  
  5. const chalk = require('chalk'); // 用于改變文字顏色  
  6. module.exports = function (remote, name, option) {  
  7.     const downSpinner = ora('正在下載模板...').start();  
  8.     return new Promise((resolve, reject) => {  
  9.         download(remote, name, option, err => {  
  10.             if (err) { 
  11.                  downSpinner.fail();  
  12.                 console.log(symbols.error, chalk.red(err));  
  13.                 reject(err);  
  14.                 return;  
  15.             };  
  16.             downSpinner.succeed(chalk.green('模板下載成功!'));  
  17.             resolve();  
  18.         });  
  19.     });  
  20.   };  
  1. // commands/init.js  
  2. const shell = require('shelljs');  
  3. const symbols = require('log-symbols');  
  4. const clone = require('../utils/clone.js');  
  5. const remote = 'https://gitee.com/letwrong/cli-demo.git' 
  6. let branch = 'master' 
  7. const initAction = async (name, option) => {  
  8.     // 0. 檢查控制臺是否可以運(yùn)行`git `,  
  9.     if (!shell.which('git')) {  
  10.         console.log(symbols.error, '對不起,git命令不可用!');  
  11.         shell.exit(1);  
  12.     }  
  13.     // 1. 驗(yàn)證輸入name是否合法  
  14.     if (fs.existsSync(name)) {  
  15.         console.log(symbols.warning,`已存在項目文件夾${name}!`);  
  16.         return;  
  17.     }  
  18.     if (name.match(/[^A-Za-z0-9\u4e00-\u9fa5_-]/g)) {  
  19.         console.log(symbols.error, '項目名稱存在非法字符!');  
  20.         return;  
  21.     }  
  22.     // 2. 獲取option,確定模板類型(分支)  
  23.     if (option.dev) branch = 'develop' 
  24.     // 4. 下載模板  
  25.     await clone(`direct:${remote}#${branch}`, name, { clone: true });  
  26. };  
  27. module.exports = initAction

測試一下,不出意外就可以成功拉取項目了。

這里拉取的項目是和遠(yuǎn)程倉庫關(guān)聯(lián)的,我們需要將其刪掉(由于我們項目是svn管理,所以直接把.git文件夾刪掉,如果使用git的話,可以git init初始化即可),清理掉一些多余文件: 

  1. // commands/init.js  
  2. // 5. 清理文件  
  3. const deleteDir = ['.git', '.gitignore', 'README.md', 'docs']; // 需要清理的文件  
  4. const pwd = shell.pwd();  
  5. deleteDir.map(item => shell.rm('-rf', pwd + `/${name}/${item}`)); 

來點(diǎn)個性化

在上述過程中,我們實(shí)現(xiàn)了一個腳手架的基本功能,大致分為三個流程(拉取模板->創(chuàng)建項目->收尾清理),也解決了上面我項目中遇到的第一個問題。接下來,我們就來看下第二個問題如何解決。

解決的思路就是在創(chuàng)建項目的時候,就通過命令行強(qiáng)制要求開發(fā)人員輸入對應(yīng)的配置,然后自動寫入配置文件,這樣就可以有效避免忘記填寫的尷尬。當(dāng)然通過這種方式也可以實(shí)現(xiàn)根據(jù)用戶的輸入來動態(tài)初始化項目,達(dá)到個性化的目的。

這里我們直接使用現(xiàn)成的輪子inquirer就可以搞定,效果和VueCli創(chuàng)建項目一樣,支持很多類型,比較強(qiáng)大,也比較簡單,具體用法看官方文檔就可以了。這里我直接上代碼,在第4步(下載模板)前面增加如下: 

  1. // init.js  
  2. const inquirer = require('inquirer');  
  3. // 定義需要詢問的問題  
  4. const questions = [  
  5.   {  
  6.     type: 'input',  
  7.     message: '請輸入模板名稱:',  
  8.     name: 'name',  
  9.     validate(val) {  
  10.       if (!val) return '模板名稱不能為空!';  
  11.       if (val.match(/[^A-Za-z0-9\u4e00-\u9fa5_-]/g)) return '模板名稱包含非法字符,請重新輸入';  
  12.       return true;  
  13.     }  
  14.   },  
  15.   {  
  16.     type: 'input',  
  17.     message: '請輸入模板關(guān)鍵詞(;分割):', 
  18.      name: 'keywords'  
  19.   },  
  20.   {  
  21.     type: 'input',  
  22.     message: '請輸入模板簡介:',  
  23.     name: 'description'  
  24.   },  
  25.   {  
  26.     type: 'list',  
  27.     message: '請選擇模板類型:',  
  28.     choices: ['響應(yīng)式', '桌面端', '移動端'],  
  29.     name: 'type'  
  30.   },  
  31.   {  
  32.     type: 'list',  
  33.     message: '請選擇模板分類:',  
  34.     choices: ['整站', '單頁', '專題'],  
  35.     name: 'category'  
  36.   },  
  37.   {  
  38.     type: 'input',  
  39.     message: '請輸入模板風(fēng)格:',  
  40.     name: 'style'  
  41.   },  
  42.   { 
  43.      type: 'input',  
  44.     message: '請輸入模板色系:',  
  45.     name: 'color'  
  46.   },  
  47.   {  
  48.     type: 'input',  
  49.     message: '請輸入您的名字:', 
  50.     name: 'author'  
  51.   }  
  52. ];  
  53. // 通過inquirer獲取到用戶輸入的內(nèi)容  
  54. const answers = await inquirer.prompt(questions);  
  55. // 將用戶的配置打印,確認(rèn)一下是否正確  
  56. console.log('------------------------');  
  57. console.log(answers);  
  58. let confirm = await inquirer.prompt([  
  59.     {  
  60.         type: 'confirm',  
  61.         message: '確認(rèn)創(chuàng)建?',  
  62.         default: 'Y',  
  63.         name: 'isConfirm'  
  64.     }  
  65. ]);  
  66. if (!confirm.isConfirm) return false; 

獲取到用戶輸入的配置以后,就可以寫入配置文件或者做個性化的處理了,這個太簡單,我這里就不贅述了。

錦上添花

到這里,一個完全滿足需求的腳手架就完成了,但是作為一個有追求的程序員,我們可以在界面和易用性上面再做點(diǎn)什么:

  •  為異步操作加上loding動畫,可以直接使用ora  
  1. const installSpinner = ora('正在安裝依賴...').start();  
  2. if (shell.exec('npm install').code !== 0) {  
  3.     console.log(symbols.warning, chalk.yellow('自動安裝失敗,請手動安裝!'));  
  4.     installSpinner.fail(); // 安裝失敗  
  5.     shell.exit(1);  
  6.  
  7. installSpinner.succeed(chalk.green('依賴安裝成功!')); 
  •  在操作成功或者失敗給出圖標(biāo)提示,使用log-symbols    

  • 可以給文字加點(diǎn)顏色,同理用現(xiàn)成的輪子Chalk    

  • 在安裝依賴或者其他耗時比較長的時候,用戶可能會把終端切到后臺,這時我們的操作完成后可以使用node-notifier發(fā)出系統(tǒng)通知給予用戶提示。 
  1. notifier.notify({  
  2.     title: 'YNCMS-template-cli',  
  3.     icon: path.join(__dirname, 'coulson.png'),  
  4.     message: ' ♪(^∀^●)ノ 恭喜,項目創(chuàng)建成功!'  
  5. }); 
  •  在創(chuàng)建項目的時候,我們可能會需要執(zhí)行一些shell命令,可以使用shelljs來完成,例如我們要在項目創(chuàng)建結(jié)束后打開vscode并退出終端 
  1. // 8. 打開編輯器  
  2. if (shell.which('code')) shell.exec('code ./');  
  3. shell.exit(1); 

結(jié)語

到這里,會發(fā)現(xiàn)開發(fā)一個腳手架其實(shí)很簡單,都是使用現(xiàn)成的輪子就可以搞定,不曉得哪位大牛說過玩NodeJS就是玩輪子。

除了上述方法,我們也可以直接通過大名鼎鼎的Yeoman來創(chuàng)建,不過個人覺得沒必要,畢竟這玩意也不難。

一個好的腳手架應(yīng)該是能夠解決工作中遇到的問題,提高開發(fā)效率的。 

 

責(zé)任編輯:龐桂玉 來源: segmentfault
相關(guān)推薦

2017-01-04 09:47:38

聯(lián)想企業(yè)網(wǎng)盤

2021-01-07 05:34:07

腳手架JDK緩存

2021-09-22 08:26:31

前端腳手架開源項目

2016-08-10 14:59:41

前端Javascript工具

2016-09-07 15:35:06

VueReact腳手架

2025-05-16 07:24:41

Springkafka腳手架

2021-12-23 10:35:32

SpringCloud腳手架架構(gòu)

2022-05-23 08:34:08

微前端微服務(wù)開發(fā)

2020-03-20 08:32:41

物聯(lián)網(wǎng)腳手架傳感器

2021-05-21 05:22:52

腳手架工具項目

2018-08-30 16:08:37

Node.js腳手架工具

2022-04-24 11:33:47

代碼管理工程

2018-06-11 14:39:57

前端腳手架工具node.js

2023-11-21 17:36:04

OpenFeignSentinel

2020-12-17 12:43:43

前端gup4.0webpack

2014-08-15 09:36:06

2024-03-11 13:18:00

RustClap項目

2022-01-14 14:09:11

腳手架代碼自定義

2020-06-29 11:35:02

Spring BootJava腳手架

2021-10-08 06:10:43

前端技術(shù)Vue
點(diǎn)贊
收藏

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

91精品国产综合久久香蕉的用户体验 | 欧美性生交大片| 欧美电影免费观看高清完整| 欧美国产亚洲另类动漫| 2019国产精品视频| 亚洲精品男人天堂| 日韩理论片av| 亚洲精品在线免费观看视频| 久久久精品麻豆| 青青草原av在线| 国产人妖乱国产精品人妖| 91久久久久久国产精品| 国产成人自拍视频在线| 99re6这里只有精品| 亚洲高清福利视频| 婷婷激情5月天| 成人影院大全| 夜夜嗨av一区二区三区| 五月天亚洲综合情| 熟妇高潮一区二区三区| 国产自产高清不卡| 国产精品18久久久久久麻辣| 久久综合综合久久| 日韩激情图片| 日韩高清不卡av| 伦伦影院午夜理论片| 另类中文字幕国产精品| 偷偷要91色婷婷| 日韩一二区视频| www.亚洲资源| 91在线porny国产在线看| 亚洲影院在线看| 最好看的日本字幕mv视频大全| 亚洲国产二区| 美女av一区二区| 美国美女黄色片| 蜜桃精品wwwmitaows| 亚洲精品在线一区二区| 一区二区三区人妻| 成人自拍视频| 伊人久久大香伊蕉在人线观看热v| 成人免费高清视频在线观看| 成人免费看黄网站| 中文字幕在线播出| 日韩av在线播放中文字幕| 97热精品视频官网| 国产乡下妇女做爰毛片| 午夜国产精品视频免费体验区| 尤物yw午夜国产精品视频| 日本少妇高潮喷水xxxxxxx| 美女福利一区| 亚洲精品在线三区| fc2成人免费视频| 91在线一区| 欧美一级片在线观看| а 天堂 在线| 国产精品一区二区三区www| 在线成人av影院| 日韩av片免费观看| 国产成人久久精品一区二区三区| 欧美日韩极品在线观看一区| 国产精品区在线| 日日夜夜亚洲精品| 欧美高清一级片在线| 手机在线国产视频| 奇米一区二区| 精品1区2区在线观看| 中国xxxx性xxxx产国| 欧美日韩导航| 亚洲图片欧美午夜| 黑人と日本人の交わりビデオ| 成人在线视频免费观看| 日韩中文字幕精品视频| 国产一二三四区| 亚洲午夜视频| 欧美在线国产精品| 中文字幕久久熟女蜜桃| 韩国欧美国产一区| 国产传媒一区| 清纯唯美亚洲色图| 国产精品网站在线观看| 一级特黄妇女高潮| 成人免费观看在线观看| 色呦呦国产精品| 亚洲欧美中文日韩在线| 久草青青在线观看| 成人在线黄色| 日韩视频国产视频| 中文字幕一区二区久久人妻网站| 精品国产一区二区三区小蝌蚪| 久久色免费在线视频| 日韩av一二三区| 日韩av在线播放中文字幕| 成人黄色影片在线| 天堂av一区二区三区| 亚洲国产成人在线| 国产精品久久国产| 中文字幕av一区二区三区佐山爱| 7777精品伊人久久久大香线蕉| 久久人妻少妇嫩草av蜜桃| 亚洲资源网你懂的| 九九热精品视频| 中文字幕一区二区人妻视频| 国产伦精品一区二区三区免费| 精品无人区一区二区三区| 婷婷在线视频| 福利微拍一区二区| 亚洲一区二区三区四区精品| 日韩av系列| 久久中文字幕在线视频| 国产黄网在线观看| 国产99久久久国产精品潘金| 亚洲狠狠婷婷综合久久久| heyzo高清中文字幕在线| 欧美日本精品一区二区三区| aaaaaav| 国产精品magnet| 国产精品美女主播在线观看纯欲| 色呦呦中文字幕| 亚洲欧美国产毛片在线| 亚洲不卡视频在线| 天天久久夜夜| 欧美日韩成人在线观看| 亚洲一卡二卡在线观看| 久久先锋资源网| 国产手机免费视频| 警花av一区二区三区| 中文精品99久久国产香蕉| 天天综合网久久综合网| 成人性视频网站| 国产人妻互换一区二区| 欧美videos粗暴| 国产亚洲一区精品| 特级做a爱片免费69| 成人一区二区三区视频在线观看| 91视频成人免费| 激情小说亚洲| 国产一区二区三区视频在线观看| 日韩手机在线观看| 成人激情文学综合网| 国产91porn| 国产精品高清一区二区| 日韩中文有码在线视频| 懂色av蜜臀av粉嫩av喷吹| 久久免费午夜影院| 亚洲国产精品久久久久婷蜜芽| 福利电影一区| 国内精品免费午夜毛片| 精品国产伦一区二区三| 一区二区不卡在线视频 午夜欧美不卡在| 中日韩av在线播放| 97精品国产一区二区三区 | 中文字幕一区二区三区四区五区六区| 国产成人免费9x9x人网站视频| 亚洲色图校园春色| 秋霞av一区二区三区| 久久精品网站免费观看| 日韩欧美xxxx| 欧美日韩中文一区二区| 国产精品女主播| 91caoporm在线视频| 欧美日韩精品专区| 欧美h片在线观看| 国产一区二区毛片| av一区二区三区免费观看| youjizz亚洲| 97在线视频免费看| 黄色av网站在线免费观看| 日本韩国精品在线| 国产精品1区2区3区4区| 国产综合久久久久影院| 久久福利一区二区| 美女视频亚洲色图| 国产精品6699| 中文字幕免费高清电视剧网站在线观看| 日韩欧美在线影院| 国产视频91在线| 国产日韩欧美电影| 亚洲国产综合av| 99亚洲精品| 亚洲乱码国产乱码精品天美传媒| 精品国产鲁一鲁****| 91黄色8090| 日韩大片在线永久免费观看网站| 欧美一区二区二区| 精品欧美一区二区三区免费观看| 中文字幕av资源一区| 国产一级二级av| 麻豆精品91| 欧美日韩中文字幕在线播放| 欧美做受69| 成人在线免费观看视视频| 国内精彩免费自拍视频在线观看网址| 一区二区欧美亚洲| 高清毛片aaaaaaaaa片| 日本高清免费不卡视频| 性欧美疯狂猛交69hd| 97国产精品videossex| 少妇一级淫免费播放| 亚洲三级电影在线观看| 亚洲一一在线| 亚洲区小说区图片区qvod按摩| 成人亚洲欧美一区二区三区| 国产高清不卡| 久久久亚洲国产天美传媒修理工| 香蕉视频在线免费看| 精品一区二区三区电影| 国产人妖一区二区| 色诱亚洲精品久久久久久| 精品无码黑人又粗又大又长| 国产精品久久毛片av大全日韩| 粉嫩av懂色av蜜臀av分享| 久久激五月天综合精品| 国产又黄又大又粗视频| 欧美久久99| 久久久国产精华液999999| 婷婷精品在线| 国产精品午夜av在线| 亚洲视频资源| 国产精品美女视频网站| 国产精品一区二区av影院萌芽| 欧美激情久久久久| 国产调教视频在线观看| 一区二区三区天堂av| 三级视频网站在线| 亚洲第一中文字幕在线观看| 99热这里只有精品在线| 欧美日韩国产美女| 国产伦精品一区二区三区视频我| 亚洲电影第三页| 麻豆91精品91久久久| 日韩码欧中文字| 日本一二三不卡视频| 色哟哟免费视频| 黑人巨大精品欧美一区| www.亚洲高清| 美女脱光内衣内裤视频久久网站| 国产一区二区三区精彩视频| 国产成人在线小视频| 成人av福利| 日韩中文字幕久久| 玖玖综合伊人| 久久av综合| 精品一区二区日本| 盗摄系列偷拍视频精品tp| 91综合免费在线| 国产免费区一区二区三视频免费| 国产精品视频区| 国产精品三p一区二区| 日韩精品久久久久| 亚洲精品久久久久avwww潮水| 678五月天丁香亚洲综合网| 亚洲一区二区人妻| 欧美日韩一区二区三区高清 | 亚洲高清久久久| 久久国产精品波多野结衣av| 一区二区三区欧美日| 亚洲熟妇国产熟妇肥婆| 色999久久久精品人人澡69| 国产精品福利在线| 99欧美精品| 国产一区视频在线| 爱情电影网av一区二区| 91美女片黄在线观| 欧美大片91| 不卡一卡2卡3卡4卡精品在| 136福利精品导航| 欧美色另类天堂2015| 国产三级av片| 色久综合一二码| 在线免费观看视频网站| 欧美一区二区视频在线观看2020| av一级黄色片| 日韩免费高清视频| 成人黄色在线观看视频| 亚洲第一福利网| 日本大片在线观看| 中文字幕亚洲字幕| 怡红院在线播放| 欧美有码在线视频| 日韩国产大片| 国产一区二区无遮挡| 国产一区二区精品久| 久久免费看毛片| 在线观看的日韩av| 婷婷激情四射五月天| 国产一区二区在线视频| 日本黄色免费观看| 国产精品久久久久久亚洲伦| 久视频在线观看| 欧美亚洲免费在线一区| 午夜精品久久久久久久96蜜桃| 亚洲欧美一区二区激情| 2024最新电影免费在线观看 | 青花影视在线观看免费高清| 五月天网站亚洲| 99国产精品久久久久久久成人| 亚洲精品乱码久久久久久按摩观| h视频网站在线观看| 久久久久久国产精品久久| 国产成人免费9x9x人网站视频| 不卡一区二区三区视频| 日本大胆欧美| 久在线观看视频| 国产一区二区不卡在线| 好吊视频在线观看| 亚洲午夜电影在线观看| 亚洲在线视频播放| 亚洲欧洲午夜一线一品| 日本大片在线播放| 国产精品久久视频| 牲欧美videos精品| 欧美精品在欧美一区二区| 蜜桃视频一区二区三区在线观看| 午夜不卡久久精品无码免费| 亚洲欧美日韩成人高清在线一区| 99re这里只有精品在线| 亚洲成年人影院在线| 大片免费在线看视频| 国产精品久久久久久久久免费看 | 国产一区视频在线看| 国产人妻大战黑人20p| 午夜精品久久久久久| 草逼视频免费看| 久久九九国产精品怡红院| 色老太综合网| 欧美精品亚洲| 国产精品女主播一区二区三区| 欧美人与性动交α欧美精品| 一区二区中文字幕在线| 曰批又黄又爽免费视频| 亚洲人在线视频| 精品极品在线| 国产精品久久波多野结衣| 综合久久综合| 国模大尺度视频| 亚洲色图.com| 国产视频在线观看视频| 久久精品国产亚洲一区二区| 欧美大片网站| 亚洲一区尤物| 狠狠色伊人亚洲综合成人| 在线观看天堂av| 欧美日韩精品免费观看视频| 亚洲视频tv| 国产欧美精品日韩| 99久久精品费精品国产风间由美| 在线观看亚洲色图| 国产精品久久久久久福利一牛影视 | 大桥未久恸哭の女教师| 亚洲一区二区欧美激情| 亚洲高清精品视频| 亚州精品天堂中文字幕| 久久porn| 欧美激情成人网| 国产校园另类小说区| 综合久久中文字幕| 日韩一区二区欧美| 日韩欧美久久| 一本久道高清无码视频| 92精品国产成人观看免费| 亚洲第一在线播放| 亚洲亚裔videos黑人hd| 久久久久久一区二区三区四区别墅| 中文字幕日韩一区二区三区| 国产精品456露脸| 国产污污视频在线观看| 亚洲天堂免费在线| 日韩综合久久| 分分操这里只有精品| wwwwww.欧美系列| 久久久久精彩视频| 另类视频在线观看| 盗摄牛牛av影视一区二区| 久久久久久久久久久久久国产精品 | 亚洲a级在线播放观看| 精品动漫3d一区二区三区免费| theav精尽人亡av| 精品视频全国免费看| 亚洲91av| 欧美精品一区三区在线观看| 美女精品一区二区| 久久久久成人精品无码| 亚洲欧美在线一区二区| 精品91福利视频| 国产成人精品视频免费看| 国产精品乱码人人做人人爱| 亚洲精品18在线观看| 日韩av片永久免费网站| 91精品一区二区三区综合| 精品视频站长推荐| 欧美亚洲日本国产| av中文在线资源| 亚洲欧洲精品在线 | 日本中文在线一区| 亚洲av鲁丝一区二区三区| 亚洲人成网站免费播放| 欧美日本三级| 亚洲狼人综合干| 亚洲国产裸拍裸体视频在线观看乱了 |