還在為部署Vue SSR煩惱?Koa-vuessr-middlware 瞭解一下
最近在寫一個新應用時,想用Koa 結合 Vue SSR,同時寫Api 介面和頁面,於是開始上手寫,結果發現需要寫的東西很多,參考的大多數例子都用的是十分類似的程式碼(好像大多都是基於尤大大的 ofollow,noindex">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
則為服務端入口js -
output
如果你想使用內建預設webpack 配置,則需要配置一個path
和outputPath
,可以參考 webpack 的output 配置 -
webpackConfig
如果你想用自定義的webpack 配置,則需要配置以下兩項:client server
注:可以在專案地址中參考相應的配置檔案進行編寫
基本用法如下:
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' // 渲染預設模板地址,如果不提供則會使用內建的預設模板 })); 複製程式碼
- 生產環境
先執行以下命令生成生產程式碼
buildssr 複製程式碼
然後使用以下程式碼
router.get('*', ssr(app, { title: '網頁預設標題', isProd: true, // 此時將直接讀取生產程式碼, templatePath: './index.template.html' // 渲染預設模板地址,如果不提供則會使用內建的預設模板 })); 複製程式碼
檔案目錄建議如下例子:
├── srcapp directory │├── router/route directory │├── views/views directory │├── components/compoennts directory │├── app.jsjs file to export a createApp function │├── App.vueroot Vue │├── entry-server.jsserver side entry point │└── entry-client.jsclient side entry point ├── index.jsserver entry point ├── .ssrconfigSSR 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) }) } 複製程式碼