最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue ssr 指南詳讀

 更新時間:2018年06月29日 08:38:27   作者:__7克__  
這篇文章主要介紹了vue ssr 指南詳讀,詳細(xì)的介紹了什么是SSR以及如何使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

本帖說明

該貼是對vue SSR Guide解讀和補充,對于官網(wǎng)文檔已有內(nèi)容會以引用方式體現(xiàn)。由于官網(wǎng)demo在國內(nèi)無法運行,該貼最后也提供了一個完整的可以運行的demo,帖子中提到的代碼均是來自于該demo,供學(xué)習(xí)交流。

介紹

什么是服務(wù)器端渲染(SSR)?

Vue.js 是構(gòu)建客戶端應(yīng)用程序的框架。默認(rèn)情況下,可以在瀏覽器中輸出 Vue 組件,進行生成 DOM 和操作 DOM。然而,也可以將同一個組件渲染為服務(wù)器端的 HTML 字符串,將它們直接發(fā)送到瀏覽器,最后將靜態(tài)標(biāo)記"混合"為客戶端上完全交互的應(yīng)用程序。

借助vue-server-renderer 將vue實例渲染為瀏覽器可以識別的html字符串。

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

  1. 更好的 SEO
  2. 更快的內(nèi)容到達時間 (白屏)

左側(cè)為瀏覽器渲染,右側(cè)為服務(wù)器渲染,從圖中可以看出服務(wù)端渲染理論上明顯少于瀏覽器渲染。

基本用法

安裝

git clone https://github.com/s249359986/learnssr.git
cd learnssr 
npm install
npm run dev

代碼結(jié)構(gòu)

src
├── components
│  ├── Foo.vue
├── views
│  ├── Home.vue
├── App.vue
├── app.js 
├── client-entry.js
├── server-entry.js

代碼詳解

server.js 是服務(wù)端啟動入口文件,接收客戶端對頁面的所有請求。

if (isProd) {
 /**
  生產(chǎn)環(huán)境,createRenderer將已經(jīng)通過webpack打包好的server-bundle.js轉(zhuǎn)化為一個可以操作的renderer對象。
 **/
 renderer = createRenderer(fs.readFileSync(resolve('./dist/server-bundle.js'), 'utf-8'))
 
 /**
 入口模板文件
 **/
 indexHTML = parseIndex(fs.readFileSync(resolve('./dist/index.html'), 'utf-8'))
} else {
 /**
  開發(fā)環(huán)境,createRenderer將已經(jīng)通過webpack打包好的server-bundle.js轉(zhuǎn)化為一個可以操作的renderer對象。
 **/
 require('./build/setup-dev-server')(app, {
  bundleUpdated: bundle => {
   renderer = createRenderer(bundle)
  },
  indexUpdated: index => {//index為入口文件及index.html
   indexHTML = parseIndex(index)
  }
 })
}

function createRenderer (bundle) {

 return require('vue-server-renderer').createBundleRenderer(bundle, {
  cache: require('lru-cache')({
   max: 1,//1000,
   maxAge: 2000//1000 * 60 * 15
  }),
  runInNewContext: false
 })
}
/*
讀取入口文件
*/
function parseIndex (template) {
 const contentMarker = '<!-- APP -->'
 const i = template.indexOf(contentMarker)
 return {
  head: template.slice(0, i),
  tail: template.slice(i + contentMarker.length)
 }
}

const serve = (path, cache) => express.static(resolve(path), {
 maxAge: cache && isProd ? 60 * 60 * 24 * 30 : 0
})

app.use('/dist', serve('./dist'))

app.get('*', (req, res) => {
 if (!renderer) {
  return res.end('waiting for compilation... refresh in a moment.')
 }

 res.setHeader('Content-Type', 'text/html')
 res.setHeader('Server', serverInfo)

 var s = Date.now()
 const context = { url: req.url }
 /*
  渲染vue實例,context對象上下文
 */
 const renderStream = renderer.renderToStream(context)

 renderStream.once('data', () => {
  res.write(indexHTML.head)
 })

 renderStream.on('data', chunk => {
  res.write(chunk)
 })

 renderStream.on('end', () => {
  if (context.initialState) {
   res.write(
    `<script>window.__INITIAL_STATE__=${
     serialize(context.initialState, { isJSON: true })
    }</script>`
   )
  }
  res.end(indexHTML.tail)
  console.log(`whole request: ${Date.now() - s}ms`)
 })

 renderStream.on('error', err => {
  if (err && err.code === '404') {
   res.status(404).end('404 | Page Not Found')
   return
  }
  res.status(500).end('Internal Error 500')
  console.error(`error during render : ${req.url}`)
  console.error(err)
 })
})

const port = process.env.PORT || 8080
app.listen(port, () => {
 console.log(`server started at localhost:${port}`)
})

服務(wù)端vue實例入口文件,通過上下文對象獲取請求的url,映射給對應(yīng)的組件。

export default context => {
 const s = isDev && Date.now()
 router.push(context.url)
 const matchedComponents = router.getMatchedComponents()
 if (!matchedComponents.length) {
  return Promise.reject({ code: '404' })
 }
 return Promise.all(matchedComponents.map(component => {
/*
增加服務(wù)端數(shù)據(jù)預(yù)處理 start

*/
  if (component.asyncData) {
     return component.asyncData({
      store,
      route: router.currentRoute
     })
    }

    /*
    增加服務(wù)端數(shù)據(jù)預(yù)處理 end

    */
 })).then(() => {
  isDev && console.log(`data pre-fetch: ${Date.now() - s}ms`)
  context.initialState = store.state
  return app
 })
}

