前言
最近在寫一個新應用時,想用Koa 結合 Vue SSR,同時寫Api 介面和頁面,於是開始上手寫,結果發現需要寫的東西很多,參考的大多數例子都用的是十分類似的程式碼(好像大多都是基於尤大大的hackernews ),於是索性花了一個晚上把程式碼封裝成一個Koa 的中介軟體,讓後來者少造個輪子;
各位看官,走過路過,給個star 鼓勵一下吧,謝謝!專案地址
示例
如果以下的文件不夠清晰,可以參考我寫的Demo 進行參考
安裝
npm install koa-vuessr-middleware
複製程式碼
使用
首先需要在專案根目錄下新增一個.ssrconfig
檔案,內容如下:
{
"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"
}
}
複製程式碼
說明:
entry
如果你想使用內建預設webpack 配置,則必須配置此項,包括一個client
和server
,client
為客戶端入口js,server
則為服務端入口jsoutput
如果你想使用內建預設webpack 配置,則需要配置一個path
和outputPath
,可以參考 webpack 的output 配置webpackConfig
如果你想用自定義的webpack 配置,則需要配置以下兩項:client
客戶端版本的webpack 配置檔案server
服務端版本的webpack 配置檔案
注:可以在專案地址中參考相應的配置檔案進行編寫
基本用法如下:
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, // 此時將啟用熱更新功能,此為預設選項,
templatePath: './index.template.html' // 渲染預設模板地址,如果不提供則會使用內建的預設模板
}));
複製程式碼
- 生產環境
如果你需要執行在生產環境中,你需要先在package.json
檔案中配置scripts
欄位,
"scripts": {
"build": "vuessr"
}
複製程式碼
然後執行 npm run build
命令生成生產程式碼
然後使用以下程式碼
router.get('*', ssr(app, {
title: '網頁預設標題',
isProd: true, // 此時將直接讀取生產程式碼,
templatePath: './index.template.html' // 渲染預設模板地址,如果不提供則會使用內建的預設模板
}));
複製程式碼
檔案目錄建議如下例子:
├── 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)
})
}
複製程式碼
結語
如果該專案對你有幫助,再次這裡求大家戳專案地址 點個star,,謝謝?