Commit af46a713 authored by Evan You's avatar Evan You

tweak server

parent f2e39ee1
const path = require('path')
const webpack = require('webpack')
const MFS = require('memory-fs')
const clientConfig = require('./webpack.client.config')
const serverConfig = require('./webpack.server.config')
module.exports = function setupDevServer (app, onUpdate) {
// setup on the fly compilation + hot-reload
clientConfig.entry.app = ['webpack-hot-middleware/client', clientConfig.entry.app]
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()
const outputPath = path.join(serverConfig.output.path, serverConfig.output.filename)
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))
onUpdate(mfs.readFileSync(outputPath, 'utf-8'))
})
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>vue-hackernews-2.0</title>
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
{{ STYLE }}
</head>
<body>
{{ APP }}
<script src="/dist/client-vendor-bundle.js"></script>
<script src="/dist/client-bundle.js"></script>
</body>
</html>
...@@ -7,54 +7,35 @@ const favicon = require('serve-favicon') ...@@ -7,54 +7,35 @@ const favicon = require('serve-favicon')
const serialize = require('serialize-javascript') const serialize = require('serialize-javascript')
const createBundleRenderer = require('vue-server-renderer').createBundleRenderer 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'))
}
const app = express() const app = express()
if (process.env.NODE_ENV !== 'production') { // parse index.html template
const webpack = require('webpack') const html = (() => {
const clientConfig = require('./build/webpack.client.config') const template = fs.readFileSync(path.resolve(__dirname, './index.html'), 'utf-8')
const i = template.indexOf('{{ APP }}')
clientConfig.entry.app = ['webpack-hot-middleware/client', clientConfig.entry.app] const style = process.env.NODE_ENV === 'production'
clientConfig.plugins.push( ? '<link rel="stylesheet" href="/dist/styles.css">'
new webpack.HotModuleReplacementPlugin(), : ''
new webpack.NoErrorsPlugin() return {
) head: template.slice(0, i).replace('{{ STYLE }}', style),
tail: template.slice(i + '{{ APP }}'.length)
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 // setup the server renderer, depending on dev/prod environment
const MFS = require('memory-fs') let renderer
const serverConfig = require('./build/webpack.server.config') if (process.env.NODE_ENV !== 'production') {
const serverCompiler = webpack(serverConfig) require('./build/setup-dev-server')(app, bundle => {
const mfs = new MFS() renderer = createBundleRenderer(bundle)
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 { } else {
app.use('/dist', express.static(path.resolve(__dirname, 'dist')))
// create server renderer from real fs // create server renderer from real fs
renderer = createRenderer(fs) const bundlePath = path.resolve(__dirname, './dist/server-bundle.js')
renderer = createBundleRenderer(fs.readFileSync(bundlePath, 'utf-8'))
} }
app.use(favicon(path.resolve(__dirname, 'src/assets/logo.png'))) app.use('/dist', express.static(path.resolve(__dirname, './dist')))
app.use(favicon(path.resolve(__dirname, './src/assets/logo.png')))
app.get('*', (req, res) => { app.get('*', (req, res) => {
var s = Date.now() var s = Date.now()
...@@ -62,25 +43,17 @@ app.get('*', (req, res) => { ...@@ -62,25 +43,17 @@ app.get('*', (req, res) => {
const renderStream = renderer.renderToStream(context) const renderStream = renderer.renderToStream(context)
let firstChunk = true let firstChunk = true
res.write(`<!DOCTYPE html> res.write(html.head)
<html lang="en">
<head>
<meta charset="utf-8">
<title>vue-hackernews-2.0</title>
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
${process.env.NODE_ENV === 'production'
? `<link rel="stylesheet" href="/dist/styles.css">`
: ``}
</head>
<body>`)
renderStream.on('data', chunk => { renderStream.on('data', chunk => {
if (firstChunk) { if (firstChunk) {
// send down initial store state // embed initial store state
if (context.initialState) { if (context.initialState) {
res.write(`<script>window.__INITIAL_STATE__=${ res.write(
`<script>window.__INITIAL_STATE__=${
serialize(context.initialState, { isJSON: true }) serialize(context.initialState, { isJSON: true })
}</script>`) }</script>`
)
} }
firstChunk = false firstChunk = false
} }
...@@ -88,11 +61,7 @@ app.get('*', (req, res) => { ...@@ -88,11 +61,7 @@ app.get('*', (req, res) => {
}) })
renderStream.on('end', () => { renderStream.on('end', () => {
res.end(` res.end(html.tail)
<script src="/dist/client-vendor-bundle.js"></script>
<script src="/dist/client-bundle.js"></script>
</body></html>`
)
console.log(`whole request: ${Date.now() - s}ms`) console.log(`whole request: ${Date.now() - s}ms`)
}) })
......
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