Vue-SSR-Koa2-Scaffold/config/ssr.js
2018-11-11 23:47:41 +08:00

97 lines
2.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const fs = require('fs')
const path = require('path')
const chalk = require('chalk')
const LRU = require('lru-cache')
const {
createBundleRenderer
} = require('vue-server-renderer')
const isProd = process.env.NODE_ENV === 'production'
const setUpDevServer = require('./setup-dev-server')
const HtmlMinifier = require('html-minifier').minify
const pathResolve = file => path.resolve(__dirname, file)
module.exports = app => {
return new Promise((resolve, reject) => {
const createRenderer = (bundle, options) => {
return createBundleRenderer(bundle, Object.assign(options, {
cache: LRU({
max: 1000,
maxAge: 1000 * 60 * 15
}),
basedir: pathResolve('../dist/web'),
runInNewContext: false
}))
}
let renderer = null
if (isProd) {
// prod mode
const template = HtmlMinifier(fs.readFileSync(pathResolve('../public/index.html'), 'utf-8'), {
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: false
})
const bundle = require(pathResolve('../dist/web/vue-ssr-server-bundle.json'))
const clientManifest = require(pathResolve('../dist/web/vue-ssr-client-manifest.json'))
renderer = createRenderer(bundle, {
template,
clientManifest
})
const API = require('../dist/api/api').default
const server = API(app)
resolve(server)
} else {
// dev mode
setUpDevServer(app, (bundle, options, apiMain, apiOutDir) => {
try {
const API = eval(apiMain).default // eslint-disable-line
const server = API(app)
renderer = createRenderer(bundle, options)
resolve(server)
} catch (e) {
console.log(chalk.red('\nServer error'), e)
}
})
}
app.use(async (ctx, next) => {
if (!renderer) {
ctx.type = 'html'
ctx.body = 'waiting for compilation... refresh in a moment.'
next()
return
}
let status = 200
let html = null
const context = {
url: ctx.url,
title: 'OK'
}
if (/^\/api/.test(ctx.url)) { // 如果请求以/api开头则进入api部分进行处理。
next()
return
}
try {
status = 200
html = await renderer.renderToString(context)
} catch (e) {
if (e.message === '404') {
status = 404
html = '404 | Not Found'
} else {
status = 500
console.log(chalk.red('\nError: '), e.message)
html = '500 | Internal Server Error'
}
}
ctx.type = 'html'
ctx.status = status || ctx.status
ctx.body = html
next()
})
})
}