mirror of
https://github.com/nuxt/nuxt.git
synced 2025-01-30 15:22:39 +00:00
feat: add tappable hooks
This commit is contained in:
parent
a587b798e4
commit
b209c80d2b
@ -43,6 +43,9 @@ export default class Builder extends Tapable {
|
|||||||
// Helper to resolve build paths
|
// Helper to resolve build paths
|
||||||
this.relativeToBuild = (...args) => relativeTo(this.options.buildDir, ...args)
|
this.relativeToBuild = (...args) => relativeTo(this.options.buildDir, ...args)
|
||||||
|
|
||||||
|
// Call builder plugin on parent nuxt to notify all modules of builder existence
|
||||||
|
this.nuxt.applyPluginsAsync('builder', this).catch(this.nuxt.errorHandler)
|
||||||
|
|
||||||
this._buildStatus = STATUS.INITIAL
|
this._buildStatus = STATUS.INITIAL
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,6 +69,8 @@ export default class Builder extends Tapable {
|
|||||||
// Wait for nuxt ready
|
// Wait for nuxt ready
|
||||||
await this.nuxt.ready()
|
await this.nuxt.ready()
|
||||||
|
|
||||||
|
await this.applyPluginsAsync('build', this)
|
||||||
|
|
||||||
// Check if pages dir exists and warn if not
|
// Check if pages dir exists and warn if not
|
||||||
this._nuxtPages = typeof this.options.build.createRoutes !== 'function'
|
this._nuxtPages = typeof this.options.build.createRoutes !== 'function'
|
||||||
if (this._nuxtPages) {
|
if (this._nuxtPages) {
|
||||||
@ -95,6 +100,8 @@ export default class Builder extends Tapable {
|
|||||||
// Start webpack build
|
// Start webpack build
|
||||||
await this.webpackBuild()
|
await this.webpackBuild()
|
||||||
|
|
||||||
|
await this.applyPluginsAsync('built', this)
|
||||||
|
|
||||||
// Flag to set that building is done
|
// Flag to set that building is done
|
||||||
this._buildStatus = STATUS.BUILD_DONE
|
this._buildStatus = STATUS.BUILD_DONE
|
||||||
|
|
||||||
@ -173,6 +180,9 @@ export default class Builder extends Tapable {
|
|||||||
} else {
|
} else {
|
||||||
templateVars.router.routes = this.options.build.createRoutes(this.options.srcDir)
|
templateVars.router.routes = this.options.build.createRoutes(this.options.srcDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.applyPluginsAsync('extendRoutes', {routes: templateVars.router.routes, templateVars, r})
|
||||||
|
|
||||||
// router.extendRoutes method
|
// router.extendRoutes method
|
||||||
if (typeof this.options.router.extendRoutes === 'function') {
|
if (typeof this.options.router.extendRoutes === 'function') {
|
||||||
// let the user extend the routes
|
// let the user extend the routes
|
||||||
@ -216,6 +226,8 @@ export default class Builder extends Tapable {
|
|||||||
}, t)
|
}, t)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
await this.applyPluginsAsync('generate', { builder: this, templatesFiles, templateVars })
|
||||||
|
|
||||||
// Interpret and move template files to .nuxt/
|
// Interpret and move template files to .nuxt/
|
||||||
await Promise.all(templatesFiles.map(async ({ src, dst, options, custom }) => {
|
await Promise.all(templatesFiles.map(async ({ src, dst, options, custom }) => {
|
||||||
// Add template to watchers
|
// Add template to watchers
|
||||||
@ -246,9 +258,11 @@ export default class Builder extends Tapable {
|
|||||||
const dateFS = Date.now() / 1000 - 1000
|
const dateFS = Date.now() / 1000 - 1000
|
||||||
return utimes(path, dateFS, dateFS)
|
return utimes(path, dateFS, dateFS)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
await this.applyPluginsAsync('generated', this)
|
||||||
}
|
}
|
||||||
|
|
||||||
webpackBuild () {
|
async webpackBuild () {
|
||||||
debug('Building files...')
|
debug('Building files...')
|
||||||
let compilersOptions = []
|
let compilersOptions = []
|
||||||
|
|
||||||
@ -291,7 +305,7 @@ export default class Builder extends Tapable {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Run after each compile
|
// Run after each compile
|
||||||
this.compiler.plugin('done', stats => {
|
this.compiler.plugin('done', async stats => {
|
||||||
// Don't reload failed builds
|
// Don't reload failed builds
|
||||||
/* istanbul ignore if */
|
/* istanbul ignore if */
|
||||||
if (stats.hasErrors() || stats.hasWarnings()) {
|
if (stats.hasErrors() || stats.hasWarnings()) {
|
||||||
@ -301,6 +315,8 @@ export default class Builder extends Tapable {
|
|||||||
if (this.nuxt.renderer) {
|
if (this.nuxt.renderer) {
|
||||||
this.nuxt.renderer.loadResources(sharedFS || fs)
|
this.nuxt.renderer.loadResources(sharedFS || fs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.applyPluginsAsync('compiled', { builder: this, stats })
|
||||||
})
|
})
|
||||||
|
|
||||||
// Add dev Stuff
|
// Add dev Stuff
|
||||||
@ -308,6 +324,8 @@ export default class Builder extends Tapable {
|
|||||||
this.webpackDev()
|
this.webpackDev()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.applyPluginsAsync('compile', { builder: this, compiler: this.compiler })
|
||||||
|
|
||||||
// Start Builds
|
// Start Builds
|
||||||
return parallel(this.compiler.compilers, compiler => new Promise((resolve, reject) => {
|
return parallel(this.compiler.compilers, compiler => new Promise((resolve, reject) => {
|
||||||
if (this.options.dev) {
|
if (this.options.dev) {
|
||||||
|
@ -15,6 +15,15 @@ export default class Generator extends Tapable {
|
|||||||
this.nuxt = nuxt
|
this.nuxt = nuxt
|
||||||
this.options = nuxt.options
|
this.options = nuxt.options
|
||||||
this.builder = builder
|
this.builder = builder
|
||||||
|
|
||||||
|
// Set variables
|
||||||
|
this.generateRoutes = resolve(this.options.srcDir, 'static')
|
||||||
|
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 generator plugin on parent nuxt to notify all modules of generator existence
|
||||||
|
this.nuxt.applyPluginsAsync('generator', this).catch(this.nuxt.errorHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
async generate (doBuild = true) {
|
async generate (doBuild = true) {
|
||||||
@ -22,12 +31,6 @@ export default class Generator extends Tapable {
|
|||||||
let errors = []
|
let errors = []
|
||||||
let generateRoutes = []
|
let generateRoutes = []
|
||||||
|
|
||||||
// Set variables
|
|
||||||
let srcStaticPath = resolve(this.options.srcDir, 'static')
|
|
||||||
let srcBuiltPath = resolve(this.options.buildDir, 'dist')
|
|
||||||
let distPath = resolve(this.options.rootDir, this.options.generate.dir)
|
|
||||||
let distNuxtPath = join(distPath, (isUrl(this.options.build.publicPath) ? '' : this.options.build.publicPath))
|
|
||||||
|
|
||||||
// Wait for nuxt be ready
|
// Wait for nuxt be ready
|
||||||
await this.nuxt.ready()
|
await this.nuxt.ready()
|
||||||
|
|
||||||
@ -36,16 +39,18 @@ export default class Generator extends Tapable {
|
|||||||
await this.builder.build()
|
await this.builder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.applyPluginsAsync('before-generate', this)
|
||||||
|
|
||||||
// Clean destination folder
|
// Clean destination folder
|
||||||
await remove(distPath)
|
await remove(this.distPath)
|
||||||
debug('Destination folder cleaned')
|
debug('Destination folder cleaned')
|
||||||
|
|
||||||
// Copy static and built files
|
// Copy static and built files
|
||||||
/* istanbul ignore if */
|
/* istanbul ignore if */
|
||||||
if (fs.existsSync(srcStaticPath)) {
|
if (fs.existsSync(this.generateRoutes)) {
|
||||||
await copy(srcStaticPath, distPath)
|
await copy(this.generateRoutes, this.distPath)
|
||||||
}
|
}
|
||||||
await copy(srcBuiltPath, distNuxtPath)
|
await copy(this.srcBuiltPath, this.distNuxtPath)
|
||||||
debug('Static & build files copied')
|
debug('Static & build files copied')
|
||||||
|
|
||||||
// Resolve config.generate.routes promises before generating the routes
|
// Resolve config.generate.routes promises before generating the routes
|
||||||
@ -53,6 +58,7 @@ export default class Generator extends Tapable {
|
|||||||
try {
|
try {
|
||||||
console.log('Generating routes') // eslint-disable-line no-console
|
console.log('Generating routes') // eslint-disable-line no-console
|
||||||
generateRoutes = await promisifyRoute(this.options.generate.routes || [])
|
generateRoutes = await promisifyRoute(this.options.generate.routes || [])
|
||||||
|
await this.applyPluginsAsync('generateRoutes', {generator: this, generateRoutes})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Could not resolve routes') // eslint-disable-line no-console
|
console.error('Could not resolve routes') // eslint-disable-line no-console
|
||||||
console.error(e) // eslint-disable-line no-console
|
console.error(e) // eslint-disable-line no-console
|
||||||
@ -85,6 +91,8 @@ export default class Generator extends Tapable {
|
|||||||
let routes = (this.options.router.mode === 'hash') ? ['/'] : flatRoutes(this.options.router.routes)
|
let routes = (this.options.router.mode === 'hash') ? ['/'] : flatRoutes(this.options.router.routes)
|
||||||
routes = decorateWithPayloads(routes)
|
routes = decorateWithPayloads(routes)
|
||||||
|
|
||||||
|
await this.applyPluginsAsync('generate', {generator: this, routes})
|
||||||
|
|
||||||
while (routes.length) {
|
while (routes.length) {
|
||||||
let n = 0
|
let n = 0
|
||||||
await Promise.all(routes.splice(0, 500).map(async ({ route, payload }) => {
|
await Promise.all(routes.splice(0, 500).map(async ({ route, payload }) => {
|
||||||
@ -111,7 +119,7 @@ export default class Generator extends Tapable {
|
|||||||
let path = join(route, sep, 'index.html') // /about -> /about/index.html
|
let path = join(route, sep, 'index.html') // /about -> /about/index.html
|
||||||
path = (path === '/404/index.html') ? '/404.html' : path // /404 -> /404.html
|
path = (path === '/404/index.html') ? '/404.html' : path // /404 -> /404.html
|
||||||
debug('Generate file: ' + path)
|
debug('Generate file: ' + path)
|
||||||
path = join(distPath, path)
|
path = join(this.distPath, path)
|
||||||
// Make sure the sub folders are created
|
// Make sure the sub folders are created
|
||||||
await mkdirp(dirname(path))
|
await mkdirp(dirname(path))
|
||||||
await writeFile(path, html, 'utf8')
|
await writeFile(path, html, 'utf8')
|
||||||
@ -120,7 +128,7 @@ export default class Generator extends Tapable {
|
|||||||
|
|
||||||
// Add .nojekyll file to let Github Pages add the _nuxt/ folder
|
// Add .nojekyll file to let Github Pages add the _nuxt/ folder
|
||||||
// https://help.github.com/articles/files-that-start-with-an-underscore-are-missing/
|
// https://help.github.com/articles/files-that-start-with-an-underscore-are-missing/
|
||||||
const nojekyllPath = resolve(distPath, '.nojekyll')
|
const nojekyllPath = resolve(this.distPath, '.nojekyll')
|
||||||
writeFile(nojekyllPath, '')
|
writeFile(nojekyllPath, '')
|
||||||
const duration = Math.round((Date.now() - s) / 100) / 10
|
const duration = Math.round((Date.now() - s) / 100) / 10
|
||||||
debug(`HTML Files generated in ${duration}s`)
|
debug(`HTML Files generated in ${duration}s`)
|
||||||
@ -137,6 +145,8 @@ export default class Generator extends Tapable {
|
|||||||
console.error('==== Error report ==== \n' + report.join('\n\n')) // eslint-disable-line no-console
|
console.error('==== Error report ==== \n' + report.join('\n\n')) // eslint-disable-line no-console
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.applyPluginsAsync('generated', this)
|
||||||
|
|
||||||
return { duration, errors }
|
return { duration, errors }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,9 @@ export default class ModuleContainer extends Tapable {
|
|||||||
this.options = nuxt.options
|
this.options = nuxt.options
|
||||||
this.requiredModules = []
|
this.requiredModules = []
|
||||||
|
|
||||||
this.nuxt.plugin('beforeInit', () => {
|
this.nuxt.plugin('beforeInit', async () => {
|
||||||
return sequence(this.options.modules, this.addModule.bind(this))
|
await sequence(this.options.modules, this.addModule.bind(this))
|
||||||
|
await this.applyPluginsAsync('ready', this)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,11 +82,14 @@ export default class ModuleContainer extends Tapable {
|
|||||||
return this.addModule(moduleOpts, true)
|
return this.addModule(moduleOpts, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
addModule (moduleOpts, requireOnce) {
|
async addModule (moduleOpts, requireOnce) {
|
||||||
/* istanbul ignore if */
|
/* istanbul ignore if */
|
||||||
if (!moduleOpts) {
|
if (!moduleOpts) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.applyPluginsAsync('add', {moduleOpts, requireOnce})
|
||||||
|
|
||||||
// Allow using babel style array options
|
// Allow using babel style array options
|
||||||
if (Array.isArray(moduleOpts)) {
|
if (Array.isArray(moduleOpts)) {
|
||||||
moduleOpts = {
|
moduleOpts = {
|
||||||
@ -93,12 +97,13 @@ export default class ModuleContainer extends Tapable {
|
|||||||
options: moduleOpts[1]
|
options: moduleOpts[1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allows passing runtime options to each module
|
// Allows passing runtime options to each module
|
||||||
const options = moduleOpts.options || (typeof moduleOpts === 'object' ? moduleOpts : {})
|
const options = moduleOpts.options || (typeof moduleOpts === 'object' ? moduleOpts : {})
|
||||||
const originalSrc = moduleOpts.src || moduleOpts
|
const originalSrc = moduleOpts.src || moduleOpts
|
||||||
|
|
||||||
// Resolve module
|
// Resolve module
|
||||||
let module = originalSrc
|
let module = originalSrc
|
||||||
|
|
||||||
if (typeof module === 'string') {
|
if (typeof module === 'string') {
|
||||||
module = require(this.nuxt.resolvePath(module))
|
module = require(this.nuxt.resolvePath(module))
|
||||||
}
|
}
|
||||||
@ -108,6 +113,7 @@ export default class ModuleContainer extends Tapable {
|
|||||||
if (typeof module !== 'function') {
|
if (typeof module !== 'function') {
|
||||||
throw new Error(`[nuxt] Module ${JSON.stringify(originalSrc)} should export a function`)
|
throw new Error(`[nuxt] Module ${JSON.stringify(originalSrc)} should export a function`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Module meta
|
// Module meta
|
||||||
if (!module.meta) {
|
if (!module.meta) {
|
||||||
module.meta = {}
|
module.meta = {}
|
||||||
@ -121,6 +127,7 @@ export default class ModuleContainer extends Tapable {
|
|||||||
this.requiredModules.push(module.meta.name)
|
this.requiredModules.push(module.meta.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call module with `this` context and pass options
|
// Call module with `this` context and pass options
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const result = module.call(this, options, err => {
|
const result = module.call(this, options, err => {
|
||||||
|
@ -79,18 +79,23 @@ 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)
|
||||||
|
|
||||||
// Silent
|
// Silent
|
||||||
if (this.options.errorHandler === false) {
|
if (this.options.errorHandler === false) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom errorHandler
|
// Custom errorHandler
|
||||||
if (typeof this.options.errorHandler === 'function') {
|
if (typeof this.options.errorHandler === 'function') {
|
||||||
return this.options.errorHandler.apply(this, arguments)
|
return this.options.errorHandler.apply(this, arguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default handler
|
// Default handler
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.error.apply(this, arguments)
|
console.error(...arguments)
|
||||||
process.exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resolvePath (path) {
|
resolvePath (path) {
|
||||||
|
@ -71,7 +71,7 @@ export default class Renderer extends Tapable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setup all middleWare
|
// Setup all middleWare
|
||||||
this.setupMiddleware()
|
await this.setupMiddleware()
|
||||||
|
|
||||||
// Load error template
|
// Load error template
|
||||||
const errorTemplatePath = resolve(this.options.buildDir, 'views/error.html')
|
const errorTemplatePath = resolve(this.options.buildDir, 'views/error.html')
|
||||||
@ -165,9 +165,9 @@ export default class Renderer extends Tapable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setupMiddleware () {
|
async setupMiddleware () {
|
||||||
// Apply setupMiddleware from modules first
|
// Apply setupMiddleware from modules first
|
||||||
this.applyPlugins('setupMiddleware', this.app)
|
await this.applyPluginsAsync('setupMiddleware', this.app)
|
||||||
|
|
||||||
// Gzip middleware for production
|
// Gzip middleware for production
|
||||||
if (!this.options.dev && this.options.render.gzip) {
|
if (!this.options.dev && this.options.render.gzip) {
|
||||||
|
Loading…
Reference in New Issue
Block a user