欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue ssr+koa2構(gòu)建服務(wù)端渲染的示例代碼

 更新時間:2020年03月23日 09:35:06   作者:三只萌新  
這篇文章主要介紹了vue ssr+koa2構(gòu)建服務(wù)端渲染的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

之前做了活動投放頁面在百度、360等渠道投放,采用 koa2 + 模版引擎的方式。發(fā)現(xiàn)幾個問題

  • 相較于框架開發(fā)頁面效率較低,維護(hù)性差
  • 兼容性問題,在頁面中添加埋點(diǎn)后發(fā)現(xiàn)有些用戶的數(shù)據(jù)拿不到,排查后發(fā)現(xiàn)通過各個渠道過來的用戶的設(shè)備中仍然包含大量低版本的瀏覽器。

 服務(wù)端渲染

 服務(wù)端渲染和單頁面渲染區(qū)別

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

 

 

@vue/cli 4 來構(gòu)建項(xiàng)目結(jié)構(gòu)

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

step1 安裝最新的腳手架初始化項(xiàng)目

yarn global add @vue/cli

step2 添加服務(wù)端文件

啟動一個 web 服務(wù)下方代碼中 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

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

const fs = require('fs')
const path = require('path')
const send = require('koa-send')
const Router = require('koa-router')
const router = new Router()
// 獲取當(dāng)前文件的絕對路徑
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')
// 創(chuàng)建一個 BunleRender 實(shí)例用于 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 回調(diào)函數(shù)是可選項(xiàng)。在不傳遞 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 // (可選)客戶端構(gòu)建 manifest
})

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

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

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

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

大體的流程就是:服務(wù)端創(chuàng)建 vue 實(shí)例,將頁面中的異步請求的數(shù)據(jù)拿到存儲在容器中 --> 客戶端接收到服務(wù)端發(fā)送的 html 以激活模式進(jìn)行掛載,自動給根元素 #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 => {
 // 因?yàn)橛锌赡軙钱惒铰酚摄^子函數(shù)或組件,所以我們將返回一個 Promise,
 // 以便服務(wù)器能夠等待所有的內(nèi)容在渲染前,
 // 就已經(jīng)準(zhǔn)備就緒。
 return new Promise((resolve, reject) => {
 const { app, router, store } = createApp()
 // 設(shè)置服務(wù)器端 router 的位置
 router.push(context.url)

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

  // 匹配不到的路由,執(zhí)行 reject 函數(shù),并返回 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(() => {
  // 在所有預(yù)取鉤子(preFetch hook) resolve 后,
  // 我們的 store 現(xiàn)在已經(jīng)填充入渲染應(yīng)用程序所需的狀態(tài)。
  // 當(dāng)我們將狀態(tài)附加到上下文,
  // 并且 `template` 選項(xiàng)用于 renderer 時,
  // 狀態(tài)將自動序列化為 `window.__INITIAL_STATE__`,并注入 HTML。
  // 否則會導(dǎo)致客戶端和服務(wù)端數(shù)據(jù)不統(tǒng)一造成渲染錯誤
  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地址

順便貼上這張圖

 

到此這篇關(guān)于vue ssr+koa2構(gòu)建服務(wù)端渲染的示例代碼的文章就介紹到這了,更多相關(guān)vue ssr koa2 服務(wù)端渲染內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue中在新窗口打開頁面及Vue-router的使用

    Vue中在新窗口打開頁面及Vue-router的使用

    這篇文章主要介紹了Vue中在新窗口打開頁面 及 Vue-router的使用,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-06-06
  • vue組件實(shí)現(xiàn)進(jìn)度條效果

    vue組件實(shí)現(xiàn)進(jìn)度條效果

    這篇文章主要為大家詳細(xì)介紹了vue組件實(shí)現(xiàn)進(jìn)度條效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • Vue懸浮窗和聚焦登錄組件功能實(shí)現(xiàn)

    Vue懸浮窗和聚焦登錄組件功能實(shí)現(xiàn)

    這篇文章主要介紹了Vue懸浮窗和聚焦登錄組件經(jīng)驗(yàn)總結(jié),? 本文整理了實(shí)現(xiàn)懸浮窗以及聚焦登錄組件的功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-11-11
  • vue中map()快速使用方法小結(jié)

    vue中map()快速使用方法小結(jié)

    map()函數(shù)是在JS的數(shù)組中定義的,它返回一個新的數(shù)組,下面這篇文章主要給大家介紹了關(guān)于vue中map()快速使用的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • vue-cli 首屏加載優(yōu)化問題

    vue-cli 首屏加載優(yōu)化問題

    這篇文章主要介紹了vue-cli 首屏加載優(yōu)化問題,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-11-11
  • vue數(shù)據(jù)更新了但在頁面上沒有顯示出來的解決方法

    vue數(shù)據(jù)更新了但在頁面上沒有顯示出來的解決方法

    有時候 vue 無法監(jiān)聽到數(shù)據(jù)的變化,導(dǎo)致數(shù)據(jù)變化但是視圖沒有變化,也就是數(shù)據(jù)更新了,但在頁面上沒有顯示出來,所以本文給出了三種解決方法,通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • VUE3傳值相關(guān)的6種方法總結(jié)

    VUE3傳值相關(guān)的6種方法總結(jié)

    件間傳參是vue開發(fā)過程中一個很常見的應(yīng)用,對于我們后端開發(fā)來說,每次看到這種組件傳參的代碼就一頭霧水,下面這篇文章主要給大家介紹了關(guān)于VUE3傳值相關(guān)的6種方法,需要的朋友可以參考下
    2023-04-04
  • Vue入門實(shí)戰(zhàn)之天氣預(yù)報

    Vue入門實(shí)戰(zhàn)之天氣預(yù)報

    這篇文章主要為大家詳細(xì)介紹了Vue入門實(shí)戰(zhàn)之天氣預(yù)報,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 詳解vue頁面狀態(tài)持久化詳解

    詳解vue頁面狀態(tài)持久化詳解

    這篇文章主要為大家介紹了vue頁面狀態(tài)持久化,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • Vue與.net?Core?接收List<T>泛型參數(shù)

    Vue與.net?Core?接收List<T>泛型參數(shù)

    這篇文章主要介紹了Vue與.net?Core?接收List<T>泛型參數(shù),文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-04-04

最新評論