VUE项目配置SSR

 1、修改路由配置

// router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'

Vue.use(VueRouter)

// 工厂函数 每次请求返回一个Router实例
export function createRouter() {
  return new VueRouter({
    mode: 'history',
    base: process.env.BASE_URL,
    routes
  })
}

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About', 
    component: () => import('../views/About.vue')
  }
]

 2、修改vuex配置

// store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

//createStore
export function createStore() {
  return new Vuex.Store({
    state: {
      count: 99,
    },
    mutations: {
      add(state){ 
        state.count += 1
      }
    },
    actions: {
    },
    modules: {
    }
  })
}

 3、修改main.js

// main.js

import Vue from 'vue'
import App from './App.vue'

//引用createRouter,createStore 
import { createRouter } from './router'
import { createStore } from './store'

Vue.config.productionTip = false

// 需要每次请求 放回一个vue实例(不用挂载app)
export function createApp(context) {
  const router = createRouter()
  const store = createStore()
  const app = new Vue({
    router,
    store, // 挂载
    context, // 用于和外的renderer交互
    render: h => h(App)
  })

  return {app, router}
}

  4、在src录下创建服务端入口(entry-server.js)

// src/entry-server.js
// 和渲染器打交道
// 创建vue实例
import { createApp } from './main'

export default context => {
    const { app, router } = createApp(context)

    return new Promise((resolve, reject) => {
        // 跳转首屏地址
        router.push(context.url)

        // 等待路由就绪
        router.onReady(() => {
            resolve(app)
        }, reject)
        
    })
}

 5、在src目录下创建客户端入口文件entry-client.js

// src/entry-client.js

import { createApp } from './main'

const { app, router } = createApp()

router.onReady(() => {
    app.$mount('#app')
})

 6、webpack配置

npm install webpack-node-externals lodash.merge -D

npm i vue vue-server-renderer -S // 必须和vue保持同一版本

 7、在项目根目录下创建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 = {
  css: {
    extract: false
  },
  outputDir: './dist/'+target,
  configureWebpack: () => ({
    // 将 entry 指向应用程序的 server / client 文件
    entry: `./src/entry-${target}.js`,
    // 对 bundle renderer 提供 source map 支持
    devtool: 'source-map',
    // target设置为node使webpack以Node适用的方式处理动态导入,
    // 并且还会在编译Vue组件时告知`vue-loader`输出面向服务器代码。
    target: TARGET_NODE ? "node" : "web",
    // 是否模拟node全局变量
    node: TARGET_NODE ? undefined : false,
    output: {
      // 此处使用Node风格导出模块
      libraryTarget: TARGET_NODE ? "commonjs2" : undefined
    },
    // https://webpack.js.org/configuration/externals/#function
    // https://github.com/liady/webpack-node-externals
    // 外置化应用程序依赖模块。可以使服务器构建速度更快,并生成较小的打包文件。
    externals: TARGET_NODE
      ? nodeExternals({
          // 不要外置化webpack需要处理的依赖模块。
          // 可以在这里添加更多的文件类型。例如,未处理 *.vue 原始文件,
          // 还应该将修改`global`(例如polyfill)的依赖模块列入白名单
          whitelist: [/\.css$/]
        })
      : undefined,
    optimization: {
      splitChunks: undefined
    },
    // 这是将服务器的整个输出构建为单个 JSON 文件的插件。
    // 服务端默认文件名为 `vue-ssr-server-bundle.json`
    // 客户端默认文件名为 `vue-ssr-client-manifest.json`。
    plugins: [TARGET_NODE ? new VueSSRServerPlugin() : new VueSSRClientPlugin()]
  }),
  chainWebpack: config => {
    // cli4项目添加
    if (TARGET_NODE) {
        config.optimization.delete('splitChunks')
    }
      
    config.module
      .rule("vue")
      .use("vue-loader")
      .tap(options => {
        merge(options, {
          optimizeSSR: false
        });
      });
  }
};

 8、脚本配置安装依赖

npm i cross-env -D

 9、修改package.json配置

"scripts": {
    "serve": "vue-cli-service serve",
    "build": "npm run build:server & npm run build:client",
    "build:client": "vue-cli-service build",
    "build:server": "cross-env WEBPACK_TARGET=node vue-cli-service build"
  },

10、修改public目录下的index.html 

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <!-- 1.删掉之前动态标签 -->
    <title>{{title}}</title>
  </head>
  <body>
    <!-- 2.把宿主元素变成一个注释 -->
    <div id="app">
        <!--vue-ssr-outlet-->
    </div>
  </body>
</html>

11、新增服务器启动文件 (根目录创建文件 server/ssr.js)

// 创建一个express实例
const express = require('express')

const app = express()

// 获取绝对地址
const resolve = dir => require('path').resolve(__dirname, dir)

// 静态文件服务
// 开发dist/client目录,关闭默认的index页面打开功能
app.use(express.static(resolve('../dist/client'), {index: false}))

// 创建渲染器
const { createBundleRenderer } = require('vue-server-renderer')
// 参数1:服务端bundle
const bundle = resolve('../dist/server/vue-ssr-server-bundle.json')
const renderer = createBundleRenderer(bundle, {
  runInNewContext: false, // https://ssr.vuejs.org/zh/api/#runinnewcontext
  template: require('fs').readFileSync(resolve("../public/index.html"), "utf-8"), // 宿主文件
  clientManifest: require(resolve("../dist/client/vue-ssr-client-manifest.json")) // 客户端清单
})


// 只做一个件事,渲染
app.get('*', async (req, res) => {

  try {
    const context = {
title:'',
      url: req.url
    }
    // 渲染: 得到html字符串
    const html = await renderer.renderToString(context)
    // 发送回前端
    res.send(html)
  } catch (error) {
    res.status(500).send('服务器内部错误')
  }

})

// 监听端口
app.listen(3000, () => console.log('服务器开启'))

12、打包文件

npm run build 

//会创建一个dist文件目录,名下包括client和server两个文件件

13、启动服务器node

node ./server/ssr.js 

 14、注意事项

1)、vue与vue-server-renderer版本一致

2)、报错:Error: [webpack-node-externals] : Option 'whitelist' is not supported. Did you mean 'allowlist'   //修改vue.config.js(whitelist 改成 allowlist)

3)、在beforeCreate,created除外的生命周期以及全局的执行环境中调用特定的api前需要判断执行环境

4)、每次修改需要重新打包,重启服务器

5)、其他注意事项vue-ssr问题 - 简书

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ahwangzc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值