mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-30 09:27:13 +00:00
Fully decouple builder
runBuild flag removed
This commit is contained in:
parent
5521925668
commit
59d7e786aa
@ -5,8 +5,7 @@ process.env.DEBUG = 'nuxt:*'
|
||||
|
||||
const fs = require('fs')
|
||||
const parseArgs = require('minimist')
|
||||
const without = require('lodash').without
|
||||
const { Nuxt } = require('../')
|
||||
const { Nuxt, Builder } = require('../')
|
||||
const resolve = require('path').resolve
|
||||
const debug = require('debug')('nuxt:build')
|
||||
debug.color = 2 // Force green color
|
||||
@ -53,7 +52,6 @@ if (typeof options.rootDir !== 'string') {
|
||||
}
|
||||
// Create production build when calling `nuxt build`
|
||||
options.dev = false
|
||||
options.runBuild = true // Force doing production build before init
|
||||
|
||||
// Analyze option
|
||||
options.build = options.build || {}
|
||||
@ -62,8 +60,10 @@ if (argv.analyze) {
|
||||
}
|
||||
|
||||
debug('Building...')
|
||||
const nuxt = module.exports = new Nuxt(options)
|
||||
nuxt.ready()
|
||||
const nuxt = new Nuxt(options)
|
||||
const builder = new Builder(nuxt)
|
||||
|
||||
builder.build()
|
||||
.then(() => {
|
||||
debug('Building done')
|
||||
})
|
||||
|
19
bin/nuxt-dev
19
bin/nuxt-dev
@ -8,10 +8,9 @@ const debug = require('debug')('nuxt:build')
|
||||
debug.color = 2 // force green color
|
||||
const fs = require('fs')
|
||||
const parseArgs = require('minimist')
|
||||
const { Nuxt, Server } = require('../')
|
||||
const { Nuxt, Server, Builder } = require('../')
|
||||
const chokidar = require('chokidar')
|
||||
const resolve = require('path').resolve
|
||||
const without = require('lodash').without
|
||||
|
||||
const argv = parseArgs(process.argv.slice(2), {
|
||||
alias: {
|
||||
@ -65,18 +64,23 @@ if (typeof options.rootDir !== 'string') {
|
||||
options.dev = true
|
||||
|
||||
const nuxt = new Nuxt(options)
|
||||
const builder = new Builder(nuxt)
|
||||
|
||||
const port = argv.port || process.env.PORT || process.env.npm_package_config_nuxt_port
|
||||
const host = argv.hostname || process.env.HOST || process.env.npm_package_config_nuxt_host
|
||||
const server = new Server(nuxt).listen(port, host)
|
||||
const server = new Server(nuxt)
|
||||
server.listen(port, host)
|
||||
|
||||
builder.build().then(() => {
|
||||
listenOnConfigChanges(nuxt, server)
|
||||
})
|
||||
|
||||
function listenOnConfigChanges (nuxt, server) {
|
||||
// Listen on nuxt.config.js changes
|
||||
const build = _.debounce(() => {
|
||||
debug('[nuxt.config.js] changed')
|
||||
delete require.cache[nuxtConfigFile]
|
||||
let options = {}
|
||||
var options = {}
|
||||
if (fs.existsSync(nuxtConfigFile)) {
|
||||
try {
|
||||
options = require(nuxtConfigFile)
|
||||
@ -84,13 +88,18 @@ function listenOnConfigChanges (nuxt, server) {
|
||||
return console.error(e) // eslint-disable-line no-console
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof options.rootDir !== 'string') {
|
||||
options.rootDir = rootDir
|
||||
}
|
||||
|
||||
nuxt.close()
|
||||
.then(() => {
|
||||
debug('Rebuilding the app...')
|
||||
const nuxt = new Nuxt(options)
|
||||
const builder = new Builder(nuxt)
|
||||
server.nuxt = nuxt
|
||||
return nuxt.ready()
|
||||
return builder.build()
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error while rebuild the app:', error) // eslint-disable-line no-console
|
||||
|
@ -7,7 +7,7 @@ const fs = require('fs')
|
||||
const parseArgs = require('minimist')
|
||||
const debug = require('debug')('nuxt:generate')
|
||||
|
||||
const { Nuxt } = require('../')
|
||||
const { Nuxt, Builder, Generator } = require('../')
|
||||
const resolve = require('path').resolve
|
||||
|
||||
const argv = parseArgs(process.argv.slice(2), {
|
||||
@ -49,11 +49,12 @@ if (typeof options.rootDir !== 'string') {
|
||||
options.rootDir = rootDir
|
||||
}
|
||||
options.dev = false // Force production mode (no webpack middleware called)
|
||||
options.runBuild = true // Force doing production build before init
|
||||
|
||||
debug('Generating...')
|
||||
const nuxt = module.exports = new Nuxt(options)
|
||||
nuxt.generate()
|
||||
const nuxt = new Nuxt(options)
|
||||
const builder = new Builder(nuxt)
|
||||
const generator = new Generator(nuxt, builder)
|
||||
generator.generate()
|
||||
.then(() => {
|
||||
debug('Generate done')
|
||||
process.exit(0)
|
||||
|
7
index.js
7
index.js
@ -14,8 +14,15 @@ process.noDeprecation = true
|
||||
|
||||
// Require Core
|
||||
const Core = require('./dist/core.js')
|
||||
Object.assign(exports, Core.default || Core)
|
||||
|
||||
// Require Builder
|
||||
const Builder = require('./dist/builder')
|
||||
Object.assign(exports, Builder.default || Builder)
|
||||
|
||||
// Use special env flag to specify app dir without modify builder
|
||||
if (!process.env.NUXT_APP_DIR) {
|
||||
process.env.NUXT_APP_DIR = path.resolve(__dirname, 'lib/app')
|
||||
}
|
||||
|
||||
module.exports = Object.assign(Core, Builder)
|
||||
|
@ -1,6 +1,6 @@
|
||||
import _ from 'lodash'
|
||||
import chokidar from 'chokidar'
|
||||
import fs from 'fs-extra'
|
||||
import fs, { remove, readFile, writeFile, mkdirp, utimes } from 'fs-extra'
|
||||
import hash from 'hash-sum'
|
||||
import pify from 'pify'
|
||||
import webpack from 'webpack'
|
||||
@ -19,11 +19,6 @@ import serverWebpackConfig from './webpack/server.config.js'
|
||||
const debug = Debug('nuxt:build')
|
||||
debug.color = 2 // Force green color
|
||||
|
||||
const remove = pify(fs.remove)
|
||||
const readFile = pify(fs.readFile)
|
||||
const utimes = pify(fs.utimes)
|
||||
const writeFile = pify(fs.writeFile)
|
||||
const mkdirp = pify(fs.mkdirp)
|
||||
const glob = pify(Glob)
|
||||
|
||||
export default class Builder extends Tapable {
|
||||
@ -32,8 +27,6 @@ export default class Builder extends Tapable {
|
||||
this.nuxt = nuxt
|
||||
this.options = nuxt.options
|
||||
|
||||
this._buildStatus = STATUS.INITIAL
|
||||
|
||||
// Fields that set on build
|
||||
this.compiler = null
|
||||
this.webpackDevMiddleware = null
|
||||
@ -46,11 +39,13 @@ export default class Builder extends Tapable {
|
||||
modules: false,
|
||||
colors: true
|
||||
}
|
||||
|
||||
this._buildStatus = STATUS.INITIAL
|
||||
}
|
||||
|
||||
async build () {
|
||||
// Avoid calling this method multiple times
|
||||
if (this._buildStatus === STATUS.BUILD_DONE) {
|
||||
// Avoid calling build() method multiple times when dev:true
|
||||
if (this._buildStatus === STATUS.BUILD_DONE && this.options.dev) {
|
||||
return this
|
||||
}
|
||||
// If building
|
||||
@ -63,6 +58,9 @@ export default class Builder extends Tapable {
|
||||
}
|
||||
this._buildStatus = STATUS.BUILDING
|
||||
|
||||
// Wait for nuxt ready
|
||||
await this.nuxt.ready()
|
||||
|
||||
// Check if pages dir exists and warn if not
|
||||
this._nuxtPages = typeof this.options.build.createRoutes !== 'function'
|
||||
if (this._nuxtPages) {
|
||||
@ -258,16 +256,27 @@ export default class Builder extends Tapable {
|
||||
|
||||
// Simulate webpack multi compiler interface
|
||||
// Separate compilers are simpler, safer and faster
|
||||
this.compiler = { cache: {}, compilers: [] }
|
||||
compilersOptions.forEach(compilersOption => {
|
||||
this.compiler.compilers.push(webpack(compilersOption))
|
||||
})
|
||||
this.compiler = { compilers: [] }
|
||||
this.compiler.plugin = (...args) => {
|
||||
this.compiler.compilers.forEach(compiler => {
|
||||
compiler.plugin(...args)
|
||||
})
|
||||
}
|
||||
|
||||
// Initialize shared FS and Cache
|
||||
const sharedFS = this.options.dev && new MFS()
|
||||
const sharedCache = {}
|
||||
|
||||
// Initialize compilers
|
||||
compilersOptions.forEach(compilersOption => {
|
||||
const compiler = webpack(compilersOption)
|
||||
if (sharedFS) {
|
||||
compiler.outputFileSystem = sharedFS
|
||||
}
|
||||
compiler.cache = sharedCache
|
||||
this.compiler.compilers.push(compiler)
|
||||
})
|
||||
|
||||
// Access to compilers with name
|
||||
this.compiler.compilers.forEach(compiler => {
|
||||
if (compiler.name) {
|
||||
@ -275,6 +284,18 @@ export default class Builder extends Tapable {
|
||||
}
|
||||
})
|
||||
|
||||
// Run after each compile
|
||||
this.compiler.plugin('done', stats => {
|
||||
// Don't reload failed builds
|
||||
if (stats.hasErrors() || stats.hasWarnings()) {
|
||||
return
|
||||
}
|
||||
// Reload renderer if available
|
||||
if (this.nuxt.renderer) {
|
||||
this.nuxt.renderer.loadResources(sharedFS || fs)
|
||||
}
|
||||
})
|
||||
|
||||
// Add dev Stuff
|
||||
if (this.options.dev) {
|
||||
this.webpackDev()
|
||||
@ -297,8 +318,11 @@ export default class Builder extends Tapable {
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// --- Production build ---
|
||||
// --- Production Build ---
|
||||
compiler.run((err, stats) => {
|
||||
if (err) {
|
||||
return reject(err)
|
||||
}
|
||||
if (err) return console.error(err) // eslint-disable-line no-console
|
||||
// Show build stats for production
|
||||
console.log(stats.toString(this.webpackStats)) // eslint-disable-line no-console
|
||||
@ -312,26 +336,6 @@ export default class Builder extends Tapable {
|
||||
}
|
||||
|
||||
webpackDev () {
|
||||
// Use shared MFS + Cache for faster builds
|
||||
let mfs = new MFS()
|
||||
this.compiler.compilers.forEach(compiler => {
|
||||
compiler.outputFileSystem = mfs
|
||||
compiler.cache = this.compiler.cache
|
||||
})
|
||||
|
||||
// Run after each compile
|
||||
this.compiler.plugin('done', stats => {
|
||||
// Don't reload failed builds
|
||||
if (stats.hasErrors() || stats.hasWarnings()) {
|
||||
return
|
||||
}
|
||||
// Reload renderer if available
|
||||
if (this.nuxt.renderer) {
|
||||
this.nuxt.renderer.loadResources(mfs)
|
||||
}
|
||||
})
|
||||
|
||||
// Add dev Middleware
|
||||
debug('Adding webpack middleware...')
|
||||
|
||||
// Create webpack dev middleware
|
||||
@ -348,6 +352,12 @@ export default class Builder extends Tapable {
|
||||
heartbeat: 2500
|
||||
}))
|
||||
|
||||
// Inject to renderer instance
|
||||
if (this.nuxt.renderer) {
|
||||
this.nuxt.renderer.webpackDevMiddleware = this.webpackDevMiddleware
|
||||
this.nuxt.renderer.webpackHotMiddleware = this.webpackHotMiddleware
|
||||
}
|
||||
|
||||
// Stop webpack middleware on nuxt.close()
|
||||
this.nuxt.plugin('close', () => new Promise(resolve => {
|
||||
this.webpackDevMiddleware.close(() => resolve())
|
||||
|
@ -1,5 +1,5 @@
|
||||
import fs from 'fs-extra'
|
||||
import pify from 'pify'
|
||||
import fs from 'fs'
|
||||
import { copy, remove, writeFile, mkdirp } from 'fs-extra'
|
||||
import _ from 'lodash'
|
||||
import { resolve, join, dirname, sep } from 'path'
|
||||
import { minify } from 'html-minifier'
|
||||
@ -8,19 +8,16 @@ import { isUrl, promisifyRoute, waitFor, flatRoutes } from 'utils'
|
||||
import Debug from 'debug'
|
||||
|
||||
const debug = Debug('nuxt:generate')
|
||||
const copy = pify(fs.copy)
|
||||
const remove = pify(fs.remove)
|
||||
const writeFile = pify(fs.writeFile)
|
||||
const mkdirp = pify(fs.mkdirp)
|
||||
|
||||
export default class Generator extends Tapable {
|
||||
constructor (nuxt) {
|
||||
constructor (nuxt, builder) {
|
||||
super()
|
||||
this.nuxt = nuxt
|
||||
this.options = nuxt.options
|
||||
this.builder = builder
|
||||
}
|
||||
|
||||
async generate () {
|
||||
async generate (doBuild = true) {
|
||||
const s = Date.now()
|
||||
let errors = []
|
||||
let generateRoutes = []
|
||||
@ -34,6 +31,11 @@ export default class Generator extends Tapable {
|
||||
// Wait for nuxt be ready
|
||||
await this.nuxt.ready()
|
||||
|
||||
// Start build process
|
||||
if (this.builder && doBuild) {
|
||||
await this.builder.build()
|
||||
}
|
||||
|
||||
// Clean destination folder
|
||||
await remove(distPath)
|
||||
debug('Destination folder cleaned')
|
||||
|
@ -1,12 +1,7 @@
|
||||
import Tapable from 'tappable'
|
||||
import chalk from 'chalk'
|
||||
import ModuleContainer from './module'
|
||||
import Renderer from './renderer'
|
||||
import Options from './options'
|
||||
import Core from './index'
|
||||
|
||||
const defaultHost = process.env.HOST || process.env.npm_package_config_nuxt_host || 'localhost'
|
||||
const defaultPort = process.env.PORT || process.env.npm_package_config_nuxt_port || '3000'
|
||||
|
||||
export default class Nuxt extends Tapable {
|
||||
constructor (_options = {}) {
|
||||
@ -26,18 +21,6 @@ export default class Nuxt extends Tapable {
|
||||
this.renderRoute = this.renderer.renderRoute.bind(this.renderer)
|
||||
this.renderAndGetWindow = this.renderer.renderAndGetWindow.bind(this.renderer)
|
||||
|
||||
// Builder is lazy loaded, so register plugin here
|
||||
this.plugin('init', async () => {
|
||||
// Call to build on dev
|
||||
if (this.options.dev) {
|
||||
this.builder.build().catch(this.errorHandler)
|
||||
}
|
||||
// If explicitly runBuild required
|
||||
if (this.options.runBuild) {
|
||||
await this.builder.build()
|
||||
}
|
||||
})
|
||||
|
||||
this._ready = this.ready()
|
||||
}
|
||||
|
||||
@ -55,26 +38,6 @@ export default class Nuxt extends Tapable {
|
||||
return this
|
||||
}
|
||||
|
||||
get builder () {
|
||||
if (this._builder) {
|
||||
return this._builder
|
||||
}
|
||||
this._builder = new Core.Builder(this)
|
||||
return this._builder
|
||||
}
|
||||
|
||||
get generator () {
|
||||
if (this._generator) {
|
||||
return this._generator
|
||||
}
|
||||
this._generator = new Core.Generator(this)
|
||||
return this._generator
|
||||
}
|
||||
|
||||
generate () {
|
||||
return this.generator.generate.apply(this.generator, arguments)
|
||||
}
|
||||
|
||||
errorHandler () {
|
||||
// Silent
|
||||
if (this.options.errorHandler === false) {
|
||||
@ -90,26 +53,10 @@ export default class Nuxt extends Tapable {
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
// Both Renderer & Server depend on this method
|
||||
serverReady ({ host = defaultHost, port = defaultPort } = {}) {
|
||||
let _host = host === '0.0.0.0' ? 'localhost' : host
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('\n' + chalk.bold(chalk.bgBlue.black(' OPEN ') + chalk.blue(` http://${_host}:${port}\n`)))
|
||||
|
||||
return this.applyPluginsAsync('serverReady').catch(this.errorHandler)
|
||||
}
|
||||
|
||||
async close (callback) {
|
||||
// Call for close
|
||||
await this.applyPluginsAsync('close')
|
||||
|
||||
// Remove all references
|
||||
delete this._generator
|
||||
delete this._builder
|
||||
|
||||
this.initialized = false
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
await callback()
|
||||
}
|
||||
|
@ -45,17 +45,11 @@ export default function Options (_options) {
|
||||
options.store = true
|
||||
}
|
||||
|
||||
// runBuild can not be enabled for dev === true
|
||||
if (options.dev === true) {
|
||||
options.runBuild = false
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
const defaultOptions = {
|
||||
dev: (process.env.NODE_ENV !== 'production'),
|
||||
runBuild: false,
|
||||
buildDir: '.nuxt',
|
||||
nuxtAppDir: resolve(__dirname, '../lib/app/'), // Relative to dist
|
||||
build: {
|
||||
|
@ -33,12 +33,16 @@ export default class Renderer extends Tapable {
|
||||
// Will be set by createRenderer
|
||||
this.bundleRenderer = null
|
||||
|
||||
// Will be available on dev
|
||||
this.webpackDevMiddleware = null
|
||||
this.webpackHotMiddleware = null
|
||||
|
||||
// Renderer runtime resources
|
||||
this.resources = {
|
||||
clientManifest: null,
|
||||
serverBundle: null,
|
||||
appTemplate: null,
|
||||
errorTemplate: '<pre>{{ stack }}</pre>' // Will be loaded on ready
|
||||
errorTemplate: parseTemplate('<pre>{{ stack }}</pre>') // Will be loaded on ready
|
||||
}
|
||||
|
||||
// Initialize
|
||||
@ -146,10 +150,6 @@ export default class Renderer extends Tapable {
|
||||
|
||||
// Promisify renderToString
|
||||
this.bundleRenderer.renderToString = pify(this.bundleRenderer.renderToString)
|
||||
|
||||
if (!this.options.runBuild) {
|
||||
this.nuxt.serverReady()
|
||||
}
|
||||
}
|
||||
|
||||
async render (req, res) {
|
||||
@ -170,9 +170,12 @@ export default class Renderer extends Tapable {
|
||||
}
|
||||
|
||||
// Call webpack middleware only in development
|
||||
if (this.options.dev && this.nuxt.builder && this.nuxt.builder.webpackDevMiddleware) {
|
||||
await this.nuxt.builder.webpackDevMiddleware(req, res)
|
||||
await this.nuxt.builder.webpackHotMiddleware(req, res)
|
||||
if (this.webpackDevMiddleware) {
|
||||
await this.webpackDevMiddleware(req, res)
|
||||
}
|
||||
|
||||
if (this.webpackHotMiddleware) {
|
||||
await this.webpackHotMiddleware(req, res)
|
||||
}
|
||||
|
||||
// Serve static/ files
|
||||
|
@ -1,6 +1,7 @@
|
||||
import http from 'http'
|
||||
import connect from 'connect'
|
||||
import path from 'path'
|
||||
import chalk from 'chalk'
|
||||
|
||||
class Server {
|
||||
constructor (nuxt) {
|
||||
@ -32,6 +33,7 @@ class Server {
|
||||
this.options.serverMiddleware.forEach(m => {
|
||||
this.useMiddleware(m)
|
||||
})
|
||||
|
||||
// Add default render middleware
|
||||
this.useMiddleware(this.render.bind(this))
|
||||
|
||||
@ -66,8 +68,9 @@ class Server {
|
||||
this.nuxt.ready()
|
||||
.then(() => {
|
||||
this.server.listen(port, host, () => {
|
||||
// Renderer calls showURL when server is really ready
|
||||
// this.nuxt.showURL(host, port)
|
||||
let _host = host === '0.0.0.0' ? 'localhost' : host
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('\n' + chalk.bold(chalk.bgBlue.black(' OPEN ') + chalk.blue(` http://${_host}:${port}\n`)))
|
||||
})
|
||||
})
|
||||
.catch(this.nuxt.errorHandler)
|
||||
|
Loading…
Reference in New Issue
Block a user