基于Koa 2.x 的Vue SSR 中间件(Vue SSR middleware for koa 2.x
)
�
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);
-
app
koa 的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"
]
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);
-
app
koa app -
opts
options objectOptions
title
default title for html, default to empty stringisProd
is Production Mode, default to false, if true, you need to runvuessr
command to build distrubution file first. if false, the middleware will usewebpack-hot-middleware
&webpack-dev-middleware
to setup a hot reload server;templatePath
html 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"
}
}
template
html template path, default to empty string, then it will use the built in template fileentry
required if you want to use the built in webpack config file. This is the entrypoint js for webpack,client
is the client side entrypoint,server
is the server side entrypoint;output
if you want to use the built in webpack config file, you need to specify output option withpath
for distribution file path &publicPath
for every URL created by the runtime or loaders, check webpack output configurationwebpackConfig
if you prefer to use your own webpack config, you need to specify this option, you need two configuration file:client
for client side configuration file pathserver
for 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)
})
}
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"
]
- 新增自定义错误页面
- 将500 错误设置默认显示为报错信息