Add nuxt.ready(), dev depends on process.env.NODE_ENV, server waits for modules to be ready and build() is called on development by default

This commit is contained in:
Sebastien Chopin 2017-06-02 17:58:53 +02:00
parent b4b740f2a0
commit 1ae3062283
6 changed files with 64 additions and 18 deletions

View File

@ -97,8 +97,21 @@ export function options () {
} }
export async function build () { export async function build () {
// Initialize modules first // Avoid calling this method multiple times
await this.module.init() if (this._buildDone) {
return this
}
// If building
if (this._building) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(this.build())
}, 300)
})
}
this._building = true
// Wait for Nuxt.js to be ready
await this.ready()
// Check if pages dir exists and warn if not // Check if pages dir exists and warn if not
this._nuxtPages = typeof this.createRoutes !== 'function' this._nuxtPages = typeof this.createRoutes !== 'function'
if (this._nuxtPages) { if (this._nuxtPages) {
@ -123,6 +136,8 @@ export async function build () {
await generateRoutesAndFiles.call(this) await generateRoutesAndFiles.call(this)
// Generate .nuxt/dist/ files // Generate .nuxt/dist/ files
await buildFiles.call(this) await buildFiles.call(this)
// Flag to set that building is done
this._buildDone = true
return this return this
} }

View File

@ -13,18 +13,16 @@ class Module {
this.nuxt = nuxt this.nuxt = nuxt
this.options = nuxt.options this.options = nuxt.options
this.modules = [] this.modules = []
this.initialized = false this.initing = this.ready()
} }
async init () { async ready () {
if (this.initialized) { if (this.initing) {
debug('[nuxt] Modules are already initialized') await this.initing
return return
} }
// Install all modules in sequence // Install all modules in sequence
await sequence(this.options.modules, this.addModule.bind(this)) await sequence(this.options.modules, this.addModule.bind(this))
// Indicate modules are already initialized
this.initialized = true
} }
addVendor (vendor) { addVendor (vendor) {

View File

@ -16,7 +16,7 @@ import * as utils from './utils'
class Nuxt { class Nuxt {
constructor (options = {}) { constructor (options = {}) {
const defaults = { const defaults = {
dev: true, dev: (process.env.NODE_ENV !== 'production'),
buildDir: '.nuxt', buildDir: '.nuxt',
env: {}, env: {},
head: { head: {
@ -72,6 +72,8 @@ class Nuxt {
} }
if (typeof options.transition === 'string') options.transition = { name: options.transition } if (typeof options.transition === 'string') options.transition = { name: options.transition }
this.options = _.defaultsDeep(options, defaults) this.options = _.defaultsDeep(options, defaults)
// Ready variable
this._ready = false
// Env variables // Env variables
this.dev = this.options.dev this.dev = this.options.dev
// Explicit srcDir, rootDir and buildDir // Explicit srcDir, rootDir and buildDir
@ -121,6 +123,21 @@ class Nuxt {
this.utils = utils this.utils = utils
// Add module integration // Add module integration
this.module = new Module(this) this.module = new Module(this)
// Init nuxt.js
this.ready()
// Launch build in development but don't wait for him to be finished
if (this.dev) {
this.build()
}
// Return nuxt.js instance
return this
}
async ready () {
if (this._ready) return this
// Init modules
await this.module.ready()
this._ready = true
} }
close (callback) { close (callback) {

View File

@ -23,6 +23,9 @@ export async function render (req, res) {
}, 1000) }, 1000)
}) })
} }
// Wait for nuxt.js to be ready
await this.ready()
// Get context
const context = getContext(req, res) const context = getContext(req, res)
res.statusCode = 200 res.statusCode = 200
try { try {
@ -92,6 +95,7 @@ export async function render (req, res) {
return err return err
} }
const html = this.errorTemplate({ const html = this.errorTemplate({
/* istanbul ignore if */
error: err, error: err,
stack: ansiHTML(encodeHtml(err.stack)) stack: ansiHTML(encodeHtml(err.stack))
}) })
@ -104,6 +108,9 @@ export async function render (req, res) {
} }
export async function renderRoute (url, context = {}) { export async function renderRoute (url, context = {}) {
// Wait for modules to be initialized
await this.ready()
// Log rendered url
debug(`Rendering url ${url}`) debug(`Rendering url ${url}`)
// Add url and isSever to the context // Add url and isSever to the context
context.url = url context.url = url
@ -165,6 +172,7 @@ export async function renderAndGetWindow (url, opts = {}) {
const { window } = await jsdom.JSDOM.fromURL(url, options) const { window } = await jsdom.JSDOM.fromURL(url, options)
// If Nuxt could not be loaded (error from the server-side) // If Nuxt could not be loaded (error from the server-side)
const nuxtExists = window.document.body.innerHTML.includes('window.__NUXT__') const nuxtExists = window.document.body.innerHTML.includes('window.__NUXT__')
/* istanbul ignore if */
if (!nuxtExists) { if (!nuxtExists) {
let error = new Error('Could not load the nuxt app') let error = new Error('Could not load the nuxt app')
error.body = window.document.body.innerHTML error.body = window.document.body.innerHTML

View File

@ -10,12 +10,15 @@ class Server {
// Initialize // Initialize
this.app = connect() this.app = connect()
this.server = http.createServer(this.app) this.server = http.createServer(this.app)
// Add Middleware this.nuxt.ready()
this.nuxt.options.serverMiddleware.forEach(m => { .then(() => {
this.useMiddleware(m) // Add Middleware
this.nuxt.options.serverMiddleware.forEach(m => {
this.useMiddleware(m)
})
// Add default render middleware
this.useMiddleware(this.render.bind(this))
}) })
// Add default render middleware
this.useMiddleware(this.render.bind(this))
return this return this
} }
@ -45,8 +48,11 @@ class Server {
listen (port, host) { listen (port, host) {
host = host || '127.0.0.1' host = host || '127.0.0.1'
port = port || 3000 port = port || 3000
this.server.listen(port, host, () => { this.nuxt.ready()
console.log('Ready on http://%s:%s', host, port) // eslint-disable-line no-console .then(() => {
this.server.listen(port, host, () => {
console.log('Ready on http://%s:%s', host, port) // eslint-disable-line no-console
})
}) })
return this return this
} }

View File

@ -7,12 +7,14 @@ test('Nuxt.js Class', t => {
t.is(typeof Nuxt, 'function') t.is(typeof Nuxt, 'function')
}) })
test('Nuxt.js Instance', async t => { test.serial('Nuxt.js Instance', async t => {
process.env.NODE_ENV = 'production'
const nuxt = new Nuxt() const nuxt = new Nuxt()
t.is(typeof nuxt, 'object') t.is(typeof nuxt, 'object')
t.is(nuxt.dev, true) t.is(nuxt.dev, false)
t.is(typeof nuxt.build, 'function') t.is(typeof nuxt.build, 'function')
t.is(typeof nuxt.generate, 'function') t.is(typeof nuxt.generate, 'function')
delete process.env.NODE_ENV
}) })
test.serial('Fail when build not done and try to render', async t => { test.serial('Fail when build not done and try to render', async t => {