vuecli项目构建SSR服务端渲染的实现

服务端渲染(SSR)

将一个 Vue 组件在服务端渲染成 HTML 字符串并发送到浏览器,最后将这些静态标记“激活”为可交互应用程序的过程就叫服务端渲染(SSR)

服务器渲染的 Vue.js 应用程序也可以被认为是"同构"或"通用",因为应用程序的大部分代码都可以在服务器和客户端上运行

为什么使用 服务端渲染(SSR)

  • 更好的 SEO:传统的 spa 页面数据都是异步加载,搜索引擎爬虫无法抓取,服务端渲染(SSR)使搜索引擎爬虫抓取工具可以直接查看完全渲染的页面,解决 vue 项目的 seo 问题
  • 更快的内容到达时间 (首屏加载更快):请求页面时,服务端将渲染好的页面直接发送给浏览器进行渲染,浏览器只需要解析渲染 HTML,无需等待所有的 JavaScript 都完成下载并执行,才显示服务器渲染的标记

服务端渲染(SSR)缺点

  • 开发条件所限:浏览器特定的代码,只能在某些生命周期钩子函数中使用;一些外部扩展库可能需要特殊处理,才能在服务器渲染应用程序中运行
  • 涉及构建设置和部署的更多要求:与可以部署在任何静态文件服务器上的完全静态单页面应用程序 (SPA) 不同,服务器渲染应用程序,需要处于 Node.js server 运行环境
  • 更多的服务器端负载:在 Node.js 中渲染完整的应用程序,显然会比仅仅提供静态文件的 server 更加大量占用 CPU 资源,因此如果你预料在高流量环境下使用,需要准备相应的服务器负载,并采用缓存策略

服务端渲染(SSR)vs 预渲染(Prerendering)

如果你只是想改善少数营销页面(例如 /, /about, /contact 等)的 SEO,那么你可能需要预渲染,无需使用 web 服务器实时动态编译 HTML,而是使用预渲染方式,在构建时简单地生成针对特定路由的静态 HTML 文件,优点是设置预渲染更简单,并可以将你的前端作为一个完全静态的站点
如果你使用 webpack,你可以使用 prerender-spa-pluginnpm地址) 插件轻松地添加预渲染

服务端渲染(SSR)原理

构建流程:所有的文件拥有一个公共入口 app.js,进入服务端入口 entry-server.js 和客户端入口 entry-client.js ,项目完成后通过使用 webpack 打包生成服务端 server bundle(一个供服务端 SSR 使用的 json 文件)和客户端 client bundle(用于浏览器),当请求页面时,服务端将 vue 组件组装成 HTML 字符串发送到浏览器,混入到客户端访问的 HTML 模板中,完成页面渲染

通过 vuecli 创建 vue 项目

vue create vue-ssr-demo

vue-server-renderer

vue-server-renderer 是 SSR 渲染的核心,提供 createRenderer 方法,这个方法的 renderToString 可以把 app 渲染成字符串。createBundleRenderer 方法可以通过预打包应用程序代码创建 bundleRenderer 实例,来渲染 bundle 和 HTML 模板

安装 vue-server-renderer

npm install vue-server-renderer --save

注意:

  • vue-server-renderer 和 vue 必须匹配版本
  • vue-server-renderer 依赖一些 Node.js 原生模块,因此只能在 Node.js 中使用

避免状态单例

Node.js 服务器是一个长期运行的进程,当我们的代码进入该进程时,它将进行一次取值并留存在内存中,这意味着如果创建一个单例对象,它将在每个传入的请求之间共享,所以我们应该暴露一个可以重复执行的工厂函数,为每个请求创建一个新的根 Vue 实例,如果我们在多个请求之间使用一个共享的实例,很容易导致交叉请求状态污染(同样的规则也适用于 router、store 和 event bus 实例)

创建 路由 router

安装 vue-router

npm install vue-router --save

src 目录下创建 router 文件夹和 index.js
在 components 目录下创建 Home.vue 和 About.vue 页面(根据项目需求自定义创建)

router/index.js:

import Vue from "vue"
import Router from "vue-router"

import Home from "@/components/Home"
import About from "@/components/About"

Vue.use(Router)

//每次用户请求都需要创建一个新的router实例
//创建createRouter工厂函数
export default function createRouter() {
  //创建router实例
  return new Router({
    mode: "history",
    routes: [
      {
        path: "/",
        name: 'home',
        component: Home
      },
      {
        path: "/about",
        name: 'about',
        component: About
      }
    ]
  })
}

修改 App.vue

修改 App.vue 页面,进行页面布局(根据项目需求自定义布局)

