91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在vue中使用ssr+koa2構建服務端渲染

發布時間:2021-05-07 15:13:02 來源:億速云 閱讀:318 作者:Leah 欄目:web開發

這篇文章給大家介紹怎么在vue中使用ssr+koa2構建服務端渲染,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

vue是什么

Vue是一套用于構建用戶界面的漸進式JavaScript框架,Vue與其它大型框架的區別是,使用Vue可以自底向上逐層應用,其核心庫只關注視圖層,方便與第三方庫和項目整合,且使用Vue可以采用單文件組件和Vue生態系統支持的庫開發復雜的單頁應用。

 服務端渲染

 服務端渲染和單頁面渲染區別

查看下面兩張圖,可以看到如果是服務端渲染,那么在瀏覽器中拿到的直接是完整的 html 結構。而單頁面是一些 script 標簽引入的js文件,最終將虛擬dom去掛在到 #app 容器上。

怎么在vue中使用ssr+koa2構建服務端渲染 

怎么在vue中使用ssr+koa2構建服務端渲染 

@vue/cli 4 來構建項目結構

下面代碼使用最精簡的實例完整代碼會放到 github 上

step1 安裝最新的腳手架初始化項目

yarn global add @vue/cli

step2 添加服務端文件

啟動一個 web 服務下方代碼中 http://localhost:9000 就是我們最終要訪問到地址

const Koa = require('koa')
const path = require('path')

const resolve = file => path.resolve(__dirname, file)
const app = new Koa()
const router = require('./router')
const port = 9000
app.listen(port, () => {
 console.log(`server started at localhost:${port}`)
})
module.exports = app

這里只是啟動了服務,我們需要在去讀取服務端和客戶端到文件,下面代碼就是服務端渲染的關鍵步驟

const fs = require('fs')
const path = require('path')
const send = require('koa-send')
const Router = require('koa-router')
const router = new Router()
// 獲取當前文件的絕對路徑
const resolve = file => path.resolve(__dirname, file)
const { createBundleRenderer } = require('vue-server-renderer')
const bundle = require('../dist/vue-ssr-server-bundle.json')
const clientManifest = require('../dist/vue-ssr-client-manifest.json')
// 創建一個 BunleRender 實例用于 renderer.renderToString 將 bundle 渲染為字符串
const renderer = createBundleRenderer(bundle, {
 runInNewContext: false,
 template: fs.readFileSync(resolve('../src/index.temp.html'), 'utf-8'),
 clientManifest: clientManifest
})

const handleRequest = async ctx => {
 ctx.res.setHeader('Content-Type', 'text/html')
 // 在 2.5.0+ 版本中,此 callback 回調函數是可選項。在不傳遞 callback 時,此方法返回一個 Promise 對象,在其 resolve 后返回最終渲染的 HTML。
 ctx.body = await renderer.renderToString(Object.assign({}, ctx.state.deliver, { url }))
}
router.get('/home',handleRequest)
module.exports = router

vue-server-render 提供一個名為 createBundleRenderer 的 API 使用方法如下

const { createBundleRenderer } = require('vue-server-renderer')

const renderer = createBundleRenderer(serverBundle, {
 runInNewContext: false, // 推薦
 template, // (可選)頁面模板
 clientManifest // (可選)客戶端構建 manifest
})

通過上面的 createBundleRenderer 方法生產 render 對象最終將 bunlde 渲染為字符串,將最終的 html 返回給客戶端。

bundleRenderer.renderToString([context, callback]): ?Promise<string>

step3 添加 entry-client.js,entry-server.js 入口文件

在 src 中除了這兩個入口文件,其他的文件都是在客戶端和服務端公用的。來看下這兩個入口文件中分別干了什么。

大體的流程就是:服務端創建 vue 實例,將頁面中的異步請求的數據拿到存儲在容器中 --> 客戶端接收到服務端發送的 html 以激活模式進行掛載,自動給根元素 #app 上添加 data-server-rendered="true" 特殊屬性

main.js

import Vue from 'vue'
import App from './App.vue'
...
export function createApp() {
 // ...
 const app = new Vue({
 router,
 store,
 render: h => h(App)
 })
 return { app, router, store }
}

entry-server.js

import { createApp } from './main.js'
export default context => {
 // 因為有可能會是異步路由鉤子函數或組件,所以我們將返回一個 Promise,
 // 以便服務器能夠等待所有的內容在渲染前,
 // 就已經準備就緒。
 return new Promise((resolve, reject) => {
 const { app, router, store } = createApp()
 // 設置服務器端 router 的位置
 router.push(context.url)

 // 等到 router 將可能的異步組件和鉤子函數解析完
 router.onReady(() => {
  const matchedComponents = router.getMatchedComponents()

  // 匹配不到的路由,執行 reject 函數,并返回 404
  if (!matchedComponents.length) {
  return reject({ code: 404 })
  }
  Promise.all(
  matchedComponents.map(component => {
   if (component.asyncData) {
   return component.asyncData({
    store,
    context,
    route: router.currentRoute
   })
   }
  })
  ).then(() => {
  // 在所有預取鉤子(preFetch hook) resolve 后,
  // 我們的 store 現在已經填充入渲染應用程序所需的狀態。
  // 當我們將狀態附加到上下文,
  // 并且 `template` 選項用于 renderer 時,
  // 狀態將自動序列化為 `window.__INITIAL_STATE__`,并注入 HTML。
  // 否則會導致客戶端和服務端數據不統一造成渲染錯誤
  context.state = store.state
  resolve(app)
  }).catch(reject)
 }, reject)
 })
}

entry-client.js

import { createApp } from './main'
const { app, router, store } = createApp()

if (window.__INITIAL_STATE__) {
 store.replaceState(window.__INITIAL_STATE__)
}

router.onReady(() => {
 router.beforeResolve((to, from, next) => {
 const matched = router.getMatchedComponents(to)
 const prevMatched = router.getMatchedComponents(from)
 let diffed = false
 const activated = matched.filter((c, i) => {
  return diffed || (diffed = prevMatched[i] !== c)
 })

 if (!activated.length) {
  return next()
 }

 Promise.all(
  activated.map(component => {
  if (component.asyncData) {
   component.asyncData({
   store,
   route: to
   })
  }
  })
 )
  .then(() => {
  next()
  })
  .catch(next)
 })
 app.$mount('#app')
})

最后

完整代碼參考 github地址

順便貼上這張圖

 怎么在vue中使用ssr+koa2構建服務端渲染

關于怎么在vue中使用ssr+koa2構建服務端渲染就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

灵寿县| 金沙县| 桑植县| 伊宁市| 宜州市| 武夷山市| 静宁县| 出国| 五指山市| 民勤县| 吉安县| 连云港市| 册亨县| 德州市| 恩施市| 彰化县| 南皮县| 太白县| 正蓝旗| 南漳县| 隆安县| 邳州市| 利津县| 分宜县| 太白县| 丹江口市| 岳阳市| 平阴县| 固始县| 蓝山县| 武隆县| 临武县| 巴马| 日土县| 绵竹市| 水富县| 南丹县| 钟祥市| 霍林郭勒市| 尤溪县| 榕江县|