koa-vuessr-middleware v1.0.3
Koa-VueSSR
基于Koa 2.x 的Vue SSR 中间件(Vue SSR middleware for koa 2.x)
installation
npm install koa-vuessr-middleware用法
如果你需要运行在生产环境中,你需要先在package.json 文件中配置scripts字段,
"scripts": {
"build": "vuessr"
}然后执行 npm run build 命令生成生产代码
const koa = require('koa');
const app = new koa();
const koaRouter = require('koa-router');
const ssr = require('koa-vuessrr-middleware');
router.get('/otherroute', othermiddleware);
router.get('*', ssr(app, opts));
app.use(router.routes());
app.listen(8080);appkoa 的app 实例opts配置选项Options
title页面默认标题,默认为空;isProd是否为生产模式,默认为false,如果设置为true,你需要先生成生产代码,为false时,该中间件会使用webpack-hot-middleware&webpack-dev-middleware以实现热更新功能;templatePath默认网页模板,默认为空,即使用内置的网页模板
你需要在项目根目录下有一个 .ssrconfig 作为配置文件,以下是配置例子
.ssrconfig
{
"template": "./src/index.template.html",
"ouput": {
"path": "./dist",
"publicPath": "/dist/"
},
"errorPage": {
"500": "./500.html",
"404": "./404.html"
},
"entry": {
"client": "./src/entry-client.js",
"server": "./src/entry-server.js"
},
"webpackConfig": {
"client": "./build/webpack.client.conf.js",
"server": "./build/webpack.server.conf.js"
}
}template默认网页模板,默认为空,即使用内置的网页模板entry当你想要使用内置webpack 配置文件的时候为必要选项。 webpack的入口js,client是客户端入口文件,server为服务端入口文件;errorPage当服务端出现500或404错误时使用的页面,可配置500 or 404字段,不配置时会显示报错信息output如果你想使用内置webpack 配置文件的时候,你需要声明输出目录选项,path为输出的文件夹目录,publicPath是生成到模板中时的资源路径, 具体可以参考 webpack output 配置webpackConfig如果你倾向于使用你自己的webpack 配置文件,你需要配置下列选项:client客户端配置webpack 配置server服务端配置webpack 配置
实际使用可以参考 Demo
目录结构示例
├── src app directory
│ ├── router/ route directory
│ ├── views/ views directory
│ ├── components/ compoennts directory
│ ├── app.js js file to export a createApp function
│ ├── App.vue root Vue
│ ├── entry-server.js server side entry point
│ └── entry-client.js client side entry point
├── index.js server entry point
├── .ssrconfig SSR configuration file
├── ... app.js 例子
import Vue from 'vue'
import App from './App.vue'
import { createRouter } from './router'
import titleMixin from './util/title'
Vue.mixin(titleMixin)
export function createApp () {
const router = createRouter()
const app = new Vue({
router,
render: h => h(App)
})
return { app, router, }
}entry-client.js 例子
import Vue from 'vue'
import 'es6-promise/auto'
import { createApp } from './app'
const { app, router } = createApp()
router.onReady(() => {
app.$mount('#app')
})entry-server.js 例子
import { createApp } from './app';
export default context => {
return new Promise((resolve, reject) => {
const { app, router } = createApp()
const { url } = context
const { fullPath } = router.resolve(url).route
if (fullPath !== url) {
return reject({ url: fullPath })
}
router.push(url)
router.onReady(() => {
const matchedComponents = router.getMatchedComponents()
if (!matchedComponents.length) {
return reject({ code: 404 })
}
Promise.all(matchedComponents.map(({ asyncData }) => asyncData)).then(() => {
resolve(app)
}).catch(reject)
}, reject)
})
}注意
如果你想要使用自己的webpack 配置文件,你需要使用Code-Splitting 功能,你需要在你的.babelrc or babel-loader中配置 syntax-dynamic-import,否则会报错
"plugins": [
"syntax-dynamic-import"
]usage
if you want to run in production mode, you should run vuessr command first
const koa = require('koa');
const app = new koa();
const koaRouter = require('koa-router');
const ssr = require('koa-vuessrr-middleware');
router.get('/otherroute', othermiddleware);
router.get('*', ssr(app, opts));
app.use(router.routes());
app.listen(8080);appkoa appoptsoptions objectOptions
titledefault title for html, default to empty stringisProdis Production Mode, default to false, if true, you need to runvuessrcommand to build distrubution file first. if false, the middleware will usewebpack-hot-middleware&webpack-dev-middlewareto setup a hot reload server;templatePathhtml template path, default to empty string, then it will use the built in template file
You also need to have a .ssrconfig file in your root directory, here is an example for .ssrconfig file;
.ssrconfig
{
"template": "./src/index.template.html",
"ouput": {
"path": "./dist",
"publicPath": "/dist/"
},
"entry": {
"client": "./src/entry-client.js",
"server": "./src/entry-server.js"
},
"webpackConfig": {
"client": "./build/webpack.client.conf.js",
"server": "./build/webpack.server.conf.js"
}
}templatehtml template path, default to empty string, then it will use the built in template fileentryrequired if you want to use the built in webpack config file. This is the entrypoint js for webpack,clientis the client side entrypoint,serveris the server side entrypoint;outputif you want to use the built in webpack config file, you need to specify output option withpathfor distribution file path &publicPathfor every URL created by the runtime or loaders, check webpack output configurationwebpackConfigif you prefer to use your own webpack config, you need to specify this option, you need two configuration file:clientfor client side configuration file pathserverfor server side configuration file path;
See Demo for more pratical usage
Directory structure example:
├── src app directory
│ ├── router/ route directory
│ ├── views/ views directory
│ ├── components/ compoennts directory
│ ├── app.js js file to export a createApp function
│ ├── App.vue root Vue
│ ├── entry-server.js server side entry point
│ └── entry-client.js client side entry point
├── index.js server entry point
├── .ssrconfig SSR configuration file
├── ... app.js example
import Vue from 'vue'
import App from './App.vue'
import { createRouter } from './router'
import titleMixin from './util/title'
Vue.mixin(titleMixin)
export function createApp () {
const router = createRouter()
const app = new Vue({
router,
render: h => h(App)
})
return { app, router, }
}entry-client.js example
import Vue from 'vue'
import 'es6-promise/auto'
import { createApp } from './app'
const { app, router } = createApp()
router.onReady(() => {
app.$mount('#app')
})entry-server.js example
import { createApp } from './app';
export default context => {
return new Promise((resolve, reject) => {
const { app, router } = createApp()
const { url } = context
const { fullPath } = router.resolve(url).route
if (fullPath !== url) {
return reject({ url: fullPath })
}
router.push(url)
router.onReady(() => {
const matchedComponents = router.getMatchedComponents()
if (!matchedComponents.length) {
return reject({ code: 404 })
}
Promise.all(matchedComponents.map(({ asyncData }) => asyncData)).then(() => {
resolve(app)
}).catch(reject)
}, reject)
})
}Notice
if you want to use your own webpack configuration & you want to use Code-Splitting, you need to use syntax-dynamic-import plugin in your .babelrc or babel-loader options;
"plugins": [
"syntax-dynamic-import"
]ChangeLog
v 1.0.3
- 新增自定义错误页面
- 将500 错误设置默认显示为报错信息