diff --git a/lib/builder/builder.js b/lib/builder/builder.js index 2fa55682ed..d3cccca87a 100644 --- a/lib/builder/builder.js +++ b/lib/builder/builder.js @@ -25,7 +25,7 @@ debug.color = 2 // Force green color const glob = pify(Glob) export default class Builder extends Tapable { - constructor (nuxt) { + constructor(nuxt) { super() this.nuxt = nuxt this.isStatic = false // Flag to know if the build is for a generated app @@ -57,9 +57,12 @@ export default class Builder extends Tapable { this.vueLoader = vueLoaderConfig.bind(this) this._buildStatus = STATUS.INITIAL + + // Call class hook + this.nuxt.applyPlugins('builder', this) } - get plugins () { + get plugins() { return this.options.plugins.map((p, i) => { if (typeof p === 'string') p = { src: p } return { @@ -70,7 +73,7 @@ export default class Builder extends Tapable { }) } - vendor () { + vendor() { return [ 'vue', 'vue-router', @@ -79,7 +82,7 @@ export default class Builder extends Tapable { ].concat(this.options.build.vendor).filter(v => v) } - vendorEntries () { + vendorEntries() { // Used for dll const vendor = this.vendor() const vendorEntries = {} @@ -94,11 +97,11 @@ export default class Builder extends Tapable { return vendorEntries } - forGenerate () { + forGenerate() { this.isStatic = true } - async build () { + async build() { // Avoid calling build() method multiple times when dev:true /* istanbul ignore if */ if (this._buildStatus === STATUS.BUILD_DONE && this.options.dev) { @@ -119,7 +122,7 @@ export default class Builder extends Tapable { await this.nuxt.ready() // Wait for build plugins - await this.nuxt.applyPluginsAsync('build', this) + await this.applyPluginsAsync('build', this.options.build) // Babel options this.babelOptions = _.defaults(this.options.build.babel, { @@ -177,15 +180,15 @@ export default class Builder extends Tapable { // Start webpack build await this.webpackBuild() - await this.applyPluginsAsync('built', this) - // Flag to set that building is done this._buildStatus = STATUS.BUILD_DONE + await this.applyPluginsAsync('built') + return this } - async generateRoutesAndFiles () { + async generateRoutesAndFiles() { debug('Generating files...') // -- Templates -- let templatesFiles = [ @@ -264,7 +267,7 @@ export default class Builder extends Tapable { templateVars.router.routes = this.options.build.createRoutes(this.options.srcDir) } - await this.applyPluginsAsync('extendRoutes', { routes: templateVars.router.routes, templateVars, r }) + await this.applyPluginsAsync('extendRoutes', templateVars.router.routes) // router.extendRoutes method if (typeof this.options.router.extendRoutes === 'function') { @@ -332,7 +335,7 @@ export default class Builder extends Tapable { } } - await this.applyPluginsAsync('generate', { builder: this, templatesFiles, templateVars }) + await this.applyPluginsAsync('generate', { templatesFiles, templateVars, resolve: r }) // Interpret and move template files to .nuxt/ await Promise.all(templatesFiles.map(async ({ src, dst, options, custom }) => { @@ -372,10 +375,10 @@ export default class Builder extends Tapable { return utimes(path, dateFS, dateFS) })) - await this.applyPluginsAsync('generated', this) + await this.applyPluginsAsync('generated') } - async webpackBuild () { + async webpackBuild() { debug('Building files...') const compilersOptions = [] @@ -433,11 +436,11 @@ export default class Builder extends Tapable { // Start Builds await sequence(this.compilers, (compiler) => new Promise(async (resolve, reject) => { const name = compiler.options.name - await this.applyPluginsAsync('compile', { builder: this, compiler, name }) + await this.applyPluginsAsync('compile', { name, compiler }) // Resolve only when compiler emit done event compiler.plugin('done', async (stats) => { - await this.applyPluginsAsync('compiled', { builder: this, compiler, name, stats }) + await this.applyPluginsAsync('compiled', { name, compiler, stats }) process.nextTick(resolve) }) // --- Dev Build --- @@ -484,7 +487,7 @@ export default class Builder extends Tapable { } } - webpackDev (compiler) { + webpackDev(compiler) { debug('Adding webpack middleware...') // Create webpack dev middleware @@ -516,7 +519,7 @@ export default class Builder extends Tapable { this.watchFiles() } - watchFiles () { + watchFiles() { const patterns = [ r(this.options.srcDir, 'layouts'), r(this.options.srcDir, 'store'), diff --git a/lib/builder/generator.js b/lib/builder/generator.js index 3afd1cb79a..da49c7fafc 100644 --- a/lib/builder/generator.js +++ b/lib/builder/generator.js @@ -9,7 +9,7 @@ import Debug from 'debug' const debug = Debug('nuxt:generate') export default class Generator extends Tapable { - constructor (nuxt, builder) { + constructor(nuxt, builder) { super() this.nuxt = nuxt this.options = nuxt.options @@ -20,9 +20,12 @@ export default class Generator extends Tapable { this.srcBuiltPath = resolve(this.options.buildDir, 'dist') this.distPath = resolve(this.options.rootDir, this.options.generate.dir) this.distNuxtPath = join(this.distPath, (isUrl(this.options.build.publicPath) ? '' : this.options.build.publicPath)) + + // Call class hook + this.nuxt.applyPlugins('generator', this) } - async generate ({ build = true, init = true } = {}) { + async generate({ build = true, init = true } = {}) { const s = Date.now() let errors = [] @@ -50,10 +53,8 @@ export default class Generator extends Tapable { try { console.log('Generating routes') // eslint-disable-line no-console generateRoutes = await promisifyRoute(this.options.generate.routes || []) - await this.applyPluginsAsync('generateRoutes', { generator: this, generateRoutes }) } catch (e) { console.error('Could not resolve routes') // eslint-disable-line no-console - console.error(e) // eslint-disable-line no-console throw e // eslint-disable-line no-unreachable } } @@ -62,7 +63,7 @@ export default class Generator extends Tapable { let routes = (this.options.router.mode === 'hash') ? ['/'] : flatRoutes(this.options.router.routes) routes = this.decorateWithPayloads(routes, generateRoutes) - await this.applyPluginsAsync('generate', { generator: this, routes }) + await this.applyPluginsAsync('generate', routes) // Start generate process while (routes.length) { @@ -86,6 +87,8 @@ export default class Generator extends Tapable { const duration = Math.round((Date.now() - s) / 100) / 10 debug(`HTML Files generated in ${duration}s`) + await this.applyPluginsAsync('generated', errors) + if (errors.length) { const report = errors.map(({ type, route, error }) => { /* istanbul ignore if */ @@ -98,12 +101,10 @@ export default class Generator extends Tapable { console.error('==== Error report ==== \n' + report.join('\n\n')) // eslint-disable-line no-console } - await this.applyPluginsAsync('generated', this) - return { duration, errors } } - async initDist () { + async initDist() { // Clean destination folder await remove(this.distPath) debug('Destination folder cleaned') @@ -137,7 +138,7 @@ export default class Generator extends Tapable { debug('Static & build files copied') } - decorateWithPayloads (routes, generateRoutes) { + decorateWithPayloads(routes, generateRoutes) { let routeMap = {} // Fill routeMap for known routes routes.forEach((route) => { @@ -148,7 +149,7 @@ export default class Generator extends Tapable { }) // Fill routeMap with given generate.routes generateRoutes.forEach((route) => { - // route is either a string or like {route : "/my_route/1"} + // route is either a string or like { route : '/my_route/1', payload: {} } const path = _.isString(route) ? route : route.route routeMap[path] = { route: path, @@ -158,7 +159,7 @@ export default class Generator extends Tapable { return _.values(routeMap) } - async generateRoute ({ route, payload = {}, errors = [] }) { + async generateRoute({ route, payload = {}, errors = [] }) { let html try { diff --git a/lib/core/module.js b/lib/core/module.js index 726227b8c7..09ae587144 100755 --- a/lib/core/module.js +++ b/lib/core/module.js @@ -9,19 +9,24 @@ import Debug from 'debug' const debug = Debug('nuxt:module') export default class ModuleContainer extends Tapable { - constructor (nuxt) { + constructor(nuxt) { super() this.nuxt = nuxt this.options = nuxt.options this.requiredModules = [] + + // Call class hook + console.log('call module container') + this.nuxt.applyPlugins('moduleContainer', this) } - async _ready () { + async ready() { + // Load every module in sequence await sequence(this.options.modules, this.addModule.bind(this)) - await this.applyPluginsAsync('ready', this) + await this.applyPluginsAsync('ready') } - addVendor (vendor) { + addVendor(vendor) { /* istanbul ignore if */ if (!vendor) { return @@ -29,7 +34,7 @@ export default class ModuleContainer extends Tapable { this.options.build.vendor = uniq(this.options.build.vendor.concat(vendor)) } - addTemplate (template) { + addTemplate(template) { /* istanbul ignore if */ if (!template) { return @@ -56,7 +61,7 @@ export default class ModuleContainer extends Tapable { return templateObj } - addPlugin (template) { + addPlugin(template) { const { dst } = this.addTemplate(template) // Add to nuxt plugins this.options.plugins.unshift({ @@ -65,31 +70,29 @@ export default class ModuleContainer extends Tapable { }) } - addServerMiddleware (middleware) { + addServerMiddleware(middleware) { this.options.serverMiddleware.push(middleware) } - extendBuild (fn) { + extendBuild(fn) { this.options.build.extend = chainFn(this.options.build.extend, fn) } - extendRoutes (fn) { + extendRoutes(fn) { this.options.router.extendRoutes = chainFn(this.options.router.extendRoutes, fn) } - requireModule (moduleOpts) { + requireModule(moduleOpts) { // Require once return this.addModule(moduleOpts, true) } - async addModule (moduleOpts, requireOnce) { + async addModule(moduleOpts, requireOnce) { /* istanbul ignore if */ if (!moduleOpts) { return } - await this.applyPluginsAsync('add', {moduleOpts, requireOnce}) - // Allow using babel style array options if (Array.isArray(moduleOpts)) { moduleOpts = { @@ -129,13 +132,13 @@ export default class ModuleContainer extends Tapable { } // Call module with `this` context and pass options - return new Promise((resolve, reject) => { - const result = module.call(this, options, err => { + const m = await new Promise((resolve, reject) => { + const result = module.call(this, options, (err, m) => { /* istanbul ignore if */ if (err) { return reject(err) } - resolve(module) + resolve(m) }) // If module send back a promise if (result && result.then instanceof Function) { @@ -146,5 +149,6 @@ export default class ModuleContainer extends Tapable { return resolve(module) } }) + await this.applyPluginsAsync('module', { meta: module.meta, module: m }) } } diff --git a/lib/core/nuxt.js b/lib/core/nuxt.js index 8ae6a2fc60..9e94dd6267 100644 --- a/lib/core/nuxt.js +++ b/lib/core/nuxt.js @@ -12,10 +12,10 @@ const debug = Debug('nuxt:') debug.color = 5 export default class Nuxt extends Tapable { - constructor (_options = {}) { + constructor(options = {}) { super() - this.options = Options.from(_options) + this.options = Options.from(options) // Paths for resolving requires from `rootDir` this.nodeModulePaths = Module._nodeModulePaths(this.options.rootDir) @@ -35,20 +35,20 @@ export default class Nuxt extends Tapable { this._ready = this.ready().catch(this.errorHandler) } - async ready () { + async ready() { if (this._ready) { return this._ready } - await this.moduleContainer._ready() + await this.moduleContainer.ready() await this.applyPluginsAsync('ready') - await this.renderer._ready() + await this.renderer.ready() this.initialized = true return this } - listen (port = 3000, host = 'localhost') { + listen(port = 3000, host = 'localhost') { return new Promise((resolve, reject) => { const server = this.renderer.app.listen({ port, host, exclusive: false }, err => { /* istanbul ignore if */ @@ -81,7 +81,7 @@ export default class Nuxt extends Tapable { }) } - errorHandler /* istanbul ignore next */() { + errorHandler/* istanbul ignore next */() { // Apply plugins // eslint-disable-next-line no-console this.applyPluginsAsync('error', ...arguments).catch(console.error) @@ -101,7 +101,7 @@ export default class Nuxt extends Tapable { console.error(...arguments) } - resolvePath (path) { + resolvePath(path) { // Try to resolve using NPM resolve path first try { let resolvedPath = Module._resolveFilename(path, { paths: this.nodeModulePaths }) @@ -118,7 +118,7 @@ export default class Nuxt extends Tapable { return resolve(this.options.srcDir, path) } - async close (callback) { + async close(callback) { await this.applyPluginsAsync('close') /* istanbul ignore if */ diff --git a/lib/core/renderer.js b/lib/core/renderer.js index 65132bcf74..e3dc16236e 100644 --- a/lib/core/renderer.js +++ b/lib/core/renderer.js @@ -25,7 +25,7 @@ setAnsiColors(ansiHTML) let jsdom = null export default class Renderer extends Tapable { - constructor (nuxt) { + constructor(nuxt) { super() this.nuxt = nuxt this.options = nuxt.options @@ -49,11 +49,12 @@ export default class Renderer extends Tapable { spaTemplate: null, errorTemplate: parseTemplate('Nuxt.js Internal Server Error') } + + // Call class hook + this.nuxt.applyPlugins('renderer', this) } - async _ready () { - await this.nuxt.applyPluginsAsync('renderer', this) - + async ready() { // Setup nuxt middleware await this.setupMiddleware() @@ -63,10 +64,10 @@ export default class Renderer extends Tapable { } // Call ready plugin - await this.applyPluginsAsync('ready', this) + await this.applyPluginsAsync('ready') } - async loadResources (_fs = fs) { + async loadResources(_fs = fs) { let distPath = resolve(this.options.buildDir, 'dist') let updated = [] @@ -115,11 +116,11 @@ export default class Renderer extends Tapable { } } - get noSSR () { + get noSSR() { return this.options.render.ssr === false } - get isReady () { + get isReady() { if (this.noSSR) { return Boolean(this.resources.spaTemplate) } @@ -127,7 +128,7 @@ export default class Renderer extends Tapable { return Boolean(this.bundleRenderer && this.resources.ssrTemplate) } - get isResourcesAvailable () { + get isResourcesAvailable() { // Required for both if (!this.resources.clientManifest) { return false @@ -142,7 +143,7 @@ export default class Renderer extends Tapable { return Boolean(this.resources.ssrTemplate && this.resources.serverBundle) } - createRenderer () { + createRenderer() { // Ensure resources are available if (!this.isResourcesAvailable) { return @@ -164,7 +165,7 @@ export default class Renderer extends Tapable { }, this.options.render.bundleRenderer)) } - useMiddleware (m) { + useMiddleware(m) { // Resolve const $m = m let src @@ -188,11 +189,11 @@ export default class Renderer extends Tapable { this.app.use(path, handler) } - get publicPath () { + get publicPath() { return isUrl(this.options.build.publicPath) ? Options.defaults.build.publicPath : this.options.build.publicPath } - async setupMiddleware () { + async setupMiddleware() { // Apply setupMiddleware from modules first await this.applyPluginsAsync('setupMiddleware', this.app) @@ -229,7 +230,7 @@ export default class Renderer extends Tapable { if (this.options.debug) { this.useMiddleware({ path: '_open', - handler (req, res) { + handler(req, res) { // Lazy load open-in-editor const openInEditor = require('open-in-editor') const editor = openInEditor.configure(_this.options.editor) @@ -280,9 +281,10 @@ export default class Renderer extends Tapable { this.useMiddleware(this.errorMiddleware.bind(this)) } - async nuxtMiddleware (req, res, next) { + async nuxtMiddleware(req, res, next) { // Get context const context = getContext(req, res) + res.statusCode = 200 try { const { html, error, redirected, resourceHints } = await this.renderRoute(req.url, context) @@ -338,7 +340,7 @@ export default class Renderer extends Tapable { } } - errorMiddleware (err, req, res, next) { + errorMiddleware(err, req, res, next) { // ensure statusCode, message and name fields err.statusCode = err.statusCode || 500 err.message = err.message || 'Nuxt Server Error' @@ -390,7 +392,7 @@ export default class Renderer extends Tapable { } } - async readSource (frame) { + async readSource(frame) { const serverBundle = this.resources.serverBundle // Remove webpack:/// & query string from the end @@ -468,7 +470,7 @@ export default class Renderer extends Tapable { } } - async renderRoute (url, context = {}) { + async renderRoute(url, context = {}) { /* istanbul ignore if */ if (!this.isReady) { return new Promise(resolve => { @@ -546,7 +548,7 @@ export default class Renderer extends Tapable { } } - async renderAndGetWindow (url, opts = {}) { + async renderAndGetWindow(url, opts = {}) { /* istanbul ignore if */ if (!jsdom) { try { @@ -561,10 +563,9 @@ export default class Renderer extends Tapable { let options = { resources: 'usable', // load subresources (https://github.com/tmpvar/jsdom#loading-subresources) runScripts: 'dangerously', - beforeParse (window) { + beforeParse(window) { // Mock window.scrollTo - window.scrollTo = () => { - } + window.scrollTo = () => {} } } if (opts.virtualConsole !== false) {