客戶端vue實例入口文件.

/*

第一種方式
 */

Vue.mixin({
 beforeMount () {
  const { asyncData } = this.$options
 console.log('beforeMount',this.$store)
  if (asyncData) {

   // 將獲取數(shù)據(jù)操作分配給 promise
   // 以便在組件中,我們可以在數(shù)據(jù)準(zhǔn)備就緒后
   // 通過運行 `this.dataPromise.then(...)` 來執(zhí)行其他任務(wù)
   this.dataPromise = asyncData({
    store: this.$store,
    route: this.$route
   })
  }
 },
 beforeRouteUpdate (to, from, next) {
 const { asyncData } = this.$options
 console.log('beforeRouteUpdate',this.$store)
 if (asyncData) {
 asyncData({
  store: this.$store,
  route: to
 }).then(next).catch(next)
 } else {
 next()
 }
}
})

/**
更新客戶端store,與服務(wù)端store同步
**/
// store.replaceState(window.__INITIAL_STATE__)
if (window.__INITIAL_STATE__) {
 store.replaceState(window.__INITIAL_STATE__)
}
// actually mount to DOM


router.onReady(() => {
/**
掛載實例,客戶端激活,所謂激活,指的是 Vue 在瀏覽器端接管由服務(wù)端發(fā)送的靜態(tài) HTML,使其變?yōu)橛?Vue 管理的動態(tài) DOM 的過程。注釋掉app.$mount('#app') 可以清楚看到<div id="app" data-server-rendered="true"> 客戶端通過data-server-rendered="true"知道該html是vue在服務(wù)端渲染的,并且不會在做多余的渲染。由于在服務(wù)端無法綁定事件,只有通過客戶端vue處理。
**/
 app.$mount('#app')
})

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Vue Router路由守衛(wèi)超詳細(xì)介紹

    Vue Router路由守衛(wèi)超詳細(xì)介紹

    路由守衛(wèi),簡單理解來說就是,當(dāng)用戶要進行一些操作時,我需要用戶的一些信息或數(shù)據(jù)或行為,我判斷過后,才會同意用戶進行操作,說到這里,我想大家心里都或多或少有點理解了吧
    2023-01-01
  • vue3使用Pinia的store的組件化開發(fā)模式詳解

    vue3使用Pinia的store的組件化開發(fā)模式詳解

    這篇文章主要介紹了vue3使用Pinia的store的組件化開發(fā)模式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • vue-rx的初步使用教程

    vue-rx的初步使用教程

    這篇文章主要介紹了vue-rx的初步使用教程,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • Vue3中Props和Emit的工作原理詳解

    Vue3中Props和Emit的工作原理詳解

    在現(xiàn)代前端開發(fā)中,Vue.js 來作為一個流行的 JavaScript 框架,提供了簡單易用的 API 和強大的功能,在 Vue 3 中,“Props”和“Emit”是兩個核心概念,本文將詳細(xì)探討這兩個概念的工作原理,并提供示例代碼以幫助更好地理解它們的使用,需要的朋友可以參考下
    2024-11-11
  • vuex2中使用mapGetters/mapActions報錯的解決方法

    vuex2中使用mapGetters/mapActions報錯的解決方法

    這篇文章主要介紹了vuex2中使用mapGetters/mapActions報錯解決方法 ,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-10-10
  • 詳解Nuxt.js Vue服務(wù)端渲染摸索

    詳解Nuxt.js Vue服務(wù)端渲染摸索

    本篇文章主要介紹了詳解Nuxt.js Vue服務(wù)端渲染摸索,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-02-02
  • vue實現(xiàn)分環(huán)境打包步驟(給不同的環(huán)境配置相對應(yīng)的打包命令)

    vue實現(xiàn)分環(huán)境打包步驟(給不同的環(huán)境配置相對應(yīng)的打包命令)

    這篇文章主要介紹了vue實現(xiàn)分環(huán)境打包步驟(給不同的環(huán)境配置相對應(yīng)的打包命令),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-06-06
  • 簡單了解vue 插值表達式Mustache

    簡單了解vue 插值表達式Mustache

    這篇文章主要介紹了vue 插值表達式Mustache的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • Vue.js項目前端多語言方案的思路與實踐

    Vue.js項目前端多語言方案的思路與實踐

    前端的國際化是一個比較常見的需求,但網(wǎng)上關(guān)于這一方面的直接可用的方案卻不多,這篇文章主要給大家介紹了關(guān)于Vue.js項目前端多語言方案的思路與實踐,需要的朋友可以參考下
    2021-07-07
  • vant中的toast層級改變操作

    vant中的toast層級改變操作

    這篇文章主要介紹了vant中的toast層級改變操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11

最新評論

郁南县| 石柱| 临武县| 平安县| 抚宁县| 定兴县| 大渡口区| 清新县| 奉新县| 额尔古纳市| 舟曲县| 小金县| 黔南| 霍山县| 清新县| 田阳县| 绥阳县| 淳化县| 土默特右旗| 婺源县| 原阳县| 卢氏县| 东阳市| 丰县| 池州市| 南汇区| 抚顺市| 台北县| 康马县| 云林县| 灵石县| 库车县| 巨野县| 晋江市| 门源| 宽甸| 高安市| 沙雅县| 郓城县| 泾阳县| 安图县|