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

從一個優質開源項目來看前端架構

新聞 前端
系統架構師是一個最終確認和評估系統需求,給出開發規范,搭建系統實現的核心構架,并澄清技術細節、掃清主要難點的技術人員。

 [[407112]]

何為系統架構師?

  • 系統架構師是一個最終確認和評估系統需求,給出開發規范,搭建系統實現的核心構架,并澄清技術細節、掃清主要難點的技術人員。主要著眼于系統的“技術實現”。因此他/她應該是特定的開發平臺、語言、工具的大師,對常見應用場景能給出最恰當的解決方案,同時要對所屬的開發團隊有足夠的了解,能夠評估自己的團隊實現特定的功能需求需要的代價。系統架構師負責設計系統整體架構,從需求到設計的每個細節都要考慮到,把握整個項目,使設計的項目盡量效率高,開發容易,維護方便,升級簡單等

這是百度百科的答案

大多數人的問題

如何成為一名前端架構師?

  • 其實,前端架構師不應該是一個頭銜,而應該是一個過程。我記得掘金上有人寫過一篇文章: 《我在一個小公司,我把我們公司前端給架構了》 , (我當時還看成 《我把我們公司架構師給上了》 )
  • 我面試過很多人,從小公司出來(我也是從一個很小很小的公司出來,現在也沒在什么 BATJ ),最大的問題在于,覺得自己不是 leader ,就沒有想過如何去提升、優化項目,而是去研究一些花里胡哨的東西,卻沒有真正使用在項目中。(自然很少會有深度)
  • 在一個兩至三人的前端團隊小公司,你去不斷優化、提升項目體驗,更新迭代替換技術棧,那么你就是 前端架構師

正式開始

我們從一個比較不錯的項目入手,談談一個前端架構師要做什么

  • SpaceX-API
  • SpaceX-API 是什么?
  • SpaceX-API 是一個用于火箭、核心艙、太空艙、發射臺和發射數據的開源 REST API(并且是使用Node.js編寫,我們用這個項目借鑒無可厚非)

 為了閱讀的舒適度,我把下面的正文盡量口語化一點

先把代碼搞下來

  1. git clone https://github.com/r-spacex/SpaceX-API.git 
  • 一個優秀的開源項目搞下來以后,怎么分析它?大部分時候,你應該先看它的目錄結構以及依賴的第三方庫( package.json 文件)

找到 package.json 文件的幾個關鍵點:

  • main 字段(項目入口)
  • scripts 字段(執行命令腳本)
  • dependencies和devDependencies字段(項目的依賴,區分線上依賴和開發依賴,我本人是非常看中這個點,SpaceX-API也符合我的觀念,嚴格的區分依賴按照)
  1. "main""server.js"
  2.    "scripts": { 
  3.     "test""npm run lint && npm run check-dependencies && jest --silent --verbose"
  4.     "start""node server.js"
  5.     "worker""node jobs/worker.js"
  6.     "lint""eslint ."
  7.     "check-dependencies""npx depcheck --ignores=\"pino-pretty\"" 
  8.   }, 
  • 通過上面可以看到,項目入口為 server.js
  • 項目啟動命令為 npm run start
  • 幾個主要的依賴:

  1. "koa""^2.13.0"
  2.     "koa-bodyparser""^4.3.0"
  3.     "koa-conditional-get""^3.0.0"
  4.     "koa-etag""^4.0.0"
  5.     "koa-helmet""^6.0.0"
  6.     "koa-pino-logger""^3.0.0"
  7.     "koa-router""^10.0.0"
  8.     "koa2-cors""^2.0.6"
  9.     "lodash""^4.17.20"
  10.     "moment-range""^4.0.2"
  11.     "moment-timezone""^0.5.32"
  12.     "mongoose""^5.11.8"
  13.     "mongoose-id""^0.1.3"
  14.     "mongoose-paginate-v2""^1.3.12"
  15.     "eslint""^7.16.0"
  16.     "eslint-config-airbnb-base""^14.2.1"
  17.     "eslint-plugin-import""^2.22.1"
  18.     "eslint-plugin-jest""^24.1.3"
  19.     "eslint-plugin-mongodb""^1.0.0"
  20.     "eslint-plugin-no-secrets""^0.6.8"
  21.     "eslint-plugin-security""^1.4.0"
  22.     "jest""^26.6.3"
  23.     "pino-pretty""^4.3.0" 

  • 都是一些通用主流庫: 主要是koa框架,以及一些koa的一些中間件,monggose(連接使用mongoDB),eslint(代碼質量檢查)

