詳解Vue SSR服務(wù)端渲染

Vue SSR介紹

SSR Github Demo

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

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

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

與傳統(tǒng) SPA (單頁(yè)應(yīng)用程序 (Single-Page Application)) 相比,服務(wù)器端渲染 (SSR) 的優(yōu)勢(shì)主要在于:

更好的 SEO,由于搜索引擎爬蟲抓取工具可以直接查看完全渲染的頁(yè)面。
更快的內(nèi)容到達(dá)時(shí)間 (time-to-content),特別是對(duì)于緩慢的網(wǎng)絡(luò)情況或運(yùn)行緩慢的設(shè)備。無需等待所有的 JavaScript 都完成下載并執(zhí)行,才顯示服務(wù)器渲染的標(biāo)記,所以你的用戶將會(huì)更快速地看到完整渲染的頁(yè)面。

SSR渲染過程

image.png

我們可以看到,左側(cè)Source部分就是我們所編寫的源代碼,所有代碼有一個(gè)公共入口,就是app.js,緊接著就是服務(wù)端的入口
(entry-server.js)和客戶端的入口(entry-client.js)。當(dāng)完成所有源代碼的編寫之后,我們通過webpack的構(gòu)建,打包出兩個(gè)bundle,分別是server bundle和client bundle;當(dāng)用戶進(jìn)行頁(yè)面訪問的時(shí)候,先是經(jīng)過服務(wù)端的入口,將vue組建組裝為html字符串,并混入客戶端所訪問的html模板中,最終就完成了整個(gè)ssr渲染的過程。

Nuxt框架

Nuxt 是一個(gè)基于 Vue 生態(tài)的更高層的框架,為開發(fā)服務(wù)端渲染的 Vue 應(yīng)用提供了極其便利的開發(fā)體驗(yàn)。更酷的是,你甚至可以用它來做為靜態(tài)站生成器。

nuxt官網(wǎng)介紹

安裝

// init過程中根據(jù)提示安裝用到的插件燈
npm init nuxt-app <project-name>

cd <project-name>
npm run dev

配置

nuxt.config.js

const path = require('path')
export default {
  // 允許你在`Javascript`和`Css`中使用別名訪問自定義目錄
  alias: {
    '~~': `<rootDir>`,
    '@@': `<rootDir>`,
    '~': `<srcDir>`,
    '@': `<srcDir>`,
    'assets': `<srcDir>/assets`, // (unless you have set a custom `dir.assets`)
    'static': `<srcDir>/static`, // (unless you have set a custom `dir.static`)
    'style': path.resolve(__dirname, './assets/style')
  },

  // 定義應(yīng)用程序的工作區(qū)目錄,默認(rèn)值process.cwd()
  rootDir: '',

  // 定義應(yīng)用程序的source目錄,默認(rèn)值同rootDir
  srcDir: '',

  // server連接配置
  server: {
    port: 3000, // default: 3000
    host: '0.0.0.0', // default: localhost,
    timing: false
  },

  // npm run generate時(shí)執(zhí)行,構(gòu)建部署靜態(tài)應(yīng)用程序
  generate: {
    // 目錄名
    dir: 'dist'
  },

  // true啟動(dòng)服務(wù)器端渲染,false只啟動(dòng)客戶端渲染
  ssr: true,

  // headers設(shè)置,Global page headers: https://go.nuxtjs.dev/config-head
  head: {
    title: 'ssr-demo',
    htmlAttrs: {
      lang: 'en'
    },
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: '' }
    ],
    link: [
      { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
    ]
  },

  // 全局css,Global CSS: https://go.nuxtjs.dev/config-css
  css: [
    // 'ant-design-vue/dist/antd.css'
    // css后綴可以省略
    'assets/style/common'
  ],

  // 添加plugins目錄下的js文件到應(yīng)用程序中,Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
  plugins: [
    '@/plugins/antd-ui',
    '@/plugins/veui'
  ],

  // 自動(dòng)掃描和導(dǎo)入組件,無需在使用時(shí)import組件,可直接使用,Auto import components: https://go.nuxtjs.dev/config-components
  components: true,

  // Build Configuration: https://go.nuxtjs.dev/config-build
  build: {
    // 是否提取css至獨(dú)立文件中
    // extractCSS: true,
    // babel相關(guān)配置
    babel: {
      plugins: [
        'veui',
        ['import', {
          'libraryName': 'ant-design-vue',
          'libraryDirectory': 'es',
          'style': true
            // customStyleName: name => {
            //   return `assets/${name}.css`
            // }
          }
        ] // `style: true` 會(huì)加載 less 文件
      ]
    },
    // 可省略的擴(kuò)展名
    resolve: {
      extensions: ['.js', '.vue', '.json']
    },
    // 需要進(jìn)行babel編譯的包
    transpile: ['veui', 'vue-awesome', 'ant-design-vue'],
    // loader配置
    loaders: {
      vue: {
        extractCSS: true
      },
      less: {
        javascriptEnabled: true
      }
    },
    // 手動(dòng)擴(kuò)展客戶端和服務(wù)端的webpack配置
    extend(config, context){
        //添加loader規(guī)則
          config.module.rules.push({
              test: /\.vue$/, //匹配.svg
              include: [path.resolve(__dirname, 'node_modules/veui')], //將存放svg的目錄加入到loader處理目錄
              use: [{ loader: 'veui-loader', options: {
                modules: [
                  {
                    package: 'veui-theme-blue',
                    fileName: '${module}.less'
                  },
                  {
                    package: 'veui-theme-blue',
                    fileName: '${module}.js',
                    transform: false
                  }
                ]
              }}]
          })
    }
  }
}

Demo示例

1. ssr: true,服務(wù)端渲染

服務(wù)端渲染時(shí),可以看到入口返回的Preview就是在服務(wù)端生成好的頁(yè)面,這種方式更利于SEO和快速展示頁(yè)面。


image.png

2. ssr: false,客戶端渲染

客戶端渲染時(shí),可以看到入口返回的Preview是一個(gè)空白頁(yè)面,頁(yè)面的Dom是由提取的其他js在瀏覽器端動(dòng)態(tài)生成的。


image.png

3. BundleRenderer自動(dòng)內(nèi)聯(lián)關(guān)鍵CSS(critical css)

關(guān)于critical css的介紹,可以看另一篇文章:https://juejin.cn/post/6946475178188603429/
pages/index.vue為首屏渲染頁(yè)面

<template>
    <div class="index">首頁(yè)</div>
</template>
<style>
.index {
    color: red;
}
</style>

新建pages/test.vue頁(yè)面,驗(yàn)證SSR是否會(huì)自動(dòng)注入關(guān)鍵css(critical css

<template>
    <div class="test">測(cè)試</div>
</template>
<style>
.test {
    color: red;
}
</style>
  • index.vue中引入test.vue,服務(wù)啟動(dòng)后,test.vue樣式也以style形式內(nèi)嵌在頁(yè)面中
    image.png
  • 不在index.vue中引入test.vue,服務(wù)啟動(dòng)后,test.vue樣式則沒有內(nèi)嵌在首屏渲染頁(yè)面中
    image.png

    只有在訪問test路由時(shí)才顯示test.vue相關(guān)樣式
    image.png

總結(jié):SSR服務(wù)端會(huì)自動(dòng)注入首屏渲染關(guān)鍵css,無需引入其他插件。

4. extract提取css

啟用extract提取css后,樣式被提取到單獨(dú)的css文件中,以外鏈的形式引入。

image.png

以上就是Vue SSR nuxt框架相關(guān)的整理,每天都有學(xué)不完的新知識(shí),加油?。?/strong>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容