經過前面兩篇文章,寫了一個簡單的支持 vue 同構的 webpack 配置,可是尚未 dev server,不能熱更新和實時編譯,用於開發仍是很是的麻煩。css
Vue 官方的 webpack 腳手架只是針對客戶端的,功能強大,配置齊全。因此在這個官方腳手架的基礎上改了一個支持 #SSR# 的版本,在改的過程當中參考了 GitHub - vuejs/vue-hackernews-2.0: HackerNews clone built with Vue 2.0, vue-router & vuex, with server-side rendering。html
改事後的源碼在 Github 上,使用方式:vue init wheato/vue-ssr-boilerplate project-name
。接下來簡單的說說這個修改的過程。vue
這一部分主要是增長兩個入口 ,修改內容和以前文章還有官方文檔同樣。若是有用到 vue-router 還要修改 route.js,具體修改能夠看官方文檔。有了 vue-router 咱們就能夠在組件裏面定義靜態方法,服務端調用注入數據。webpack
// Foo.vue
<template>
<div>
<h2>Foo</h2>
</div>
</template>
<script>
export default {
preFetch(data) {
console.log(data)
},
data () {
return {}
}
}
</script>複製代碼
// entry-server.js
import { createApp } from './app.js'
export default context => {
return new Promise((resolve, reject) => {
const { app, router } = createApp()
router.push('/foo')
router.onReady(() => {
const matchedComponents = router.getMatchedComponents()
matchedComponents.forEach(p => {
p.preFetch('數據')
})
resolve(app)
}, reject)
})
}複製代碼
server.js 基本上就是從 vue-hackernews-2.0 種複製過來的,作了一些刪減,使用 express,也可使用 Koa。git
webpack.prod.conf.js 的修改點:github
process.env.VUE_ENV = ‘client’
;增長 webpack.server.conf.js:web
process.env.VUE_ENV = ‘server’
。webpack.dev.conf.js 中增長 vue-server-renderer client 端插件,修改入口爲 entry-client.js。vue-router
dev-server.js 這部分修改挺大的, 其中 client 的配置使用 webpack.dev.conf.js。vuex
Client 部分沒有太多的改動,必需要使用的兩個插件 webpack-dev-middleware 和 webpack-hot-middleware。增長了 clientCompiler done 事件的回調,把編譯好的 client-bundle 文件保存進 clientManifest 中,頁面刷新的時候服務器渲染就能同步到以前修改過的內容。express
// dev middleware
var clientCompiler = webpack(clientWebpackConfig)
var devMiddleware = require('webpack-dev-middleware')(clientCompiler, {
publicPath: clientWebpackConfig.output.publicPath,
noInfo: true
})
app.use(devMiddleware)
clientCompiler.plugin('done', stats => {
stats = stats.toJson()
stats.errors.forEach(err => console.error(err))
stats.warnings.forEach(err => console.warn(err))
if (stats.errors.length) return
clientManifest = JSON.parse(readFile(
devMiddleware.fileSystem,
'vue-ssr-client-manifest.json'
))
update()
})
// hot middleware
var hotMiddleware = require('webpack-hot-middleware')(clientCompiler, { heartbeat: 5000 })
app.use(hotMiddleware)複製代碼
Server 部分中,devMiddleware 的代碼更新不到服務端,因此要添加 watch 事件,實時編譯 server-bundle。
// watch and update server renderer
var serverCompiler = webpack(serverWebpackConfig)
var mfs = new MFS()
serverCompiler.outputFileSystem = mfs
serverCompiler.watch({}, (err, stats) => {
if (err) throw err
stats = stats.toJson()
if (stats.errors.length) return
// read bundle generated by vue-ssr-webpack-plugin
bundle = JSON.parse(readFile(mfs, 'vue-ssr-server-bundle.json'))
update()
})
// read template from disk and watch
template = fs.readFileSync(templatePath, 'utf-8')
chokidar.watch(templatePath).on('change', () => {
template = fs.readFileSync(templatePath, 'utf-8')
console.log('index.html template updated.')
hotMiddleware.publish({ action: 'reload' })
})複製代碼
修改點比較簡單,在 client 端編譯完後,再增長編譯 server 端就能夠。最後修改一下 package.json 的命令。
npm run dev
npm run build
npm run server // 啓動服務器複製代碼
更多的代碼可使用腳手架模板建立一個空項目跑一下看看。