improvements

This commit is contained in:
Pooya Parsa 2017-06-15 19:23:00 +04:30
parent 15bc36afb0
commit d882b1ac77
4 changed files with 64 additions and 42 deletions

View File

@ -5,10 +5,9 @@ import hash from 'hash-sum'
import pify from 'pify'
import webpack from 'webpack'
import serialize from 'serialize-javascript'
import webpackDevMiddleware from 'webpack-dev-middleware'
import webpackHotMiddleware from 'webpack-hot-middleware'
import { join, resolve, basename, dirname } from 'path'
import Tapable from 'tappable'
import chalk from 'chalk'
import { r, wp, createRoutes } from './utils'
import clientWebpackConfig from './webpack/client.config.js'
import serverWebpackConfig from './webpack/server.config.js'
@ -282,7 +281,7 @@ export default class Builder extends Tapable {
// Start build
return new Promise((resolve, reject) => {
this.compiler.run((err, multiStats) => {
const handler = (err, multiStats) => {
if (err) {
return reject(err)
}
@ -292,8 +291,15 @@ export default class Builder extends Tapable {
return reject(new Error('Webpack build exited with errors'))
}
}
// Use watch handler instead of compiler.apply('done') to prevent duplicate emits
this.applyPlugins('reload', multiStats)
resolve()
})
}
if (this.options.dev) {
this.compiler.watch(this.options.watchers.webpack, handler)
} else {
this.compiler.run(handler)
}
})
}
@ -306,42 +312,33 @@ export default class Builder extends Tapable {
compiler.outputFileSystem = mfs
})
let clientConfig = this.compiler.$client.options
// Watch
this.plugin('reload', () => {
// Show open URL
let _host = host === '0.0.0.0' ? 'localhost' : host
// eslint-disable-next-line no-console
console.log(chalk.bold(chalk.bgCyan.black(' OPEN ') + chalk.cyan(` http://${_host}:${port}\n`)))
// Setup on the fly compilation + hot-reload
clientConfig.entry.app = _.flatten(['webpack-hot-middleware/client?reload=true', clientConfig.entry.app])
clientConfig.plugins.push(
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
)
// Reload renderer if available
if (this.nuxt.renderer) {
this.nuxt.renderer.loadResources(mfs)
}
})
// Create webpack dev middleware
this.webpackDevMiddleware = pify(webpackDevMiddleware(this.compiler.$client, {
publicPath: clientConfig.output.publicPath,
// Create webpack Dev/Hot middleware
this.webpackDevMiddleware = pify(require('webpack-dev-middleware')(this.compiler.$client, {
publicPath: this.options.build.publicPath,
stats: this.webpackStats,
quiet: true,
noInfo: true,
watchOptions: this.options.watchers.webpack
}))
this.webpackHotMiddleware = pify(webpackHotMiddleware(this.compiler.$client, {
this.webpackHotMiddleware = pify(require('webpack-hot-middleware')(this.compiler.$client, {
log: false,
heartbeat: 2500
}))
// Run after compilation is done
this.compiler.plugin('done', async stats => {
// Reload renderer if available
if (this.nuxt.renderer) {
await this.nuxt.renderer.loadResources(mfs)
}
// Show open URL
if (!stats.hasErrors() && !stats.hasWarnings()) {
let _host = host === '0.0.0.0' ? 'localhost' : host
console.log(`> Open http://${_host}:${port}\n`) // eslint-disable-line no-console
}
})
this.watchFiles()
}

View File

@ -1,4 +1,5 @@
import Tapable from 'tappable'
import Builder from './builder'
import * as Utils from './utils'
import Renderer from './renderer'
import ModuleContainer from './module-container'
@ -56,7 +57,7 @@ export default class Nuxt extends Tapable {
if (this._builder) {
return this._builder
}
const Builder = require('./builder').default
// const Builder = require('./builder').default
this._builder = new Builder(this)
return this._builder
}

View File

@ -69,8 +69,10 @@ export default class Renderer extends Tapable {
this.gzipMiddleware = pify(compression(this.options.render.gzip))
}
// Try to load resources from fs
return this.loadResources()
// Load resources from fs
if (!this.options.dev) {
return this.loadResources()
}
}
async loadResources (_fs = fs, distPath) {
@ -91,21 +93,32 @@ export default class Renderer extends Tapable {
}
}
let updated = []
Object.keys(resourceMap).forEach(resourceKey => {
let { path, transform } = resourceMap[resourceKey]
let data
if (_fs.existsSync(path)) {
data = _fs.readFileSync(path, 'utf8')
if (typeof transform === 'function') {
data = transform(data)
}
let rawKey = '$$' + resourceKey
let rawData, data
if (!_fs.existsSync(path)) {
return // Resource not exists
}
if (data) {
this.resources[resourceKey] = data
rawData = _fs.readFileSync(path, 'utf8')
if (!rawData || rawData === this.resources[rawKey]) {
return // No changes
}
this.resources[rawKey] = rawData
data = transform(rawData)
if (!data) {
return // Invalid data ?
}
this.resources[resourceKey] = data
updated.push(resourceKey)
})
this.createRenderer()
if (updated.length > 0) {
// debug('Updated', updated.join(', '))
this.createRenderer()
}
}
createRenderer () {
@ -232,7 +245,9 @@ export default class Renderer extends Tapable {
async renderRoute (url, context = {}) {
/* istanbul ignore if */
if (!this.bundleRenderer || !this.resources.appTemplate) {
return Promise.reject(new Error('bundleRenderer is not available'))
return new Promise(resolve => {
setTimeout(() => resolve(this.renderRoute(url, context)), 1000)
})
}
// Log rendered url

View File

@ -1,4 +1,4 @@
import { each, defaults } from 'lodash'
import { each, defaults, flatten } from 'lodash'
import webpack from 'webpack'
import VueSSRClientPlugin from 'vue-server-renderer/client-plugin'
import HTMLPlugin from 'html-webpack-plugin'
@ -88,6 +88,15 @@ export default function webpackClientConfig () {
if (this.options.dev) {
config.plugins.push(new FriendlyErrorsWebpackPlugin())
}
// Dev client build
if(this.options.dev){
// Add HMR support
config.entry.app = flatten(['webpack-hot-middleware/client?name=$client&reload=true', config.entry.app])
config.plugins.push(
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
)
}
// Production client build
if (!this.options.dev) {
config.plugins.push(