最近在寫一個新應用時,想用Koa 結合 Vue SSR,同時寫Api 接口和頁面,因而開始上手寫,結果發現須要寫的東西不少,參考的大多數例子都用的是十分相似的代碼(好像大多都是基於尤大大的hackernews ),因而索性花了一個晚上把代碼封裝成一個Koa 的中間件,讓後來者少造個輪子;javascript
各位看官,走過路過,給個star 鼓勵一下吧,謝謝!項目地址html
若是如下的文檔不夠清晰,能夠參考我寫的Demo 進行參考vue
npm install koa-vuessr-middleware
文檔java
首先須要在項目根目錄下添加一個.ssrconfig
文件,內容以下:webpack
{ "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" } }
說明:git
template
默認網頁模板,默認爲空,即便用內置的網頁模板entry
若是你想使用內置默認webpack 配置,則必須配置此項,包括一個client
和 server
,client
爲客戶端入口js, server
則爲服務端入口jsoutput
若是你想使用內置默認webpack 配置,則須要配置一個path
和outputPath
,能夠參考 webpack 的output 配置 webpackConfig
若是你想用自定義的webpack 配置,則須要配置如下兩項:es6
client
客戶端版本的webpack 配置文件server
服務端版本的webpack 配置文件注:能夠在項目地址中參考相應的配置文件進行編寫github
基本用法以下:web
const koa = require('koa'); const app = new koa(); const koaRouter = require('koa-router'); const ssr = require('koa-vuessrr-middleware'); router.get('/otherroute', otherloaders); router.get('*', ssr(app, opts)); app.use(router.routes()); app.listen(8080);
router.get('*', ssr(app, { title: '網頁默認標題', isProd: false, // 此時將啓用熱更新功能,此爲默認選項, }));
先執行如下命令生成生產代碼npm
buildssr
而後使用如下代碼
router.get('*', ssr(app, { title: '網頁默認標題', isProd: true, // 此時將直接讀取生產代碼, }));
文件目錄建議以下例子:
├── 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) }) }