Commit 5b456688 authored by Evan You's avatar Evan You

setup SSR with hot-reload

parents
{
"presets": ["es2015-webpack"]
}
.DS_Store
node_modules/
dist/
npm-debug.log
# vue-hackernews-2.0
> A Vue.js project
## Build Setup
``` bash
# install dependencies
npm install
# serve with hot reload at localhost:8080
npm run dev
# build for production with minification
npm run build
```
For detailed explanation on how things work, consult the [docs for vue-loader](http://vuejs.github.io/vue-loader).
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>vue-hackernews-2.0</title>
</head>
<body>
<div id="app"></div>
<script src="dist/build.js"></script>
</body>
</html>
{
"name": "vue-hackernews-2.0",
"description": "A Vue.js project",
"author": "Evan You <yyx990803@gmail.com>",
"private": true,
"scripts": {
"start": "node server",
"build": "npm run build:client && npm run build:server",
"build:client": "NODE_ENV=production webpack --config webpack.client.config.js --progress --hide-modules",
"build:server": "NODE_ENV=production webpack --config webpack.server.config.js --progress --hide-modules"
},
"dependencies": {
"express": "^4.14.0",
"serialize-javascript": "^1.3.0",
"serve-favicon": "^2.3.0",
"vue": "^2.0.0-beta.6",
"vue-router": "^2.0.0-beta.4",
"vue-server-renderer": "^2.0.0-beta.6",
"vuex": "^2.0.0-rc.3"
},
"devDependencies": {
"babel-core": "^6.0.0",
"babel-loader": "^6.0.0",
"babel-preset-es2015-webpack": "^6.0.0",
"css-loader": "^0.23.1",
"file-loader": "^0.8.4",
"vue-loader": "^9.2.2",
"webpack": "^2.1.0-beta.20",
"webpack-dev-middleware": "^1.6.1",
"webpack-hot-middleware": "^2.12.2",
"webpack-merge": "^0.14.1"
}
}
process.env.VUE_ENV = 'server'
const fs = require('fs')
const path = require('path')
const express = require('express')
const favicon = require('serve-favicon')
const serialize = require('serialize-javascript')
const createBundleRenderer = require('vue-server-renderer').createBundleRenderer
let renderer
function createRenderer (fs) {
const bundlePath = path.resolve(__dirname, 'dist/server-bundle.js')
return createBundleRenderer(fs.readFileSync(bundlePath, 'utf-8'), {
cache: require('lru-cache')({ max: 1000 })
})
}
const app = express()
if (process.env.NODE_ENV !== 'production') {
const webpack = require('webpack')
const MFS = require('memory-fs')
const clientConfig = require('./webpack.client.config')
const serverConfig = require('./webpack.server.config')
clientConfig.entry = ['webpack-hot-middleware/client', clientConfig.entry]
clientConfig.plugins.push(
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
)
const clientCompiler = webpack(clientConfig)
app.use(require('webpack-dev-middleware')(clientCompiler, {
publicPath: clientConfig.output.publicPath,
stats: {
colors: true,
chunks: false
}
}))
app.use(require('webpack-hot-middleware')(clientCompiler))
// watch and update server renderer
const serverCompiler = webpack(serverConfig)
const mfs = new MFS()
serverCompiler.outputFileSystem = mfs
serverCompiler.watch({}, (err, stats) => {
if (err) throw err
stats = stats.toJson()
stats.errors.forEach(err => console.error(err))
stats.warnings.forEach(err => console.warn(err))
renderer = createRenderer(mfs)
})
} else {
app.use(express.static(path.resolve(__dirname, 'dist')))
renderer = createRenderer(fs)
}
app.use(favicon(path.resolve(__dirname, 'src/assets/logo.png')))
app.get('*', (req, res) => {
const context = { url: req.url }
const renderStream = renderer.renderToStream(context)
let firstChunk = true
res.write('<!DOCTYPE html><body>')
renderStream.on('data', chunk => {
if (firstChunk) {
// send down initial store state
if (context.initialState) {
res.write(`<script>window.__INITIAL_STATE__=${
serialize(context.initialState, { isJSON: true })
}</script>`)
}
firstChunk = false
}
res.write(chunk)
})
renderStream.on('end', () => {
res.end(`<script src="/dist/client-bundle.js"></script></body>`)
})
renderStream.on('error', err => {
throw err
})
})
app.listen(3000, () => {
console.log('ready at localhost:3000')
})
<template>
<div id="app">
<img src="./assets/logo.png">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
data () {
return {
msg: 'Hello Vue 2.0!'
}
}
}
</script>
<style>
body {
font-family: Helvetica, sans-serif;
}
</style>
import Vue from 'vue'
import App from './App.vue'
export const app = new Vue({
render: h => h(App)
})
import { app } from './app'
app.$mount('#app')
import { app } from './app'
export default app
const path = require('path')
const webpack = require('webpack')
const isProd = process.env.NODE_ENV === 'production'
module.exports = {
devtool: '#eval-source-map',
entry: './src/client-entry.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'client-bundle.js'
},
resolveLoader: {
root: path.join(__dirname, 'node_modules'),
},
module: {
loaders: [
{
test: /\.vue$/,
loader: 'vue'
},
{
test: /\.js$/,
loader: 'babel',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file',
query: {
name: '[name].[ext]?[hash]'
}
}
]
},
devServer: {
historyApiFallback: true,
noInfo: true
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development')
}
})
]
}
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
module.exports.plugins = module.exports.plugins.concat([
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
])
}
const webpack = require('webpack')
const merge = require('webpack-merge')
const webpackConfig = require('./webpack.client.config')
module.exports = merge(webpackConfig, {
target: 'node',
entry: './src/server-entry.js',
output: {
filename: 'server-bundle.js',
libraryTarget: 'commonjs2'
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"',
VUE_ENV: '"server"'
}
})
]
})
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment