美文网首页
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