App.vue:

<template>
 <div id="app">
  <nav>
   <router-link to="/">首页</router-link>
   <router-link to="/about">关于</router-link>
  </nav>
  <router-view></router-view>
 </div>
</template>

创建 公共入口 app.js

src 目录下创建 公共入口 app.js ,用于创建 vue 实例

app.js:

import Vue from "vue"
import App from "./App.vue"
import createRouter from "./router"

//创建createApp工厂函数
export default function createApp() {
  const router = createRouter()
  //创建vue实例
  const app = new Vue({
    router,
    render: h => h(App),
  })
  return { app, router }
}

创建 服务端入口 entry-server.js

src 目录下创建 服务端入口 entry-server.js ,用于渲染首屏

entry-server.js:

import createApp from "./app"

export default context => {
  return new Promise((resolve, reject) => {
    const { app, router } = createApp()
    //渲染首屏
    router.push(context.url)
    router.onReady(() => {
      resolve(app)
    }, reject)
  })
}

创建 客户端入口 entry-client.js

src 目录下创建 客户端入口 entry-client.js ,用于挂载激活 app

entry-client.js:

import createApp from "./app"

const { app, router } = createApp()
router.onReady(() => {
  //挂载激活app
  app.$mount("#app")
})

创建 页面模板 index.temp.html

public 目录下创建 index.temp.html ,作为渲染 Vue 应用程序时,renderer 生成 HTML 页面包裹容器,来包裹生成的 HTML 标记
<!--vue-ssr-outlet--> 注释将是应用程序 HTML 标记注入的地方

index.temp.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>vue ssr</title>
</head>
<body>
  <!--vue-ssr-outlet-->
</body>
</html>

创建 Node.js 服务器

服务端渲染(SSR)需要使用 Node.js 服务器,这里使用 express 框架搭建
安装 express

npm install express --save

根目录下创建 server.js 文件,用于搭建 Node.js 服务器

server.js:

//nodejs服务器
const express = require("express")
const Vue = require("vue")
const fs = require("fs")

//创建express实例
const app = express()
//创建渲染器
const { createBundleRenderer } = require("vue-server-renderer")
const serverBundle = require("./dist/server/vue-ssr-server-bundle.json")
const clientManifest = require("./dist/client/vue-ssr-client-manifest.json")
const renderer = createBundleRenderer(serverBundle, {
  runInNewContext: false,
  template: fs.readFileSync("./public/index.temp.html", "utf-8"), //页面模板
  clientManifest
})

//中间件处理静态文件请求
app.use(express.static("./dist/client", {index: false}))

//将路由的处理交给vue
app.get("*", async (req, res) => {
  try {
    const context = {
      url: req.url,
      title: ""
    }
    const html = await renderer.renderToString(context)
    res.send(html)
  }catch {
    res.status(500).send("服务器内部错误!")
  }
})

app.listen(9999, () => {
  console.log("服务器渲染成功!")
})

webpack 打包配置

根目录下创建 vue 配置文件 vue.config.js 进行 webpack 配置,该配置会覆盖 vue-cli 中 webpack 的默认配置

vue.config.js:

const VueSSRServerPlugin = require("vue-server-renderer/server-plugin")
const VueSSRClientPlugin = require("vue-server-renderer/client-plugin")

//环境变量,决定入口是客户端还是服务端
const TARGRT_NODE = process.env.WEBPACK_TARGET === "node"
const target = TARGRT_NODE ? "server" : "client"

module.exports = {
  css: {
    extract: false
  },
  outputDir: "./dist/" + target,
  configureWebpack: () => ({
    //将 entry 指向应用程序的 server entry 文件
    entry: `./src/entry-${target}.js`,
    //对 bundle renderer 提供 source map 支持
    devtool: "source-map",
    //这允许 webpack 以 Node 适用方式(Node-appropriate fashion)处理动态导入(dynamic import)
    //并且还会在编译 Vue 组件时,告知 `vue-loader` 输送面向服务器代码(server-oriented code)
    target: TARGRT_NODE ? "node" : "web",
    node: TARGRT_NODE ? undefined : false,
    output: {
      //此处告知 server bundle 使用 Node 风格导出模块(Node-style exports)
      libraryTarget: TARGRT_NODE ? "commonjs2" : undefined
    },
    optimization: { splitChunks: TARGRT_NODE ? false : undefined },
    //将服务器的整个输出构建为单个 JOSN 文件的插件
    //服务端默认文件名为 vue-ssr-server-bundle.json
    plugins: [TARGRT_NODE ? new VueSSRServerPlugin() : new VueSSRClientPlugin()]
  })
}

