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

聊聊 Nuxt 開箱即用的特性

開發 前端
最近公司項目中使用了 Nuxt 框架,進行首屏的服務端渲染,加快了內容的到達時間 (time-to-content),于是筆者開始了對 Nuxt 的學習和使用。以下是從源碼角度對 Nuxt 的一些特性的介紹和分析。

 [[420713]]

引文

最近公司項目中使用了 Nuxt 框架,進行首屏的服務端渲染,加快了內容的到達時間 (time-to-content),于是筆者開始了對 Nuxt 的學習和使用。以下是從源碼角度對 Nuxt 的一些特性的介紹和分析。

FEATURES

服務端渲染(SSR)

Vue.js 是構建客戶端應用程序的框架。默認情況下,可以在瀏覽器中輸出 Vue 組件,進行生成 DOM 和操作 DOM。然而,也可以將同一個組件渲染為服務器端的 HTML 字符串,將它們直接發送到瀏覽器,最后將這些靜態標記"激活"為客戶端上完全可交互的應用程序。 ------Vue SSR 指南

官方Vue SSR指南的基本用法章節,給出了 demo 級別的服務端渲染實現,Nuxt 也是基于該章節實現的,大體流程幾乎一致。建議先食用官方指南,再看本文定大有裨益。

Nuxt 作為一個服務端渲染框架,了解其服務端渲染的實現原理必然是重中之重,就讓我們通過相關源碼,看看其具體實現吧!

