美文网首页
vue-cli3 ssr 服务器渲染

vue-cli3 ssr 服务器渲染

作者: 带刀打天下 | 来源:发表于2020-04-24 16:35 被阅读0次
  1. 使用 vue-cli3 创建项目
  2. 项目结构


    image.png
  3. src 目录下 增加文件
    entry-client.js
import { createApp } from './main'

// 客户端特定引导逻辑……

const { app } = createApp()

// 这里假定 App.vue 模板中根元素具有 `id="app"`
app.$mount('#app')

entry-server.js

// entry-server.js
import { createApp } from './main'

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 应该 resolve 应用程序实例,以便它可以渲染
      resolve(app)
    }, reject)
  })
}

修改 main.js

// main.js
import Vue from 'vue'
import App from './App.vue'
import { createRouter } from "./router";
import { createStore } from "./store";
 
// 导出一个工厂函数,用于创建新的
// 应用程序、router 和 store 实例
export function createApp () {
 const router = createRouter();
 const store = createStore();
 const app = new Vue({
  router,
  store,
  // 根实例简单的渲染应用程序组件。
  render: h => h(App)
 })
 return { app }
}

修改 router.js

import Vue from 'vue'
import Router from 'vue-router'
import Home from '../views/Home.vue'
 
Vue.use(Router)
 
export function createRouter(){
 return new Router({
  mode: 'history', //一定要是history模式
  routes: [
   {
    path: '/',
    name: 'home',
    component: Home
   },
   {
    path: '/about',
    name: 'about',
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
   }
  ]
 })
}

新增配置文件
vue.config.js

const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')
const nodeExternals = require('webpack-node-externals')
const merge = require('lodash.merge')
const TARGET_NODE = process.env.WEBPACK_TARGET === 'node'
const target = TARGET_NODE ? 'server' : 'client'

module.exports = {
  configureWebpack: () => ({
    // 将 entry 指向应用程序的 server / client 文件
    entry: `./src/entry-${target}.js`,
    // 对 bundle renderer 提供 source map 支持
    devtool: 'source-map',
    target: TARGET_NODE ? 'node' : 'web',
    node: TARGET_NODE ? undefined : false,
    output: {
      libraryTarget: TARGET_NODE ? 'commonjs2' : undefined
    },
    // https://webpack.js.org/configuration/externals/#function
    // https://github.com/liady/webpack-node-externals
    // 外置化应用程序依赖模块。可以使服务器构建速度更快,
    // 并生成较小的 bundle 文件。
    externals: TARGET_NODE
      ? nodeExternals({
        // 不要外置化 webpack 需要处理的依赖模块。
        // 你可以在这里添加更多的文件类型。例如,未处理 *.vue 原始文件,
        // 你还应该将修改 `global`(例如 polyfill)的依赖模块列入白名单
        whitelist: [/\.css$/]
      })
      : undefined,
    optimization: {
      splitChunks: TARGET_NODE ? false : {
        chunks: "async",
        minSize: 30000,
        minChunks: 2,
        maxAsyncRequests: 5,
        maxInitialRequests: 3
       }
    },
    plugins: [TARGET_NODE ? new VueSSRServerPlugin() : new VueSSRClientPlugin()]
  }),
  chainWebpack: config => {
    config.module
      .rule('vue')
      .use('vue-loader')
      .tap(options => {
        return merge(options, {
          optimizeSSR: false
        })
      })
  }
}

node koa
app.js

const fs = require("fs");
const Koa = require("koa");
const path = require("path");
const koaStatic = require('koa-static')
const app = new Koa();
 
const resolve = file => path.resolve(__dirname, file);
// 开放dist目录
app.use(koaStatic(resolve('./dist')))
 
// 第 2 步:获得一个createBundleRenderer
const { createBundleRenderer } = require("vue-server-renderer");
const bundle = require("./dist/vue-ssr-server-bundle.json");
const clientManifest = require("./dist/vue-ssr-client-manifest.json");
 
const renderer = createBundleRenderer(bundle, {
 runInNewContext: false,
 template: fs.readFileSync(resolve("./src/index.temp.html"), "utf-8"),
 clientManifest: clientManifest
});
 
function renderToString(context) {
 return new Promise((resolve, reject) => {
  renderer.renderToString(context, (err, html) => {
   err ? reject(err) : resolve(html);
  });
 });
}
// 第 3 步:添加一个中间件来处理所有请求
app.use(async (ctx, next) => {
 const context = {
  title: "ssr test",
  url: ctx.url
 };
 // 将 context 数据渲染为 HTML
 const html = await renderToString(context);
 ctx.body = html;
});
 
const port = 3000;
app.listen(port, function() {
 console.log(`server started at localhost:${port}`);
});

相关文章

网友评论

      本文标题:vue-cli3 ssr 服务器渲染

      本文链接:https://www.haomeiwen.com/subject/ffgboctx.html