Vue基於ssr渲染

vue ssr指南

傳統的瀏覽器端渲染

通常,我們的Vue項目實在npm run build打包之後,直接放到服務器端。瀏覽器去請求相應的html,加載對應的js文件,生成DOM。
路由改變,局部刷新,瀏覽器不會刷新
缺點
需要js全部加載完,頁面才能出來,加載較慢(懶加載)
js改變dom,生成頁面,不利於SEO

SSR(服務器端渲染是什麼)

SSR的原理是將打包後的文件,先在服務器端處理,生成一個個的HTML字符串,當瀏覽器請求的時候直接發過去。
每一個路由請求到的都是一個html串,路由改變,瀏覽器刷新
優點
利於SEO,搜索引擎爬蟲抓取工具可以直接查看完全渲染的頁面
更快的內容到達時間 (time-to-content),更好的用戶體驗,特別是對於緩慢的網絡情況或運行緩慢的設備。

預渲染

只是用來改善少數營銷頁面的 SEO,可以使用預渲染,在構建時 (build time) 簡單地生成針對特定路由的靜態 HTML 文件,而無需使用 web 服務器實時動態編譯 HTML。

vue項目中手動加入SSR

在這裏插入圖片描述
1、創建兩個js文件,server.js和client.js
將之前的一次打包,轉化爲兩次打包,一個用於服務端打包入口js文件,一個用於客戶端打包入口js文件。
server.js

//服務器端打包入口文件
import {createApp} from './main'
//根據返回的內容,拿到指定的路由節點
export default context => {
    return new Promise((resolve, reject)=>{
        const {app, router} = createApp();
        router.push(context.url);
        router.onReady(()=>{
            const mathComponents = router.getMatchedComponents();
            if(!mathComponents){
                return reject({code: 404});
            }
            resolve(app);
        },reject);
    })
}

client.js

//客戶端打包入口文件
import {createApp} from './main'
const {app,router} = createApp();
//路由完成之後,再去進行掛載,以防有異步路由的情況
router.onReady(()=>{
    app.$mount("#app");
})

2、新建存放服務器端生成的html模板
index.ssr.html用於保存服務器端生成的html,其中爲注入標記,即在這兒進行添加。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>ssr-test</title>
  </head>
  <body>
    <!--vue-ssr-outlet-->
    <script type="text/javascript" src="<%=htmlWebpackPlugin.options.files.js%>"></script>
  </body>
</html>

3、改造router和main文件,將其中的new Router和new Vue轉化爲方法,便於後面使用
router:

export function createRouter(){
  return new Router({
    mode: "history",
    routes: [
      {
        path: '/',
        name: 'HelloWorld',
        component: HelloWorld
      }
    ]
  })
}

main:

let router = createRouter();
export function createApp(){
  const app = new Vue({
    router,
    render:h => h(App)
  })
  return {app,router};
}

4、創建客戶端和服務器端打包配置文件
安裝:

npm install vue vue-server-renderer --save

webpack.build.server.js拷貝webpack.prod.conf.js生產打包配置文件進行修改

添加入口文件
打包後的服務端文件需要在node下面執行,所以將target指定爲node
nodejs的規範爲commonjs,所以需要將output中的libraryTarget指定爲commonjs。新版本node使用commonjs2
修改HtmlWebpackPlugin下面的模板文件和目標文件爲我們創建的index.ssr.html
刪除HtmlWebpackPlugin下面minify中的removeComments(刪除註釋),因爲我們上面說的服務器端html模板中的註釋有特定作用,不能被刪除
引入vue-server-renderer下面的server-plugin,並進行註冊
const VueSSRServePlugin = require('vue-server-renderer/server-plugin')
entry:{
  app:'./src/server.js'
},
target: 'node',
output:{
  libraryTarget:'commonjs2'  
},
plugins: [
    new VueSSRServePlugin(),
    new HtmlWebpackPlugin({
      filename: 'index.ssr.html',
      template: 'index.ssr.html',
      inject: true,
      files:{
        js:'app.js'
      },
      minify: {
        collapseWhitespace: true,
        removeAttributeQuotes: true
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
      },
      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
      chunksSortMode: 'dependency'
    })
]

webpack.build.client.js拷貝webpack.prod.conf.js生產打包配置文件進行修改

添加入口文件
引入vue-server-renderer下面的client-plugin,並進行註冊
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')
entry:{
  app:'./src/ client.js'
},

plugins: [
    new VueSSRClientPlugin(),
]

5、package.json中新加兩條打包命令

"build:client": "webpack --config build/webpack.build.client.js",
"build:server": "webpack --config build/webpack.build.server.js"
npm run build:client
npm run build:server

打包完成之後的目錄
在這裏插入圖片描述
6、配置node服務
根目錄創建server.js

const express = require('express');
const server = express();
const { createBundleRenderer } = require('vue-server-renderer');
const path = require('path');
const fs = require('fs');
const { target } = require('./config/dev.env');
const serverBuild = require(path.resolve(__dirname, "./dist/vue-ssr-server-bundle.json"));
const clientManifest = require(path.resolve(__dirname, "./dist/vue-ssr-client-manifest.json"));
const template = fs.readFileSync(path.resolve(__dirname, "./dist/index.ssr.html"), 'utf-8');
const renderer = createBundleRenderer(serverBuild, {
    runInNewContext: false,
    template: template,
    clientManifest: clientManifest
});
server.get("*", (req, res) => {
    if(req.url != "/favicon.ico"){
        const context = { url: req.url };
        const ssrStream = renderer.renderToStream(context);
        ssrStream.on('error',(err)=>{
            res.status(500).end('Internal Server Error')
            console.log(err);
            return;
        });
        let buffers = [];
        ssrStream.on('data',(data) => buffers.push(data));
        ssrStream.on('end', () => {res.end(Buffer.concat(buffers))});
    }
})
server.listen(1000);

7、啓動服務,查看效果

node server.js

在這裏插入圖片描述

nuxt配置SSR

nuxt中文網

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章