這里強調一點,如果你的代碼需要兩人及以上維護,我就強烈建議你不要使用任何黑魔法,以及不使用非主流的庫,除非你編寫核心底層邏輯時候非用不可(這個時候應該只有你維護)

項目目錄 

 

 

 

  • 這是一套標準的 REST API, 嚴格分層
  • 幾個重點目錄 :

    • server.js 項目入口

    • app.js 入口文件

    • services 文件夾 => 項目提供服務層

    • scripts 文件夾 => 項目腳本

    • middleware 文件夾 => 中間件

    • docs 文件夾 =>文檔存放

    • tests 文件夾 => 單元測試代碼存放

    • .dockerignore docker的忽略文件

    • Dockerfile 執行docker build命令讀取配置的文件

    • .eslintrc eslint配置文件

    • jobs 文件夾 => 我想應該是對應檢查他們api服務的代碼,里面都是準備的一些參數然后直接調服務

逐個分析

從項目依賴安裝說起

  • 安裝環境嚴格區分開發依賴和線上依賴,讓閱讀代碼者一目了然哪些依賴是線上需要的

  1. "dependencies": { 
  2.     "blake3""^2.1.4"
  3.     "cheerio""^1.0.0-rc.3"
  4.     "cron""^1.8.2"
  5.     "fuzzball""^1.3.0"
  6.     "got""^11.8.1"
  7.     "ioredis""^4.19.4"
  8.     "koa""^2.13.0"
  9.     "koa-bodyparser""^4.3.0"
  10.     "koa-conditional-get""^3.0.0"
  11.     "koa-etag""^4.0.0"
  12.     "koa-helmet""^6.0.0"
  13.     "koa-pino-logger""^3.0.0"
  14.     "koa-router""^10.0.0"
  15.     "koa2-cors""^2.0.6"
  16.     "lodash""^4.17.20"
  17.     "moment-range""^4.0.2"
  18.     "moment-timezone""^0.5.32"
  19.     "mongoose""^5.11.8"
  20.     "mongoose-id""^0.1.3"
  21.     "mongoose-paginate-v2""^1.3.12"
  22.     "pino""^6.8.0"
  23.     "tle.js""^4.2.8"
  24.     "tough-cookie""^4.0.0" 
  25.   }, 
  26.   "devDependencies": { 
  27.     "eslint""^7.16.0"
  28.     "eslint-config-airbnb-base""^14.2.1"
  29.     "eslint-plugin-import""^2.22.1"
  30.     "eslint-plugin-jest""^24.1.3"
  31.     "eslint-plugin-mongodb""^1.0.0"
  32.     "eslint-plugin-no-secrets""^0.6.8"
  33.     "eslint-plugin-security""^1.4.0"
  34.     "jest""^26.6.3"
  35.     "pino-pretty""^4.3.0" 
  36.   }, 

項目目錄劃分

  • 目錄劃分,嚴格分層

  • 通用,清晰簡介明了,讓人一看就懂

正式開始看代碼

  • 入口文件, server.js 開始

    1. const http = require('http'); 
    2. const mongoose = require('mongoose'); 
    3. const { logger } = require('./middleware/logger'); 
    4. const app = require('./app'); 
    5.  
    6. const PORT = process.env.PORT || 6673
    7. const SERVER = http.createServer(app.callback()); 
    8.  
    9. // Gracefully close Mongo connection 
    10. const gracefulShutdown = () => { 
    11.   mongoose.connection.close(false, () => { 
    12.     logger.info('Mongo closed'); 
    13.     SERVER.close(() => { 
    14.       logger.info('Shutting down...'); 
    15.       process.exit(); 
    16.     }); 
    17.   }); 
    18. }; 
    19.  
    20. // Server start 
    21. SERVER.listen(PORT, '0.0.0.0', () => { 
    22.   logger.info(`Running on port: ${PORT}`); 
    23.  
    24.   // Handle kill commands 
    25.   process.on('SIGTERM', gracefulShutdown); 
    26.  
    27.   // Prevent dirty exit on code-fault crashes: 
    28.   process.on('uncaughtException', gracefulShutdown); 
    29.  
    30.   // Prevent promise rejection exits 
    31.   process.on('unhandledRejection', gracefulShutdown); 
    32. }); 
  • 幾個優秀的地方

    • 每個回調函數都會有聲明功能注釋

    • 像 SERVER.listen 的host參數也會傳入,這里是為了避免產生不必要的麻煩。至于這個麻煩,我這就不解釋了(一定要有能看到的默認值,而不是去靠猜)
    • 對于監聽端口啟動服務以后一些異常統一捕獲,并且統一日志記錄, process 進程退出,防止出現僵死線程、端口占用等(因為node部署時候可能會用pm2等方式,在 Worker 線程中,process.exit()將停止當前線程而不是當前進程)