打包脚本配置

cross-env 插件:运行跨平台设置和使用环境变量的脚本
安装 cross-env 插件

npm install cross-env --save

package.json 文件中定义项目运行打包脚本

package.json:

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

终端执行命令打包项目:

npm run build

打包完成后,终端执行命令启动 Node.js 服务器

npm run server

服务器启动后,浏览器打开 localhost:9999 即可访问 SSR 项目
查看网页源代码发现根元素上添加了一个特殊的属性:data-server-rendered,该属性让客户端 Vue 知道这部分 HTML 是由 Vue 在服务端渲染的,并且应该以激活模式进行挂载

<div id="app" data-server-rendered="true">......</div>

项目目录:

打包后 dist 目录:

到此这篇关于vuecli项目构建SSR服务端渲染的实现的文章就介绍到这了,更多相关vuecli构建SSR服务端渲染内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 通过vue-cli3构建一个SSR应用程序的方法

    1.前沿 1.1.什么是SSR SSR(服务端渲染)顾名思义就是将页面在服务端渲染完成后在客户端直接展示. 1.2.客户端渲染与服务端渲染的区别 传统的SPA模式 即客户端渲染的模式 Vue.js构建的应用程序,默认情况下是有一个html模板页,然后通过webpack打包生成一堆js.css等等资源文件.然后塞到index.html中 用户输入url访问页面 -> 先得到一个html模板页 -> 然后通过异步请求服务端数据 -> 得到服务端的数据 -> 渲染成局部页面 ->

  • vue/vue-cli+express手把教你搭建SSR

    最近简单的研究了一下SSR,对SSR已经有了一个简单的认知,主要应用于单页面应用,Nuxt是SSR很不错的框架.也有过调研,简单的用了一下,感觉还是很不错.但是还是想知道若不依赖于框架又应该如果处理SSR,研究一下做个笔记. 什么是SSR 把Vue组件渲染为服务器端的HTML字符串,将他们直接发送到浏览器,最后将静态标记混合为客户端上完全交互的应用程序. 为什么要使用SSR 更好的SEO,搜索引擎爬虫爬取工具可以直接查看完全渲染的页面 更宽的内容达到时间(time-to-content),当权请

  • 从0到1构建vueSSR项目之node以及vue-cli3的配置

    前言 上一次做了路由的相关配置,原本计划今天要做vuex部分,但是想了想,发现vuex单独的客户端部分穿插解释起来很麻烦,所以今天改做服务端部分. 服务端部分做完,再去做vuex的部分,这样就会很清晰. vue ssr是分两个端,一个是客户端,一个是服务端. 所以要做两个cli3的配置. 那么下面就直接开始做吧. 修改package.json的命令 //package.json :client代表客户端 :server代表服务端 //使用VUE_NODE来作为运行环境是node的标识 //cli

  • vuecli项目构建SSR服务端渲染的实现

    服务端渲染(SSR) 将一个 Vue 组件在服务端渲染成 HTML 字符串并发送到浏览器,最后将这些静态标记"激活"为可交互应用程序的过程就叫服务端渲染(SSR) 服务器渲染的 Vue.js 应用程序也可以被认为是"同构"或"通用",因为应用程序的大部分代码都可以在服务器和客户端上运行 为什么使用 服务端渲染(SSR) 更好的 SEO:传统的 spa 页面数据都是异步加载,搜索引擎爬虫无法抓取,服务端渲染(SSR)使搜索引擎爬虫抓取工具可以直接查

  • 实现ssr服务端渲染的方法步骤

    前言 前段时间寻思做个个人网站,然后就立马行动了.  个人网站如何实现选择什么技术方案,自己可以自由决定.  刚好之前有大致想过服务端渲染,加载速度快,还有seo挺适合个人网站的.  所以就自己造了个轮子用koa+react来实现ssr服务端渲染. 什么是ssr 最初听说有单页面的服务端渲染的时候,就理解为类似传统的服务端路由+模板渲染,只是需要用单页面应用的框架写.后面寻思这样好像有点傻,再一了解,原来只是在首次加载的时候,后端进行当前路径页面的组件渲染和数据请求,组装成html返回给前端,用

  • vue的ssr服务端渲染示例详解

    为什么使用服务器端渲染 (SSR) 更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面. 请注意,截至目前,Google 和 Bing 可以很好对同步 JavaScript 应用程序进行索引.在这里,同步是关键.如果你的应用程序初始展示 loading 菊花图,然后通过 Ajax 获取内容,抓取工具并不会等待异步完成后再行抓取页面内容.也就是说,如果 SEO 对你的站点至关重要,而你的页面又是异步获取内容,则你可能需要服务器端渲染(SSR)解决此问题. 更快的内容到达时间 (ti

  • vue ssr服务端渲染(小白解惑)

    >初学ssr入坑 初学vue服务端渲染疑惑非常多,我们大部分前端都是半路出家,上手都是前后端分离,对服务端并不了解,不说java.php语言了,连node服务都还没搞明白,理解服务端渲染还是有些困难的: 网上有非常多的vue服务渲染的入门案例,但看了很久,很多,还是一头雾水,搞不明白这些文件和关键字的联系和意思: server.js entrt-client.js server-js built-server-bundle.js vue-ssr-server-bundle.json vue-ss

  • VUE基于NUXT的SSR 服务端渲染

    Server Side Rendering(服务端渲染) SSR 目的是为了解决单页面应用的 SEO 的问题,对于一般网站影响不大,但是对于论坛类,内容类网站来说是致命的,搜索引擎无法抓取页面相关内容,也就是用户搜不到此网站的相关信息. 原理 将 html 在服务端渲染,合成完整的 html 文件再输出到浏览器. 适用场景 客户端的网络比较慢 客户端运行在老的或者直接没有 JavaScript 引擎上 NUXT 作用就是在 node.js 上进一步封装,然后省去我们搭建服务端环境的步骤,只需要遵

  • Egg Vue SSR 服务端渲染数据请求与asyncData

    服务端渲染 Node 层直接获取数据 在 Egg 项目如果使用模板引擎规范时通是过 render 方法进行模板渲染,render 的第一个参数模板路径,第二个参数时模板渲染数据. 如如下调用方式: async index(ctx) { // 获取数据,可以是从数据库,后端 Http 接口 等形式 const list = ctx.service.article.getArtilceList(); // 对模板进行渲染,这里的 index.js 是 vue 文件通过 Webpack 构建的 JSB

  • 详解React项目的服务端渲染改造(koa2+webpack3.11)

    因为对网页SEO的需要,要把之前的React项目改造为服务端渲染,经过一番调查和研究,查阅了大量互联网资料.成功踩坑. 选型思路:实现服务端渲染,想用React最新的版本,并且不对现有的写法做大的改动,如果一开始就打算服务端渲染,建议直接用NEXT框架来写 项目地址:https://github.com/wlx200510/react_koa_ssr 脚手架选型:webpack3.11.0 + react Router4 + Redux + koa2 + React16 + Node8.x 主要

  • Vue服务端渲染实践之Web应用首屏耗时最优化方案

    随着各大前端框架的诞生和演变,SPA开始流行,单页面应用的优势在于可以不重新加载整个页面的情况下,通过ajax和服务器通信,实现整个Web应用拒不更新,带来了极致的用户体验.然而,对于需要SEO.追求极致的首屏性能的应用,前端渲染的SPA是糟糕的.好在Vue 2.0后是支持服务端渲染的,零零散散花费了两三周事件,通过改造现有项目,基本完成了在现有项目中实践了Vue服务端渲染. 关于Vue服务端渲染的原理.搭建,官方文档已经讲的比较详细了,因此,本文不是抄袭文档,而是文档的补充.特别是对于如何与现

  • vue ssr+koa2构建服务端渲染的示例代码

    之前做了活动投放页面在百度.360等渠道投放,采用 koa2 + 模版引擎的方式.发现几个问题 相较于框架开发页面效率较低,维护性差 兼容性问题,在页面中添加埋点后发现有些用户的数据拿不到,排查后发现通过各个渠道过来的用户的设备中仍然包含大量低版本的浏览器. 服务端渲染 服务端渲染和单页面渲染区别 查看下面两张图,可以看到如果是服务端渲染,那么在浏览器中拿到的直接是完整的 html 结构.而单页面是一些 script 标签引入的js文件,最终将虚拟dom去挂在到 #app 容器上. @vue/c

  • 详解Vue基于 Nuxt.js 实现服务端渲染(SSR)

    直接使用 Vue 构建前端单页面应用,页面源码时只有简单的几行 html,这并不利于网站的 SEO,这时候就需要服务端渲染 2016 年 10 月 25 日,zeit.co 背后的团队对外发布了一个 React 的服务端渲染应用框架 Next.js 几小时后,一个基于 Vue.js 的服务端渲染应用框架应运而生,与 Next.js 异曲同工,这就是Nuxt.js 一.快速模板 在已经安装了 vue-cli 的前提下,可以快速创建一个 nuxt 的项目模板 vue init nuxt-commun

随机推荐