整个项目的雏形也就这样了,由于服务端把路由控制权交还给客户端,需要复杂的webpack配置,so~不再赘述了,下面直接使用vue-cli继续(做的是使用需要用到上面的代码)。
vue-cli项目搭建
在做准备工作的时候简单讲述了vue中使用ssr的运行思路,里面提及了一个很重要的webpack,因此这里需要借助vue-cli脚手架,直接更改原有的webpack就可以了,这样会方便很多。
这里建议大家返回顶部再次看一下vue服务端渲染的流程,在介绍中的client-bundle和server-bundle,,所以需要构建两个配置,分别是服务端配置和客户端的配置。
如想要实现服务端渲染需要对vue-cli中个js文件中的配置进行修改。以下只展示更改部分的代码,不展示全部。
文件分别是:
webpack.server.conf.js - 服务端webpack配置
dev-server.js - 获取服务端bundle
server.js - 创建后端服务
webpack.dev.conf.js - 客户端的bundle
webpack.base.conf - 修改入口文件
客户端配置
客户端生成一份客户端构建清单,记录客户端的资源,最终会将客户端构建清单中记录的文件,注入到执行的执行的模板中,这个清单与服务端类似,同样也会生成一份json文件,这个文件的名字是vue-ssr-client-manifest.json(项目启动以后可以通过地址/文件名访问到),当然必不可少的是,同样也需要引入一个叫做vue-server-renderer/client-plugin模块,作为webpack的插件供其使用。
首先要安装一下vue-server-render这个模块,这个是整个服务端渲染的核心,没有整个ssr是没有任何灵魂的。
npm install vue-server-render -S
安装完成之后,首先要找到webpack.dev.conf.js,首先要对其进行相关配置。
webpack.dev.conf.js
// 添加引入 vue-server-render/client-plugin 模块 const vueSSRClientPlugin = require("vue-server-render/client-plugin"); const devWebpackConfig = merge(baseWebpackConfig,{ plugins:[ new vueSSRClientPlugin() ] });
添加了这个配置以后,重新启动项目通过地址就可以访问到vue-ssr-client-manifest.json(:8080/vue-ssr-client-manifest.json),页面中出现的内容就是所需要的client-bundle。
服务端配置
服务端会默认生成一个vue-ssr-server-bundle.json文件,在文件中会记录整个服务端整个输出,怎么才能生成这个文件呢?要在这个json文件,必须要引入vue-server-renderer/server-plugin,并将其作为webpack的插件。
在开始服务端配置之前,需要在src文件夹下面创建三个文件,app.js,entry-client.js,entry-server.js,创建完成之后需要对其写入相关代码。
src/router/index.js
import vueRouter from "vue-router"; import Vue from "vue"; import HelloWorld from "@/components/HelloWorld"); Vue.use(vueRouter); export default () => { return new vueRouter({ mode:"history", routers:[ { path:"https://www.jb51.net/", component:HelloWorld, name:"HelloWorld" } ] }) }
app.js
import Vue from "vue"; import createRouter from "./router"; import App from "./App.vue"; export default (context) => { const router = createRouter(); const app = new Vue({ router, component:{App}, template:"<App/>" }); return { app, router } }
entry-server.js
import createApp from "./app.js"; export default (context) => { return new Promise((reslove,reject) => { let {url} = context; let {app,router} = createApp(context); router.push(url); router.onRady(() => { let matchedComponents = router.getMatchedComponents(); if(!matchedComponents.length){ return reject({ code:404, }); } reslove(app); },reject) }) }
entry-client.js
import createApp from "./app.js"; let {app,router} = createApp(); router.onReady(() => { app.$mount("#app"); }); webpack.base.conf.js module.exports = { entry:{ app:"./src/entry-client.js" }, output:{ publicpath:"http://localhost:8080/" } };
webpack.server.conf.js(手动创建)
const webpack = require("webpack"); const merge = require("webpack-merge"); const base = require("./webpack.base.conf"); // 手动安装 // 在服务端渲染中,所需要的文件都是使用require引入,不需要把node_modules文件打包 const webapckNodeExternals = require("webpack-node-externals"); const vueSSRServerPlugin = require("vue-server-render/server-plugin"); module.exports = merge(base,{ // 告知webpack,需要在node端运行 target:"node", entry:"./src/entry-server.js", devtool:"source-map", output:{ filename:'server-buldle.js', libraryTarget: "commonjs2" }, externals:[ webapckNodeExternals() ], plugins:[ new webapck.DefinePlugin({ 'process.env.NODE_ENV':'"devlopment"', 'process.ent.VUE_ENV': '"server"' }), new vueSSRServerPlugin() ] });
dev-server.js(手动创建)