app.js入口文件

  • 這里是由 koa 提供基礎服務
  • monggose 負責連接 mongoDB 數據庫
  • 若干中間件負責跨域、日志、錯誤、數據處理等

    1. const conditional = require('koa-conditional-get'); 
    2. const etag = require('koa-etag'); 
    3. const cors = require('koa2-cors'); 
    4. const helmet = require('koa-helmet'); 
    5. const Koa = require('koa'); 
    6. const bodyParser = require('koa-bodyparser'); 
    7. const mongoose = require('mongoose'); 
    8. const { requestLogger, logger } = require('./middleware/logger'); 
    9. const { responseTime, errors } = require('./middleware'); 
    10. const { v4 } = require('./services'); 
    11.  
    12. const app = new Koa(); 
    13.  
    14. mongoose.connect(process.env.SPACEX_MONGO, { 
    15.   useFindAndModify: false
    16.   useNewUrlParser: true
    17.   useUnifiedTopology: true
    18.   useCreateIndex: true
    19. }); 
    20.  
    21. const db = mongoose.connection; 
    22.  
    23. db.on('error', (err) => { 
    24.   logger.error(err); 
    25. }); 
    26. db.once('connected', () => { 
    27.   logger.info('Mongo connected'); 
    28.   app.emit('ready'); 
    29. }); 
    30. db.on('reconnected', () => { 
    31.   logger.info('Mongo re-connected'); 
    32. }); 
    33. db.on('disconnected', () => { 
    34.   logger.info('Mongo disconnected'); 
    35. }); 
    36.  
    37. // disable console.errors for pino 
    38. app.silent = true
    39.  
    40. // Error handler 
    41. app.use(errors); 
    42.  
    43. app.use(conditional()); 
    44.  
    45. app.use(etag()); 
    46.  
    47. app.use(bodyParser()); 
    48.  
    49. // HTTP header security 
    50. app.use(helmet()); 
    51.  
    52. // Enable CORS for all routes 
    53. app.use(cors({ 
    54.   origin: '*'
    55.   allowMethods: ['GET''POST''PATCH''DELETE'], 
    56.   allowHeaders: ['Content-Type''Accept'], 
    57.   exposeHeaders: ['spacex-api-cache''spacex-api-response-time'], 
    58. })); 
    59.  
    60. // Set header with API response time 
    61. app.use(responseTime); 
    62.  
    63. // Request logging 
    64. app.use(requestLogger); 
    65.  
    66. // V4 routes 
    67. app.use(v4.routes()); 
    68.  
    69. module.exports = app; 
  • 邏輯清晰,自上而下,首先連接db數據庫,掛載各種事件后,經由koa各種中間件,而后真正使用koa路由提供api服務(代碼編寫順序,即代碼運行后的業務邏輯,我們寫前端的react等的時候,也提倡由生命周期運行順序去編寫組件代碼,而不是先編寫unmount生命周期,再編寫mount),例如應該這樣:
  1. //組件掛載 
  2. componentDidmount(){ 
  3.  
  4. //組件需要更新時 
  5. shouldComponentUpdate(){ 
  6.  
  7. //組件將要卸載 
  8. componentWillUnmount(){ 
  9.  
  10. ... 
  11. render(){} 

router的代碼,簡介明了

  1. const Router = require('koa-router'); 
  2. const admin = require('./admin/routes'); 
  3. const capsules = require('./capsules/routes'); 
  4. const cores = require('./cores/routes'); 
  5. const crew = require('./crew/routes'); 
  6. const dragons = require('./dragons/routes'); 
  7. const landpads = require('./landpads/routes'); 
  8. const launches = require('./launches/routes'); 
  9. const launchpads = require('./launchpads/routes'); 
  10. const payloads = require('./payloads/routes'); 
  11. const rockets = require('./rockets/routes'); 
  12. const ships = require('./ships/routes'); 
  13. const users = require('./users/routes'); 
  14. const company = require('./company/routes'); 
  15. const roadster = require('./roadster/routes'); 
  16. const starlink = require('./starlink/routes'); 
  17. const history = require('./history/routes'); 
  18. const fairings = require('./fairings/routes'); 
  19.  
  20. const v4 = new Router({ 
  21.   prefix: '/v4'
  22. }); 
  23.  
  24. v4.use(admin.routes()); 
  25. v4.use(capsules.routes()); 
  26. v4.use(cores.routes()); 
  27. v4.use(crew.routes()); 
  28. v4.use(dragons.routes()); 
  29. v4.use(landpads.routes()); 
  30. v4.use(launches.routes()); 
  31. v4.use(launchpads.routes()); 
  32. v4.use(payloads.routes()); 
  33. v4.use(rockets.routes()); 
  34. v4.use(ships.routes()); 
  35. v4.use(users.routes()); 
  36. v4.use(company.routes()); 
  37. v4.use(roadster.routes()); 
  38. v4.use(starlink.routes()); 
  39. v4.use(history.routes()); 
  40. v4.use(fairings.routes()); 
  41.  
  42. module.exports = v4; 

模塊眾多,找幾個代表性的模塊

  • admin 模塊
  1. const Router = require('koa-router'); 
  2. const { auth, authz, cache } = require('../../../middleware'); 
  3.  
  4. const router = new Router({ 
  5.   prefix: '/admin'
  6. }); 
  7.  
  8. // Clear redis cache 
  9. router.delete('/cache', auth, authz('cache:clear'), async (ctx) => { 
  10.   try { 
  11.     await cache.redis.flushall(); 
  12.     ctx.status = 200
  13.   } catch (error) { 
  14.     ctx.throw(400, error.message); 
  15.   } 
  16. }); 
  17.  
  18. // Healthcheck 
  19. router.get('/health', async (ctx) => { 
  20.   ctx.status = 200
  21. }); 
  22.  
  23. module.exports = router; 
  • 分析代碼

  •  這是一套標準的restful API ,提供的/admin/cache接口,請求方式為delete,請求這個接口,首先要經過auth和authz兩個中間件處理

這里補充一個小細節

  • 一個用戶訪問一套系統,有兩種狀態,未登陸和已登陸,如果你未登陸去執行一些操作,后端應該返回 401 。但是登錄后,你只能做你權限內的事情,例如你只是一個打工人,你說你要關閉這個公司,那么對不起,你的狀態碼此時應該是 403

回到admin

  • 此刻的你,想要清空這個緩存,調用/admin/cache接口,那么首先要經過 auth 中間件判斷你是否有登錄
  1. /** 
  2.  * Authentication middleware 
  3.  */ 
  4. module.exports = async (ctx, next) => { 
  5.   const key = ctx.request.headers['spacex-key']; 
  6.   if (key) { 
  7.     const user = await db.collection('users').findOne({ key }); 
  8.     if (user?.key === key) { 
  9.       ctx.state.roles = user.roles; 
  10.       await next(); 
  11.       return
  12.     } 
  13.   } 
  14.   ctx.status = 401
  15.   ctx.body = 'https://youtu.be/RfiQYRn7fBg'
  16. }; 
  • 如果沒有登錄過,那么意味著你沒有權限,此時為401狀態碼,你應該去登錄.如果登錄過,那么應該前往下一個中間件 authz 。 (所以redux的中間件源碼是多么重要。它可以說貫穿了我們整個前端生涯,我以前些過它的分析,有興趣的可以翻一翻公眾號)

    1. /** 
    2.  * Authorization middleware 
    3.  * 
    4.  * @param   {String}   role   Role for protected route 
    5.  * @returns {void} 
    6.  */ 
    7. module.exports = (role) => async (ctx, next) => { 
    8.   const { roles } = ctx.state; 
    9.   const allowed = roles.includes(role); 
    10.   if (allowed) { 
    11.     await next(); 
    12.     return
    13.   } 
    14.   ctx.status = 403
    15. }; 
  •  在authz這里會根據你傳入的操作類型(這里是'cache:clear'),看你的對應所有權限roles里面是否包含傳入的操作類型role 。如果沒有,就返回403,如果有,就繼續下一個中間件 - 即真正的/admin/cache接口
  1. // Clear redis cache 
  2. router.delete('/cache', auth, authz('cache:clear'), async (ctx) => { 
  3.   try { 
  4.     await cache.redis.flushall(); 
  5.     ctx.status = 200
  6.   } catch (error) { 
  7.     ctx.throw(400, error.message); 
  8.   } 
  9. }); 
  • 此時此刻,使用try catch包裹邏輯代碼,當redis清除所有緩存成功即會返回狀態碼400,如果報錯,就會拋出錯誤碼和原因。接由洋蔥圈外層的 error 中間件處理
  1. /** 
  2.  * Error handler middleware 
  3.  * 
  4.  * @param   {Object}    ctx       Koa context 
  5.  * @param   {function}  next      Koa next function 
  6.  * @returns {void} 
  7.  */ 
  8. module.exports = async (ctx, next) => { 
  9.   try { 
  10.     await next(); 
  11.   } catch (err) { 
  12.     if (err?.kind === 'ObjectId') { 
  13.       err.status = 404
  14.     } else { 
  15.       ctx.status = err.status || 500
  16.       ctx.body = err.message; 
  17.     } 
  18.   } 
  19. }; 
  • 這樣只要任意的 server 層內部出現異常,只要拋出,就會被 error 中間件處理,直接返回狀態碼和錯誤信息. 如果沒有傳入狀態碼,那么默認是500(所以我之前說過,代碼要穩定,一定要有顯示的指定默認值,要關注代碼異常的邏輯,例如前端setLoading,請求失敗也要取消loading,不然用戶就沒法重試了,有可能這一瞬間只是用戶網絡出錯呢)

補一張koa洋蔥圈的圖

再接下來看其他的services

  • 現在,都非常輕松就能理解了

  1. // Get one history event 
  2. router.get('/:id', cache(300), async (ctx) => { 
  3.   const result = await History.findById(ctx.params.id); 
  4.   if (!result) { 
  5.     ctx.throw(404); 
  6.   } 
  7.   ctx.status = 200
  8.   ctx.body = result; 
  9. }); 
  10.  
  11. // Query history events 
  12. router.post('/query', cache(300), async (ctx) => { 
  13.   const { query = {}, options = {} } = ctx.request.body; 
  14.   try { 
  15.     const result = await History.paginate(query, options); 
  16.     ctx.status = 200
  17.     ctx.body = result; 
  18.   } catch (error) { 
  19.     ctx.throw(400, error.message); 
  20.   } 
  21. }); 


通過這個項目,我們能學到什么

  • 一個能上天的項目,必然是非常穩定、高可用的,我們首先要學習它的優秀點:用最簡單的技術加上最簡單的實現方式,讓人一眼就能看懂它的代碼和分層

  • 再者:簡潔的注釋是必要的

  • 從業務角度去抽象公共層,例如鑒權、錯誤處理、日志等為公共模塊(中間件,前端可能是一個工具函數或組件)

  • 多考慮錯誤異常的處理,前端也是如此,js大多錯誤發生來源于a.b.c這種代碼(如果a.b為undefined那么就會報錯了)
  • 顯示的指定默認值,不讓代碼閱讀者去猜測

  • 目錄分區必定要簡潔明了,分層清晰,易于維護和拓展

成為一個優秀前端架構師的幾個技能點

  • 原生JavaScript、CSS、HTML基礎扎實(系統學習過)

  • 原生Node.js基礎扎實(系統學習過),Node.js不僅提供服務,更多的是用于制作工具,以及現在serverless場景也會用到,還有SSR

  • 熟悉框架和類庫原理,能手寫簡易的常用類庫,例如promise redux 等

  • 數據結構基礎扎實,了解常用、常見算法

  • linux基礎扎實(做工具,搭環境,編寫構建腳本等有會用到)

  • 熟悉TCP和http等通信協議

  • 熟悉操作系統linux Mac windows iOS 安卓等(在跨平臺產品時候會遇到)

  • 會使用docker(部署相關)

  • 會一些c++最佳(在addon場景等,再者Node.js和JavaScript本質上是基于 C++ )
  • 懂基本數據庫、redis、nginxs操作,像跨平臺產品,基本前端都會有個sqlite之類的,像如果是node自身提供服務,數據庫和redis一般少不了

  • 再者是要多閱讀優秀的開源項目源碼,不用太多,但是一定要精

 

 

責任編輯:張燕妮 來源: 前端巔峰
相關推薦

2018-07-12 14:34:05

2020-12-11 11:19:54

區塊鏈資金投資

2022-02-28 08:23:02

開源項目重構

2015-07-29 10:00:16

開源項目

2014-10-21 10:25:50

程序員

2023-05-05 08:09:51

運維Oracle數據庫

2022-12-27 15:09:30

2019-03-22 11:24:01

GitHub 技術開發

2025-01-02 14:56:42

開源.NET開發

2021-03-02 14:50:57

開源技術 項目

2024-02-07 01:32:48

頁面前端項目

2017-11-07 11:36:57

開源項目代碼

2022-08-02 07:57:54

RAC故障運維

2024-07-02 08:28:17

開源代碼社區

2013-08-19 12:40:18

開源項目

2014-02-17 17:47:16

前端后端架構

2015-09-23 14:07:12

前端與后端架構實例

2019-02-26 09:42:14

開源技術 趨勢

2014-08-11 16:32:04

架構項目

2020-02-27 15:01:17

前端開源項目
點贊
收藏

51CTO技術棧公眾號

邻家有女韩剧在线观看国语| 久久久综合久久久| 国产欧美在线观看免费| 亚洲欧美日韩国产一区二区三区 | 黄网在线观看视频| 欧美日韩精品一区二区视频| 日韩精品一区二区三区视频播放 | 欧美成人黄色| 亚洲成人一区二区在线观看| 婷婷四月色综合| 免费a级片在线观看| 奇米四色…亚洲| 久久999免费视频| аⅴ天堂中文在线网| 99精品国产一区二区三区2021 | 精品av一区二区| 欧美一级理论性理论a| 欧美aⅴ在线观看| 成人无遮挡免费网站视频在线观看| 北岛玲一区二区三区四区| 国产乱肥老妇国产一区二| 黄色片视频网站| 91精品国产自产拍在线观看蜜| 日韩av在线资源| 日本一区二区三区在线免费观看| av有声小说一区二区三区| 亚洲午夜激情网页| 久久久无码中文字幕久...| 黄色av免费在线观看| 风流少妇一区二区| 91在线免费网站| 怡红院男人的天堂| 亚洲综合精品四区| 97精品免费视频| 久久成人在线观看| 自拍视频亚洲| 久久视频免费在线播放| 欧美a在线播放| 国际精品欧美精品| 亚洲人午夜色婷婷| 中文字幕5566| 五月天亚洲色图| 亚洲第一区在线观看| 少妇伦子伦精品无吗| 欧美经典影片视频网站| 17videosex性欧美| 波多野结衣在线观看一区二区三区| 精品卡一卡二卡三卡四在线| 久久久久久久久久毛片| 黄色成人小视频| 1024国产精品| 日本电影一区二区三区| 日本黄在线观看| 99精品国产99久久久久久白柏| 国产精品美女黄网| 欧美亚洲精品在线观看| 成人不卡免费av| 国产综合av一区二区三区| 蜜桃久久一区二区三区| 成人高清视频免费观看| 国产精品乱子乱xxxx| 国产 日韩 欧美 精品| 成人午夜视频免费看| 国产高清在线精品一区二区三区| 国产 欧美 精品| 成人av在线播放网址| 国产在线精品一区二区三区》| 日本黄色一区二区三区| 91在线观看免费视频| 久久国产精品 国产精品| 水莓100国产免费av在线播放| av在线这里只有精品| 久久久久国产精品视频| 成人全视频高清免费观看| 国产欧美精品一区二区色综合朱莉| 午夜精品一区二区在线观看| 欧美精品日韩少妇| 亚洲精品久久久蜜桃| 免费在线观看视频a| 亚洲v.com| 欧美午夜影院一区| 国产欧美精品一二三| 国产成人av毛片| 亚洲少妇激情视频| 日韩精品一区二区亚洲av性色| 欧美日韩一视频区二区| 欧美一区在线直播| 国产精品国产精品国产专区| 粉嫩久久99精品久久久久久夜 | www.四虎在线观看| av在线一区二区| 亚洲电影免费| 丁香花高清在线观看完整版| 日韩欧美视频一区二区三区| 久久久久久久久久久久久久久国产| silk一区二区三区精品视频| 国产亚洲欧洲高清一区| 欧美人妻一区二区| 日本在线播放一区二区三区| 不卡一区二区三区视频| 成人综合影院| 精品久久久久久亚洲精品| 国产三级国产精品国产专区50| 国产精品白丝av嫩草影院| 一区二区在线视频播放| 久久综合久久鬼| 蜜臀av性久久久久蜜臀av麻豆| 国产精品久久久对白| 在线免费观看的av网站| 精品久久久香蕉免费精品视频| 亚洲一区二区福利视频| 偷拍一区二区| 欧美高清第一页| 一区二区日韩在线观看| wwwwww.欧美系列| 国产精品美女在线播放| 五月婷婷深深爱| 欧美体内she精视频在线观看| 国产91精品久久久久久久| 国产毛片一区二区三区va在线| 久久久久久日产精品| 青青草综合在线| 成人黄色在线| 亚洲老板91色精品久久| 久久这里只有精品国产| 国产伦精品一区二区三区免费| 日韩国产欧美精品| 亚洲校园激情春色| 日韩欧美在线网站| 999精品在线视频| 日韩成人午夜电影| 久久久久久久久一区二区| 美女精品视频| 欧美日韩亚洲天堂| 亚洲熟女乱综合一区二区三区| 国产韩国精品一区二区三区| 国产精品免费福利| 伦理片一区二区三区| 精品久久久久久国产91| 亚洲熟女一区二区| 伊人久久亚洲热| 国产精品区一区| 波多野结衣在线高清| 日韩欧美一级片| 99热这里只有精品4| 免费国产亚洲视频| 亚洲欧美日韩不卡一区二区三区| 日韩欧美精品电影| 国产亚洲欧美一区| 一本色道久久综合亚洲| 综合精品久久久| 男人的天堂免费| 你懂的国产精品永久在线| 亚洲一区中文字幕在线观看| 成人在线观看亚洲| 精品伦理精品一区| 欧美福利视频一区二区| 2024国产精品| 一区二区三区免费播放| 日韩电影免费网站| 成人在线一区二区| 欧美hdxxx| 日韩电影网在线| 最近免费中文字幕大全免费版视频| 91小视频在线观看| 91网址在线播放| 99久久国产综合精品成人影院| 国产综合在线观看视频| a免费在线观看| 亚洲大胆人体视频| 手机在线看片1024| 中文字幕在线观看不卡| 亚洲国产日韩a在线播放性色| 欧美日韩中文不卡| 亚洲不卡av不卡一区二区| 成人精品水蜜桃| 国产免费拔擦拔擦8x高清在线人| 亚洲美女在线观看| 亚洲自拍偷拍另类| 亚洲亚洲精品在线观看| 无码一区二区三区在线| 精品一区二区三区免费| 777av视频| 国产一区网站| 动漫3d精品一区二区三区| 成人爱爱网址| 久久亚洲精品成人| 日韩一区二区精品视频| 日本免费高清不卡| 国产极品一区| 久久97精品久久久久久久不卡| 天堂av手机版| 欧美无乱码久久久免费午夜一区| 黄色香蕉视频在线观看| 成人综合婷婷国产精品久久免费| 免费无码av片在线观看| 久久国产影院| 精品日本一区二区三区在线观看| 粉嫩av一区二区三区四区五区 | 久久久久亚洲av无码网站| 欧美亚洲三级| 日本wwwcom| 日韩大片在线| 久久亚裔精品欧美| 久久免费精品| 国产激情久久久久| 91豆花视频在线播放| 日韩中文有码在线视频| 四虎影视精品成人| 欧美不卡一二三| 136福利视频导航| 日韩欧美在线视频| 精品一区二区三区人妻| 国产精品盗摄一区二区三区| 免费观看av网站| 国产成人精品免费在线| 91亚洲免费视频| 久久婷婷av| 热99这里只有精品| 国内精品久久久久久久影视麻豆| 亚洲电影网站| 欧美猛男男男激情videos| 国产精品精品软件视频| 欧美专区一区| 亚洲aⅴ男人的天堂在线观看| 深夜成人福利| 国产91精品久| 国产亚洲成av人片在线观看 | 亚洲成人久久久久| 国产999久久久| 日一区二区三区| 欧美一级视频免费看| 午夜久久黄色| 热这里只有精品| 97精品视频| 亚洲成人午夜在线| 精品国产一区二区三区小蝌蚪 | 自拍视频在线免费观看| 精品亚洲一区二区三区在线播放| 天堂v在线观看| 亚洲国产小视频在线观看| 女人18毛片水真多18精品| 日韩欧美中文字幕公布| 国产成人精品一区二三区四区五区| 欧美精品一二三区| 国产视频在线观看视频| 日韩色视频在线观看| 精品人妻无码一区二区色欲产成人 | 天堂а√在线中文在线新版| 精品久久久中文| 欧美性猛交bbbbb精品| 欧美在线免费视屏| 中文字幕人妻色偷偷久久| 7878成人国产在线观看| 99精品人妻无码专区在线视频区| 欧美一区二区高清| 国精品人妻无码一区二区三区喝尿 | 欧美日韩激情美女| 久久久久久久久久久影院| 91高清视频免费看| 一区二区三区亚洲视频| 欧美一级日韩一级| 日本人妻丰满熟妇久久久久久| 日韩av网站电影| 国产美女视频一区二区三区 | 欧美变态tickling挠脚心| 欧美一区二区黄片| 亚洲女人被黑人巨大进入| 成人h小游戏| 欧美激情精品久久久久久久变态| 日本福利视频在线| 国产综合色产| 久久成人免费观看| 日本不卡的三区四区五区| www.欧美激情.com| 成人久久视频在线观看| 91精品人妻一区二区| 国产精品国产三级国产aⅴ入口| 91香蕉视频在线播放| 有坂深雪av一区二区精品| 久热这里只有精品6| 欧美视频精品在线| 国精产品乱码一区一区三区四区| 亚洲欧美综合v| 在线āv视频| 国产精品久久久久久久久久尿| 北岛玲精品视频在线观看| 久久久久久久久久久久久久久久av| 精品久久久久中文字幕小说| 狠狠精品干练久久久无码中文字幕 | 92久久精品一区二区| 精品99久久久久久| www.91在线| 性色av一区二区三区| 日韩亚洲国产免费| 看高清中日韩色视频| 伊人成综合网| 亚洲激情在线观看视频| 成人av免费观看| 免费精品在线视频| 色综合天天综合| 亚洲第一页视频| 日韩中文视频免费在线观看| 欧美gv在线观看| 亚洲综合av影视| 成人同人动漫免费观看| 国产免费观看高清视频| 国产一区二区三区四| 成人激情五月天| 欧美特级www| 丰满肉嫩西川结衣av| 久久的精品视频| 日本在线精品| 蜜桃导航-精品导航| 亚洲国产精品第一区二区三区| 激情图片中文字幕| 中文字幕免费一区| aaa在线视频| 日韩av在线免费看| www欧美xxxx| av在线不卡一区| 亚洲成人免费| 三上悠亚在线一区| 久久久久久久久久久久久久久99| 久久精品国产亚洲av高清色欲| 欧美高清hd18日本| 午夜在线视频播放| 国产在线观看精品一区二区三区| 久久av电影| 欧美日韩一区二区在线免费观看| 99精品视频在线免费观看| 国产亚洲第一页| 精品日韩一区二区三区免费视频| a级毛片免费观看在线| 91精品视频在线免费观看| 国产精品成人av| 亚洲怡红院在线| 国产精品盗摄一区二区三区| 一本色道久久综合熟妇| 久久天天躁狠狠躁夜夜av| 粉嫩av国产一区二区三区| 九一免费在线观看| 粉嫩绯色av一区二区在线观看 | 欧美大波大乳巨大乳| 色婷婷久久久综合中文字幕| 九色视频在线观看免费播放 | 伊人精品久久| 国产欧美精品aaaaaa片| 99久久综合色| 精产国品一区二区| 中文字幕国产亚洲2019| 欧美高清xxx| ijzzijzzij亚洲大全| 国产激情偷乱视频一区二区三区 | 色域天天综合网| www黄在线观看| 国产在线不卡精品| 国产精品theporn| 欧美做受喷浆在线观看| 日本久久电影网| 免费在线看黄网站| 999精品在线观看| 日韩视频精品在线观看| a天堂中文字幕| 欧美偷拍一区二区| caoporn免费在线视频| 好吊色欧美一区二区三区四区| 久久不射中文字幕| 国产又色又爽又高潮免费| 日韩欧美的一区二区| 亚洲女同av| 一区二区三区的久久的视频| 国产成人亚洲精品青草天美| 日韩在线观看第一页| 少妇高潮久久77777| 97视频一区| 亚洲成人av免费看| 亚洲一区二区影院| 国产高清在线| 99久热re在线精品996热视频 | 久久6免费视频| 香蕉影视欧美成人| av资源在线观看免费高清| 91青青草免费观看| 久久综合激情| 久草免费在线视频观看| 亚洲天堂日韩电影| 欧美国产亚洲精品| 超碰在线97免费| 亚洲成av人片| 日本福利专区在线观看| 精品国产一区二区三区久久久久久| 全部av―极品视觉盛宴亚洲| 久久亚洲AV无码| 少妇高潮久久77777| 三级小说欧洲区亚洲区| 亚洲一区二区中文字幕在线观看| 色域天天综合网| 超级碰碰不卡在线视频| 亚洲一区在线免费|