资讯专栏INFORMATION COLUMN

从零开始搭建一个vue-ssr(下)

Jochen / 668人阅读

摘要:开始改建补充安装依赖与上一次不同,这次我们基于进行改建,已经有了很多依赖库了,但我们任需要补充一个核心修改客户端的配置修改文件,添加插件添加了这个配置以后,重新启动项目通过地址就可以访问到,页面中出现的内容就是所需要的。

从零开始搭建一个vue-ssr 前言

上次我们已经实现了从零开始,搭建一个简单的vue-ssr的demo:从零开始搭建一个vue-ssr(上)。那么这次呢,我们基于vue-cli,进行webpack的改造,实现vue-cli版本的vue-ssr。

开始改建 补充安装依赖

与上一次不同,这次我们基于vue-cli进行改建,已经有了很多依赖库了,但我们任需要补充一个核心:

npm install vue-server-renderer
修改客户端的webpack配置

修改webpack.dev.conf.js文件,添加插件

const vueSSRClientPlugin = require("vue-server-renderer/client-plugin");

const devWebpackConfig = merge(baseWebpackConfig,{
    plugins:[
        new vueSSRClientPlugin()
    ] 
});

添加了这个配置以后,重新启动项目通过地址就可以访问到vue-ssr-client-manifest.json(http://localhost:8082/vue-ssr-client-manifest.json),页面中出现的内容就是所需要的client-bundle。

修改vue的相关文件

此步骤跟从零开始搭建一个vue-ssr(上)大有相似,不重复描述,直接上代码:
修改 router/index.js

import vueRouter from "vue-router";
import Vue from "vue";
import HelloWorld from "@/components/HelloWorld";
import About from "@/components/About";

Vue.use(vueRouter);
export default () => {
  return new vueRouter({
    mode:"history",
    routes:[
      {
        path:"/",
        component:HelloWorld,
        name:"HelloWorld"
      },
      {
        path:"/about",
        component:About,
        name:"About"
      }
    ]
  })
}

修改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,
    components: { App },
    template: ""
  });
  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.onReady(() => {
            let matchedComponents = router.getMatchedComponents();
            if(!matchedComponents.length){
                return reject();
            }
            reslove(app);
        },reject)
    })
}

修改entry-client.js

import createApp from "./app.js";
let {app,router} = createApp();

router.onReady(() => {
    app.$mount("#app");
});
修改webpack客户端入口以及输出

修改webpack.base.conf.js

module.exports = {
    entry:{
        app:"./src/entry-client.js"
    },
    output:{
        publicPath:"http://localhost:8080/"
    }
};
创建服务端webpakc配置文件

创建build/webpack.server.conf.js文件,目的将插件vue-server-renderer/server-plugin引入server端执行。

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-renderer/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 webpack.DefinePlugin({
            "process.env.NODE_ENV":""development"",
            "process.ent.VUE_ENV": ""server""
        }),
        new vueSSRServerPlugin()
    ]
});

创建build/dev-server.js,拿到客户端和服务端的bundle文件以及读取到index.html中的模板用作渲染。

const serverConf = require("./webpack.server.conf");
const webpack = require("webpack");
const fs = require("fs");
const path = require("path");
//  读取内存中的.json文件
//  这个模块需要手动安装
const Mfs = require("memory-fs");
const axios = require("axios");

module.exports = (cb) => {
    const webpackComplier = webpack(serverConf);
    var mfs = new Mfs();
    
    webpackComplier.outputFileSystem = mfs;
    
    webpackComplier.watch({},async (error,stats) => {
        if(error) return console.log(error);
        stats = stats.toJson();
        stats.errors.forEach(error => console.log(error));
        stats.warnings.forEach(warning => console.log(warning));
        //  获取server bundle的json文件
        let serverBundlePath = path.join(serverConf.output.path,"vue-ssr-server-bundle.json");
        let serverBundle = JSON.parse(mfs.readFileSync(serverBundlePath,"utf-8"));
        //  获取client bundle的json文件
        let clientBundle = await axios.get("http://localhost:8082/vue-ssr-client-manifest.json");
        //  获取模板
        let template = fs.readFileSync(path.join(__dirname,"..","index.html"),"utf-8");
        cb && cb(serverBundle,clientBundle,template);
    })
};

