在 Express 应用中接入 Vue 2.0 服务端渲染
发布于 8 年前 作者 hilongjw 19794 次浏览 来自 分享

写在前面

Vue 2.0 发布快有两周了,最近两天终于有空做了服务端渲染和同构的一些尝试,并实现了一个对 Vue Server Renderer 的封装,可以用更精简的代码来实现在目前的 Node.js 应用中引入 Vue 服务端渲染。

Vue 的服务端渲染支持流式输出,可以做组件级的缓存,这使得它的渲染速度也是非常快速。通过搭配新版的 vue-routervuex( Vue 全家桶 大雾 ),可以实现一个既可以满足SEO需求 ,也如SPA一样交互体验流畅的前后端同构应用。

vue-hackernews-2.0 是 Vue 2.0 的同构示例项目,使用 firebase 作为数据层,实现了完全实时的 hackernews 信息流,同时还能被搜索引擎当做静态内容抓取。

vue-ssr

Use Vue 2.0 server-side rendering with Express 项目地址: vue-ssr

先上demo

还没有做优化,只是基础使用了 lru 做了组件的缓存,服务器平均渲染时间在 40ms 左右。 http://ssr.bood.in/

安装

npm i vue-ssr --save

用法

const express = require('express')
const router = express.Router()

const vueRender = require('vue-ssr')

// webpack server-side bundle config
const serverConfig = require('path to webpack.server.js')

// create a project renderer
const indexRenderer = vueRender({
    projectName: 'index', 
    rendererOptions: {
        cache: require('lru-cache')({
            max: 1000,
            maxAge: 1000 * 60 * 15
        })
    }, 
    webpackServer: serverConfig
})

// handler
// 这里的静态模板只做演示,可以查看文末的实例实例代码
function indexView (req, res) => {
    indexRenderer(req, res, `
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <title>Cov-X</title>
        {{ STYLE }}
      </head>
      <body>
        {{ APP }}
        <script src="/dist/client-bundle.js"></script>
      </body>
    </html>
    `)
}

router.get('/', indexView)
router.get('/home', indexView)
router.get('/article', indexView)
router.get('/tag', indexView)

API

projectName

project name of webpack entries that you want to server side rendering

// webpack config

...

entry: {
    index: ['../path to app client entry'],
    dashboard: ['../path to dashboard project client entry']
},

...
const indexRenderer = vueRender({
    projectName: 'index',
    webpackServer: serverConfig
})

const dashRenderer = vueRender({
    projectName: 'dashboard',
    webpackServer: serverConfig
})

rendererOptions

rendererOptions 即 Vue server renderer 的配置项

指令( directives )

声明一些自定义指令的服务端实现:

const indexRenderer = vueRender('index', {
  directives: {
    example (vnode, directiveMeta) {
    // transform vnode based on directive binding metadata
    }
  }
}, serverConfig)

缓存( cache )

const indexRenderer = vueRender('index', {
    cache: require('lru-cache')({
        max: 1000,
        maxAge: 1000 * 60 * 15
    })
}, serverConfig)

更多信息可以参考:Why Use bundleRenderer?

webpack 服务端打包配置( webpackServer )

推荐参考webpack.server.js

将 webpack 服务端打包配置引入到 webpackServer 就完成了。

const serverConfig = require('path to webpack.server.js')

const indexRenderer = vueRender({
    projectName: 'index', 
    webpackServer: serverConfig
})

示例代码

vue-ssr-hmr-template是一个使用了 vue-ssr 的项目脚手架,既可以使用前后端同构,也可以使用普通的spa模式(node 渲染静态页)。

  • Vue 2.0
  • Webpack 2.1.0
  • HotModuleReplacement
  • Server Side Render
  • Express
5 回复

手动支持佳文,多分享。

谢谢 @yunkou ,哈哈 第一次发

棒棒哒~能参考express里模板引擎的做法嘛?这样看起来还是有点不太习惯

@i5ting 可以的。文档里是一个简单的演示,在实际项目中是这样用的:

function index (req, res) {
    const template = render('index', { title: 'cov-x', bundle: 'index' })
    indexRenderer(req, res, template)
}

render 是简单封装了一个pug

function render (view, data) {
    return pug.compileFile(path.join(__dirname, '../views/' + view + '.pug'), {
        cache: true
    })(data)
}
回到顶部