我們通過 nuxt 啟動 Nuxt 項目,其首先會執行 startDev 方法,然后調用_listenDev 方法,獲取 Nuxt 配置,調用getNuxt方法實例化 Nuxt。然后執行 nuxt.ready() 方法,生成渲染器。

  1. // @nuxt/server/src/server.js 
  2. async ready () { 
  3.  // Initialize vue-renderer 
  4.  this.serverContext = new ServerContext(this) 
  5.  this.renderer = new VueRenderer(this.serverContext) 
  6.  await this.renderer.ready() 
  7.  
  8.  // Setup nuxt middleware 
  9.  await this.setupMiddleware() 
  10.  
  11.  return this 

在 ready 中會執行 this.setupMiddleware() ,其中會調用nuxtMiddleware 中間件(這里是響應的關鍵)。

  1. // @nuxt/server/src/middleware/nuxt.js 
  2. export default ({ options, nuxt, renderRoute, resources }) => async function nuxtMiddleware (req, res, next) { 
  3.  const context = getContext(req, res) 
  4.  try { 
  5.    const url = normalizeURL(req.url) 
  6.    res.statusCode = 200 
  7.    const result = await renderRoute(url, context) // 渲染相應路由,后文會展開 
  8.     
  9.    const { 
  10.      html, 
  11.      redirected, 
  12.      preloadFiles 
  13.   } = result // 得到html 
  14.  
  15.    // 設置頭部字段 
  16.    res.setHeader('Content-Type''text/html; charset=utf-8'
  17.    res.setHeader('Accept-Ranges''none'
  18.    res.setHeader('Content-Length', Buffer.byteLength(html)) 
  19.    res.end(html, 'utf8') // 做出響應 
  20.    return html 
  21. } catch (err) { 
  22.    if (context && context.redirected) { 
  23.      consola.error(err) 
  24.      return err 
  25.   } 
  26.    next(err) 

nuxtMiddleware 中間件中首先標準化請求的url,設置請求狀態碼,通過url匹配到相應的路由,渲染出對應的路由組件,設置頭部信息,最后做出響應。

  1. renderSSR (renderContext) { 
  2.  // Call renderToString from the bundleRenderer and generate the HTML (will update the renderContext as well) 
  3.  // renderSSR 只是 universal app的渲染方法,Nuxt 也可以進行開發普通的 SPA 項目 
  4.  const renderer = renderContext.modern ? this.renderer.modern : this.renderer.SSR 
  5.  return renderer.render(renderContext) 

其中 renderRoute 方法會調用 @nuxt/vue-render 的renderSSR 進行服務端渲染操作。

  1. // @nuxt/vue-renderer/src/renderers/SSR.js 
  2. async render (renderContext) { 
  3.  // Call Vue renderer renderToString 
  4.  let APP = await this.vueRenderer.renderToString(renderContext) 
  5.  
  6.  let HEAD = '' 
  7.  // ... 此處省略n行HEAD拼接代碼,后續 HEAD 管理部分會提及 
  8.     
  9.  // Render with SSR template 
  10.  const html = this.renderTemplate(this.serverContext.resources.SSRTemplate, templateParams) 
  11.  
  12.  return { 
  13.    html, 
  14.    preloadFiles 

而 renderSSR 又會調用 renderer.render 方法,將 url 匹配的路由渲染成字符串,將字符串與模版相結合,得到最終返回給瀏覽器的html,至此 Nuxt 服務端渲染完成。

最后貼一張盜來的 Nuxt 執行流程圖,圖畫的很棒,流程也很清晰,感謝。

數據拉取(Data Fetching)

在客戶端程序(CSR)可以通過在 mounted 鉤子中獲取數據,但在通用程序(Universal)中則需要使用特定的鉤子才能在服務端獲取數據。

Nuxt 中主要提供了兩種鉤子獲取數據

  • asyncData
    • 只可以在頁面級組件中獲取,不可以訪問 this
    • 通過返回對象保存數據狀態或與Vuex配合進行狀態保存
  • fetch
    • 所有組件中都可以獲取,可以訪問 this
    • 無需傳入 context,傳入 context 會 fallback 到老版的 fetch,功能類似于 asyncData
  1. // .nuxt/server.js 
  2. // Components are already resolved by setContext -> getRouteData (app/utils.js) 
  3. const Components = getMatchedComponents(app.context.route) 
  4.   
  5. // 在匹配的路由中,調用 asyncData 和 legacy 版本的 fetch方法 
  6. const asyncDatas = await Promise.all(Components.map((Component) => { 
  7.  const promises = [] 
  8.  
  9.  // 調用 asyncData(context) 
  10.  if (Component.options.asyncData && typeof Component.options.asyncData === 'function') { 
  11.    const promise = promisify(Component.options.asyncData, app.context) 
  12.    promise.then((asyncDataResult) => { 
  13.      SSRContext.asyncData[Component.cid] = asyncDataResult 
  14.      applyAsyncData(Component) 
  15.      return asyncDataResult 
  16.   }) 
  17.    promises.push(promise) 
  18.   } else { 
  19.      promises.push(null
  20.   } 
  21.  
  22.    // 調用 legacy 版本的fetch(context) 兼容老版本的 fetch 
  23.    if (Component.options.fetch && Component.options.fetch.length) { 
  24.      promises.push(Component.options.fetch(app.context)) 
  25.   } else { 
  26.    promises.push(null
  27.  
  28.  return Promise.all(promises) 
  29. })) 

在生成的 .nuxt/server.js 中,會遍歷匹配的組件,查看組件中是否定義了 asyncData 選項以及 legacy 版 fetch ,存在就依次調用,獲得 asyncDatas。

  1. // .nuxt/mixins/fetch.server.js  
  2. // nuxt v2.14及之后 
  3. async function serverPrefetch() { 
  4.  // Call and await on $fetch 
  5.  // v2.14 之后推薦的 fetch 
  6.  try { 
  7.    await this.$options.fetch.call(this) 
  8. } catch (err) { 
  9.    if (process.dev) { 
  10.      console.error('Error in fetch():', err) 
  11.   }  
  12.  this.$fetchState.pending = false // 設置fetchState 為 false 

在服務端實例化 vue 實例之后,執行 serverPrefetch,觸發 fetch 選項方法,獲取數據,數據會作用于生成 html的過程。

HEAD 管理(Meta Tags and SEO)

截至目前,Google 和 Bing 可以很好對同步 JavaScript 應用程序進行索引。但是對于異步獲取數據的網站來說,主流的搜索引擎暫時還無法支持,于是造成網站搜索排名靠后,于是希望獲得更好的SEO成為眾多網站考慮使用SSR框架的原因。

為了獲得良好的SEO,那么就需要對HEAD進行精細化的配置和管理。讓我們看看其是如何實現的吧~

Nuxt框架借助 vue-meta 庫實現全局、單個頁面的 meta 標簽的自定義。Nuxt 內部的實現也幾乎遵循 vue-meta 官方的 SSR meta 管理的流程。具體詳情請查看。

  1. // @nuxt/vue-app/template/index.js 
  2. // step1 
  3. Vue.use(Meta, JSON.stringify(vueMetaOptions)) 
  4.  
  5. // @nuxt/vue-app/template/template.js 
  6. // step2 
  7. export default async (SSRContext) => { 
  8.  const _app = new Vue(app) 
  9.  // Add meta infos (used in renderer.js) 
  10.  SSRContext.meta = _app.$meta() 
  11.  return _app 

首先通過Vue插件的形式,注冊vue-meta,內部會在Vue的原型上掛載$meta屬性。然后將meta添加到服務端渲染上下文中。

  1. async render (renderContext) { 
  2.    // Call Vue renderer renderToString 
  3.    let APP = await this.vueRenderer.renderToString(renderContext) 
  4.    // step3 
  5.    let HEAD = '' 
  6.  
  7.    // Inject head meta 
  8.    // (this is unset when features.meta is false in server template) 
  9.    // 以下就是上文省略的 n 行 HEAD 拼接代碼,可以適當忽略 
  10.    // 了解主要過程即可,具體細節按需查看 
  11.    const meta = renderContext.meta && renderContext.meta.inject({ 
  12.      isSSR: renderContext.nuxt.serverRendered, 
  13.      ln: this.options.dev 
  14.   }) 
  15.  
  16.    if (meta) { 
  17.      HEAD += meta.title.text() + meta.meta.text() 
  18.   } 
  19.  
  20.    if (meta) { 
  21.      HEAD += meta.link.text() + 
  22.        meta.style.text() + 
  23.        meta.script.text() + 
  24.        meta.noscript.text() 
  25.   } 
  26.  
  27.    // Check if we need to inject scripts and state 
  28.    const shouldInjectScripts = this.options.render.injectScripts !== false 
  29.  
  30.    // Inject resource hints 
  31.    if (this.options.render.resourceHints && shouldInjectScripts) { 
  32.      HEAD += this.renderResourceHints(renderContext) 
  33.   } 
  34.  
  35.    // Inject styles 
  36.    HEAD += this.renderStyles(renderContext) 
  37.  
  38.  
  39.    // Prepend scripts 
  40.    if (shouldInjectScripts) { 
  41.      APP += this.renderScripts(renderContext) 
  42.   } 
  43.  
  44.    if (meta) { 
  45.      const appendInjectorOptions = { body: true } 
  46.      // Append body scripts 
  47.      APP += meta.meta.text(appendInjectorOptions) 
  48.      APP += meta.link.text(appendInjectorOptions) 
  49.      APP += meta.style.text(appendInjectorOptions) 
  50.      APP += meta.script.text(appendInjectorOptions) 
  51.      APP += meta.noscript.text(appendInjectorOptions) 
  52.   } 
  53.  
  54.    // Template params 
  55.    const templateParams = { 
  56.      HTML_ATTRS: meta ? meta.htmlAttrs.text(renderContext.nuxt.serverRendered /* addSrrAttribute */) : ''
  57.      HEAD_ATTRS: meta ? meta.headAttrs.text() : ''
  58.      BODY_ATTRS: meta ? meta.bodyAttrs.text() : ''
  59.      HEAD, 
  60.      APP, 
  61.      ENV: this.options.env 
  62.   } 
  63.  
  64.    // Render with SSR template 
  65.    // 通過模版和參數 生成html 
  66.    const html = this.renderTemplate(this.serverContext.resources.SSRTemplate, templateParams) 
  67.  
  68.    let preloadFiles 
  69.    if (this.options.render.http2.push) { 
  70.      // 獲取需要預加載的文件 
  71.      preloadFiles = this.getPreloadFiles(renderContext) 
  72.   } 
  73.  
  74.    return { 
  75.      html, 
  76.      preloadFiles, 
  77.   } 

最后在響應的 html 中注入 metadata 即可。

文件系統路由(File System Routing)

想必使用過 Nuxt 的同學應該都對其基于文件生成路由的特性,印象深刻。讓我從源碼角度看看 Nuxt 是如何實現基于 pages 目錄(可配置),自動生成路由的。

首先在啟動 Nuxt 項目或者修改文件時,會自動調 generateRoutesAndFiles 方法,生成路由 以及 .nuxt 目錄下的文件。

  1. // @nuxt/builder/src/builder.js 
  2. async generateRoutesAndFiles() { 
  3.   ... 
  4.   await Promise.all([ 
  5.     this.resolveLayouts(templateContext), 
  6.     this.resolveRoutes(templateContext), //解析生成路由,需要關注的重點 
  7.     this.resolveStore(templateContext), 
  8.     this.resolveMiddleware(templateContext) 
  9.   ]) 
  10.   ... 

解析路由會存在三種情況:一是修改了默認的 pages 目錄名稱,且未在 nuxt.config.js 中配置相關目錄,二是使用 nuxt 默認的 pages 目錄,三是使用調用用戶自定義的路由生成方法生成路由。

  1. // @nuxt/builder/src/builder.js 
  2. async resolveRoutes({ templateVars }) { 
  3.   consola.debug('Generating routes...'
  4.   if (this._defaultPage) { 
  5.     // 在srcDir下未找到pages目錄 
  6.   } else if (this._nuxtPage) { 
  7.     // 使用nuxt動態生成路由 
  8.   } else { 
  9.     // 用戶提供了自定義方法去生成路由,提供用戶自定義路由的能力 
  10.   } 
  11.   // router.extendRoutes method 
  12.   if (typeof this.options.router.extendRoutes === 'function') { 
  13.     const extendedRoutes = await this.options.router.extendRoutes( 
  14.       templateVars.router.routes, 
  15.       resolve 
  16.     ) 
  17.     if (extendedRoutes !== undefined) { 
  18.       templateVars.router.routes = extendedRoutes 
  19.     } 
  20.   } 

除此之外,還可以提供相應的 extendRoutes 方法,在 nuxt 生成路由的基礎上添加自定義路由。

  1. export default { 
  2.   router: { 
  3.     extendRoutes(routes, resolve) { 
  4.       // 例如添加 404 頁面 
  5.       routes.push({ 
  6.         name'custom'
  7.         path: '*'
  8.         component: resolve(__dirname, 'pages/404.vue'
  9.       }) 
  10.     } 
  11.   } 

其中當修改了默認的 pages 目錄,導致找不到相關的目錄,會使用 @nuxt/vue-app/template/pages/index.vue 文件生成路由。

  1. async resolveRoutes({ templateVars }) { 
  2.   if (this._defaultPage) { 
  3.     // createRoutes 方法根據傳參,生成路由。具體算法,不再展開 
  4.     templateVars.router.routes = createRoutes({ 
  5.       files: ['index.vue'], 
  6.       srcDir: this.template.dir + '/pages', // 指向@nuxt/vue-app/template/pages/index.vue 
  7.       routeNameSplitter, // 路由名稱分隔符,默認`-` 
  8.       trailingSlash // 尾斜杠 / 
  9.     }) 
  10.   } else if (this._nuxtPage) { 
  11.     const files = {} 
  12.     const ext = new RegExp(`\\.(${this.supportedExtensions.join('|')})$`) 
  13.     for (const page of await this.resolveFiles(this.options.dir.pages)) { 
  14.       const key = page.replace(ext, ''
  15.       // .vue file takes precedence over other extensions 
  16.       if (/\.vue$/.test(page) || !files[key]) { 
  17.         files[key] = page.replace(/(['"])/g, '\\$1') 
  18.       } 
  19.     } 
  20.     templateVars.router.routes = createRoutes({ 
  21.       files: Object.values(files), 
  22.       srcDir: this.options.srcDir, 
  23.       pagesDir: this.options.dir.pages, 
  24.       routeNameSplitter, 
  25.       supportedExtensions: this.supportedExtensions, 
  26.       trailingSlash 
  27.     }) 
  28.     } else { 
  29.       templateVars.router.routes = await this.options.build.createRoutes(this.options.srcDir) 
  30.     } 
  31.     // router.extendRoutes method 
  32.     if (typeof this.options.router.extendRoutes === 'function') { 
  33.       const extendedRoutes = await this.options.router.extendRoutes( 
  34.         templateVars.router.routes, 
  35.         resolve 
  36.       ) 
  37.       if (extendedRoutes !== undefined) { 
  38.         templateVars.router.routes = extendedRoutes 
  39.       } 
  40.   } 

然后就是調用 createRoutes 方法,生成路由。生成的路由大致長這樣,和手動書寫的路由文件幾乎一致(后續還會進行打包??,懶加載引入路由組件)。

  1.   { 
  2.     name'index'
  3.     path: '/'
  4.     chunkName: 'pages/index'
  5.     component: 'Users/username/projectName/pages/index.vue' 
  6.   }, 
  7.   { 
  8.     name'about'
  9.     path: '/about'
  10.     chunkName: 'pages/about/index'
  11.     component: 'Users/username/projectName/pages/about/index.vue' 
  12.   } 

智能預取(Smart Prefetching)

從 Nuxt v2.4.0 開始,當 出現在可視區域后,Nuxt將會預取經過code-splitted的 page 頁面的腳本,使得在用戶點擊之前,該路由指向的地址,就處于 ready 狀態,這將極大的提升用戶的體驗。

相關實現邏輯集中于 .nuxt/components/nuxt-link.client.js 中。

首先 Smart Prefetching 特性的實現依賴于window.IntersectionObserver 這個實驗性的 API,如果瀏覽器不支持該 API,就不會進行組件預取操作。

  1. mounted () { 
  2.   if (this.prefetch && !this.noPrefetch) { 
  3.     this.handleId = requestIdleCallback(this.observe, { timeout: 2e3 }) 
  4.   } 

然后在需要預取的 組件掛載階段,會調用 requestIdleCallback 方法在瀏覽器的空閑時段內調用 observe 方法。

  1. const observer = window.IntersectionObserver && new window.IntersectionObserver((entries) => { 
  2.   entries.forEach(({ intersectionRatio, target: link }) => { 
  3.     // 如果intersectionRatio 小于等于0,表示目標不在viewport內 
  4.     if (intersectionRatio <= 0 || !link.__prefetch) { 
  5.       return 
  6.     } 
  7.     // 進行預取數據(其實就是加載組件) 
  8.     link.__prefetch() 
  9.   }) 
  10. }) 

當被監聽的元素的可視情況發生改變的時候(且出現在視圖內時),會觸發 new window.IntersectionObserver(callback) 的回調,執行真正的預取操作prefetchLink。

  1. prefetchLink () { 
  2.   // 判斷網絡環境,離線或者2G環境下,不進行預取操作 
  3.   if (!this.canPrefetch()) { 
  4.     return 
  5.   } 
  6.   // 停止監聽該元素,提高性能 
  7.   observer.unobserve(this.$el) 
  8.   const Components = this.getPrefetchComponents() 
  9.  
  10.   for (const Component of Components) { 
  11.     // 及時加載組件,使得用戶點擊時,該組件是一個就緒的狀態 
  12.     const componentOrPromise = Component() 
  13.     if (componentOrPromise instanceof Promise) { 
  14.       componentOrPromise.catch(() => {}) 
  15.     Component.__prefetched = true // 已經預取的標志位 
  16.   } 

總結

上文從源碼角度介紹了 Nuxt 服務端渲染的實現、服務端數據的獲取以及 Nuxt 開箱即用的幾個特性:HEAD 管理、基于文件系統的路由和智能預取 code-splitted 的路由。如果希望對 SSR 進行更深入研究,還可以橫向學習 React 的 SSR 實現 Next 框架。

希望對您有所幫助,如有紕漏,望請輔正。

參考

為什么使用服務器端渲染 (SSR)?

Nuxt源碼精讀

Vue Meta

Introducing Smart prefetching

服務端渲染

 

責任編輯:武曉燕 來源: 大轉轉FE
相關推薦

2024-11-25 06:20:00

Netty封裝框架

2023-01-15 20:28:32

前端圖片壓縮

2023-03-08 21:25:58

開源工具庫開箱

2022-08-08 08:29:55

圖片壓縮前端互聯網

2023-11-04 12:43:44

前端圖片參數

2021-09-26 05:41:47

基礎設施連接無線技術網絡

2025-07-10 00:00:05

開箱ApacheHertzbeat

2021-09-01 17:43:32

StreamNativ開源

2021-09-28 09:30:18

uni-appVue 3.0uniCloud

2023-01-29 07:49:57

2022-08-02 09:01:55

后臺管理模版

2025-04-14 11:00:00

2013-11-01 09:37:19

Android系統架構工具

2022-01-03 18:15:35

FlaskTepHttpRunner

2025-05-15 08:35:00

2015-06-30 09:49:19

管理平臺開源KVM

2019-11-25 00:00:00

開源技術 數據

2023-04-04 10:09:09

2021-04-22 10:28:52

開發技能代碼
點贊
收藏

51CTO技術棧公眾號

巨骚激情综合| 热99精品里视频精品| 91精品综合久久久久久五月天| 黑人无套内谢中国美女| 精品无码一区二区三区的天堂| 美国十次综合久久| 久久精品国产精品亚洲综合| 日韩av在线免播放器| 中文字幕一区二区三区精彩视频| 午夜影院免费在线观看| 国产成人在线中文字幕| 亚洲欧美视频一区| 成人午夜在线影院| 国产一区二区三区四区五区六区| 1024在线看片你懂得| 国内精品国产三级国产a久久| 亚洲色图五月天| 91免费视频网站在线观看| 秋霞欧美在线观看| 午夜久久一区| 欧美不卡一区二区三区四区| 天天做天天躁天天躁| 96亚洲精品久久久蜜桃| 日韩免费视频| 欧美日本在线播放| 在线看无码的免费网站| 色婷婷综合视频| 99国产精品视频免费观看一公开| 亚洲国产三级网| av之家在线观看| 性插视频在线观看| 日韩精品乱码免费| 中文精品99久久国产香蕉| 福利在线一区二区三区| 日本亚洲精品| 国产精品一级在线| 欧美精品久久久久| 国产高清成人久久| 另类激情视频| 国产精品视频一二三区| 日本成人免费在线| 久久精品一区二区三| 国产亚洲精品美女久久| 制服丝袜亚洲精品中文字幕| 91嫩草国产丨精品入口麻豆| 丰满人妻一区二区三区免费视频| 亚洲第一毛片| 亚洲视频在线看| 国产一级伦理片| 国产精品一线| 亚洲电影免费观看高清完整版在线观看 | 日韩精品社区| 色婷婷精品大在线视频| 亚洲欧美国产一区二区| av男人天堂av| 国产欧美不卡| 在线日韩精品视频| 乳色吐息在线观看| 国产在线一区不卡| 欧美丝袜一区二区| 中国 免费 av| 欧美男男同志| 久久久天堂av| 91亚洲永久免费精品| 伊人网站在线观看| 亚洲视频日本| 中文字幕亚洲精品| 青青青视频在线免费观看| 成人香蕉社区| 欧美三区在线观看| 久久久亚洲国产精品| 成人免费一区二区三区视频网站| 国产精品一级二级三级| av蓝导航精品导航| 中文字幕在线观看视频一区| 蜜桃久久久久久久| 7m精品福利视频导航| 久久久久久久久久97| 露出调教综合另类| 91麻豆精品91久久久久久清纯| 国产一级片自拍| 男女羞羞在线观看| 一二三区精品视频| 特级毛片在线免费观看| 污视频在线看网站| 国产精品不卡视频| 欧美三日本三级少妇三99| 草草视频在线播放| 久久国产三级精品| 99在线视频免费观看| 天天干天天草天天射| 久久久久久麻豆| 一区二区三区免费看| 伦理片一区二区三区| 国产精品素人一区二区| 国产成人一二三区| 这里有精品可以观看| 亚洲国产裸拍裸体视频在线观看乱了| 一区二区视频在线免费| 色屁屁www国产馆在线观看| 欧美日韩精品在线播放| 欧美一区二区视频在线播放| 久久黄色美女电影| 国产精品国产三级国产| 男人添女荫道口女人有什么感觉| 色偷偷偷在线视频播放 | 一级爱爱免费视频| 亚洲在线视频| 91精品国产自产91精品| a片在线免费观看| 久久久久在线| 日韩av不卡电影| 免费黄色网址在线| 国产精品婷婷| 91精品视频免费看| 黄色视屏网站在线免费观看| 久久久亚洲高清| av中文字幕av| 成人国产一区二区三区精品麻豆| 在线区一区二视频| 手机在线看福利| 开心激情综合| 九九热这里只有精品免费看| 久久艹精品视频| 男人的天堂亚洲一区| 精品国产乱码久久久久久久软件| 性xxxx视频| 亚洲自拍偷拍欧美| 国产福利精品一区二区三区| 免费观看亚洲天堂| 综合网日日天干夜夜久久| 在线国产视频一区| 99视频一区| 国产99在线免费| | 久久综合av免费| 欧美日韩三区四区| freexxx性亚洲精品| 日韩一区二区免费在线观看| 黄色国产在线视频| 日韩av黄色在线| 中文字幕精品在线视频| 岛国av中文字幕| 91蜜桃免费观看视频| 亚洲国产一区二区精品视频| 在线播放高清视频www| 亚洲国产成人91精品| 久久久久香蕉视频| 久久久久久亚洲精品杨幂换脸| 国产专区一区二区| yw视频在线观看| 色婷婷av一区二区三区之一色屋| 中文字幕22页| 色综合色综合| 国产精品偷伦一区二区| 亚洲精品无遮挡| 国产欧美视频一区二区三区| 黄色录像特级片| 国产欧美视频在线| 欧美成人免费视频| 久久久久久久久久久影院| 99精品在线免费| 日韩第一页在线观看| 亚洲伦理久久| 亚洲精品有码在线| 欧美黄色aaa| 丝袜脚交一区二区| 国产伦精品一区二区三| 第一页在线观看| 午夜av电影一区| 色男人天堂av| 第一社区sis001原创亚洲| 97在线视频免费播放| 国产色综合视频| 国产女人aaa级久久久级| 久久婷婷综合色| 亚洲电影男人天堂| 久久久久久久久网站| 色丁香婷婷综合久久| 欧美日韩美女在线观看| 欧美大波大乳巨大乳| 国产原创一区二区| 亚洲 国产 欧美一区| 原纱央莉成人av片| 中文字幕精品网| 亚洲欧美激情在线观看| 欧美性极品少妇精品网站| 人妻视频一区二区| 亚洲专区免费| 亚洲一区二区三区精品在线观看| 国产欧美88| 日本亚洲欧洲色α| a级网站在线播放| 777亚洲妇女| 日韩精品视频免费看| 夫妻av一区二区| 在线观看免费黄色片| 福利视频一区| 色综合久久中文字幕综合网小说| 中文字幕av在线免费观看| 亚洲免费在线观看| 日本在线播放一区二区| 亚洲国产日本| 九9re精品视频在线观看re6 | 色播五月激情综合网| 日韩视频中文字幕在线观看| 91天堂素人约啪| 毛片毛片毛片毛片毛| 玖玖在线精品| 综合一区中文字幕| 伊人久久亚洲| 欧美激情免费视频| 日本在线免费网| 亚洲欧美日韩第一区| www.国产一区二区| 亚洲乱码国产乱码精品精98午夜 | 欧美在线黄色| 少妇免费毛片久久久久久久久| 91蜜桃臀久久一区二区| 国产在线观看一区二区三区| 成年网站在线| 亚洲第一福利视频| 精品国产999久久久免费| 欧美亚洲国产bt| 性少妇xx生活| 91蜜桃网址入口| 水蜜桃av无码| 国产99久久久国产精品潘金 | 久久综合精品国产一区二区三区| 国产chinesehd精品露脸| 好看的av在线不卡观看| 一区二区视频国产| 日本久久综合| 日韩av图片| 亚洲精品大片| 欧美精品精品精品精品免费| 黄色免费在线观看| 综合网日日天干夜夜久久| 搞黄视频在线观看| 亚洲人成啪啪网站| 男女视频在线观看| 亚洲精品中文字幕有码专区| 色屁屁草草影院ccyycom| 精品乱码亚洲一区二区不卡| av网站免费大全| 欧美一区二区精美| 中文字幕亚洲高清| 国产精品卡一卡二| 国产精品理论在线| 国产99精品国产| 成人一区二区三区仙踪林| 国产在线观看免费一区| 激情久久综合网| 国产视频一区欧美| 人妻少妇精品无码专区二区| 欧美三级免费| 亚洲国产另类久久久精品极度| 美日韩中文字幕| 51成人做爰www免费看网站| 国产精品av一区二区三区| 91wwwcom在线观看| 日韩免费福利视频| 欧美劲爆第一页| 高清毛片在线观看| 欧美超级免费视 在线| 97caopor国产在线视频| 伊人伊成久久人综合网小说 | 国产喷白浆一区二区三区| jizz18女人高潮| 亚洲激情六月丁香| 亚洲v国产v欧美v久久久久久| 国产亚洲欧美激情| 又黄又爽的网站| 久久久噜噜噜久久人人看 | 婷婷色在线观看| 亚洲免费高清视频| 麻豆传媒视频在线观看| 日韩毛片在线观看| 国产成人天天5g影院在线观看| 久久精品91久久香蕉加勒比| 欧美zzoo| 久久精品久久久久久| 99热99re6国产在线播放| 欧美在线性视频| 伊人久久一区| 精品综合在线| 亚洲欧美在线专区| 在线精品日韩| 亚洲激情av| 一区二区三区韩国| 成人激情av网| 制服丝袜在线第一页| 久久久久久电影| 青青草精品在线视频| 亚洲欧洲三级电影| 男人天堂资源网| 亚洲成人免费电影| 中文字幕欧美人妻精品一区蜜臀| 欧美成va人片在线观看| 国产爆初菊在线观看免费视频网站| 欧美日韩国产成人在线| 麻豆精品蜜桃| 国产精品免费视频xxxx| 精品欧美日韩精品| 国产精品一区视频网站| 91一区二区| 中日韩在线视频| 国产欧美精品| 日韩精品xxx| 1024成人网| 亚洲精品毛片一区二区三区| 精品福利一区二区三区| 日本美女一级视频| 视频直播国产精品| 345成人影院| 国产伦精品一区二区三区在线| 91精品综合久久久久久久久久久| 伊人色综合久久天天五月婷| 99精品热6080yy久久| 99999精品| 国产精品福利在线播放| 无码人妻av免费一区二区三区 | 亚洲一区二区三区国产| 不卡的免费av| 欧美午夜美女看片| 亚洲不卡免费视频| 美女扒开尿口让男人操亚洲视频网站| 欧美日韩不卡| 91精品中文在线| 日韩毛片视频| 亚洲视频在线a| 国产一区二区三区精品视频| 国产又粗又黄又猛| 色94色欧美sute亚洲13| 日韩资源在线| 中文字幕日韩av综合精品| 校园春色亚洲| 精品一区二区三区视频日产| 激情亚洲成人| 久草视频福利在线| 亚洲二区视频在线| 少妇精品视频一区二区| 国内精品视频一区| 成人不卡视频| 性高潮久久久久久久久| 另类成人小视频在线| 无码人妻精品中文字幕| 欧美日韩国产影片| 欧美成人hd| 亚洲aaaaaa| 国产亚洲一区二区三区不卡| 99热这里只有精品7| 国产真实乱子伦精品视频| 神马午夜精品91| 色综合久久久久综合体| av女名字大全列表| 国产精品对白刺激| 国产精品毛片久久久| 日本xxxxxxxxxx75| 99国产精品国产精品久久| 国产69精品久久久久久久久久| 亚洲欧美在线一区| 中文.日本.精品| 久久久国产精华液999999| 国产一区 二区 三区一级| 免费网站看av| 精品视频—区二区三区免费| 欧美最新精品| 黄色a级在线观看| jlzzjlzz国产精品久久| 91狠狠综合久久久| 日韩区在线观看| 欧美私密网站| 亚洲va韩国va欧美va精四季| 国产真实乱子伦精品视频| 日本五十路女优| 亚洲视频在线看| 亚洲精品福利| 黄色a级片免费| 99久久久国产精品免费蜜臀| 欧美精品韩国精品| 久久久精品免费视频| 精品国产午夜肉伦伦影院| 精品www久久久久奶水| 99久久免费视频.com| 高潮毛片又色又爽免费| 日韩中文在线视频| 丁香5月婷婷久久| 天美星空大象mv在线观看视频| 洋洋成人永久网站入口| 国产三级在线免费观看| 亚洲专区在线视频| 久久这里只有| 欧美日韩国产精品综合| 亚洲午夜色婷婷在线| 成人做爰视频www网站小优视频| 最新精品视频| 国产亚洲一二三区| 成人激情四射网| 国产精品美女网站|