在根目录下创建server.js文件,用于启动服务,并利用createBundleRenderer将两个Bundle和html模板渲染出来。

const devServer = require("./build/dev-server.js");
const express = require("express");
const app = express();
const vueRender = require("vue-server-renderer");

app.get("*",(request,respones) => {
    respones.status(200);
    respones.setHeader("Content-Type","text/html;charset-utf-8;");
    devServer((serverBundle,clientBundle,template) => {
        let render = vueRender.createBundleRenderer(serverBundle,{
            template,
            clientManifest:clientBundle.data,
            //  每次创建一个独立的上下文
            renInNewContext:false
        }); 
        render.renderToString({
            url:request.url
        }).then((html) => {
            respones.end(html);
        }).catch(error => {
          respones.end(JSON.stringify(error));
        });
    });
})

app.listen(5001,() => {
    console.log("服务已开启")
});
补充一个html模板

根目录下创建index.html



  
    
    
    vue_cli_ssr
  
  
    

最后在package.json中添加一个启动服务端的命令:

"server": "node server.js"

大功告成,开启两个终端,分别输入

npm run dev
npm run server

浏览器打开localhost:8082,我们便可以看到由vue-cli改造而成的vue-ssr。

总结

本文是直接基于vue-cli进行改造的一个ssr版本,若想从零开始手撕vue-ssr,可以看上一篇文章从零开始搭建一个vue-ssr(上)。

项目源码

https://github.com/TheWalking...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/105153.html

相关文章

  • 从零开始搭建一个vue-ssr(上)

    摘要:从零开始搭建一个背景是什么全拼是,服务端渲染。大家不妨可以打开一些页面或者一些公司的网站,查看源代码,你会发现,也是有这个标记。这时候,我们发现页面的路由切换生效了,并且不同页面的源代码也不一样了。从零开始搭建一个下项目源码 从零开始搭建一个vue-ssr 背景 What?SSR是什么? SSR全拼是Server-Side Rendering,服务端渲染。 所谓服务端渲染,指的是把...

    Winer 评论0 收藏0
  • vue服务端渲染demo将vue-cli生成的项目转为ssr

    摘要:无需使用服务器实时动态编译,而是使用预渲染方式,在构建时简单地生成针对特定路由的静态文件。与可以部署在任何静态文件服务器上的完全静态单页面应用程序不同,服务器渲染应用程序,需要处于运行环境。更多的服务器端负载。 目录结构 -no-ssr-demo 未做ssr之前的项目代码用于对比 -vuecli2ssr 将vuecli生成的项目转为ssr -prerender-demo 使用prer...

    whinc 评论0 收藏0
  • 用vue搭建的个人博客介绍----mapblog小站

    摘要:后端主要使用的框架,数据库采用。后台管理登录采用与后端进行登陆状态的确认。本文首发于小站,这是一个积累和分享知识的个人博客 这篇文章搁置了很长时间,最终决定还是把它写出来,给刚开始学习vue并且想用vue写个人博客的同学一个参考。因为当初我也是参考了其他人分享的知识,从一个vue小白变成了一个入门级选手,并最终完成了这个个人博客的搭建工作,代码已托管在Github-justJokee。...

    Ashin 评论0 收藏0
  • 每个前端猿都有一个开发属于自己技术博客的心

    摘要:总算是今天成功把自己的孩子托付到阿里云的服务器上面了。中间还遇到很多很多坑最后看这自己所部署的三个网站安静的躺在自己租的阿里云上。 一把桌子,一台电脑,一瓶红牛,一包纸巾,从白天到黑夜。历经一个多月的时间,从零到构思到设计,从设计到vue-ssr 的框架设计,然后再从前端的业务逻辑代码的实现,从 后台nodejs 的 koa2框架到数据库的设计到后端的业务逻辑的代码实现,从购买阿里云服...

    wslongchen 评论0 收藏0

发表评论

0条评论

Jochen

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<