mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-23 14:15:13 +00:00
feat(generator): export:route
hook and setPayload
(#7422)
* feat(generator): shared payload support for `nuxt export` * feat: add `export:` hooks for upward compatibility * fix: use setPayload to avoid breaking usage * test: update test * fix: deep assign * chore: update tests * fix: route payload has more periority than shared one * test: update generator hook tests * lint: remove unnecessary import
This commit is contained in:
parent
618eb5fad0
commit
a82f8d8b1f
@ -2,6 +2,7 @@ import path from 'path'
|
|||||||
import chalk from 'chalk'
|
import chalk from 'chalk'
|
||||||
import consola from 'consola'
|
import consola from 'consola'
|
||||||
import fsExtra from 'fs-extra'
|
import fsExtra from 'fs-extra'
|
||||||
|
import defu from 'defu'
|
||||||
import htmlMinifier from 'html-minifier'
|
import htmlMinifier from 'html-minifier'
|
||||||
import { parse } from 'node-html-parser'
|
import { parse } from 'node-html-parser'
|
||||||
|
|
||||||
@ -23,6 +24,12 @@ export default class Generator {
|
|||||||
isUrl(this.options.build.publicPath) ? '' : this.options.build.publicPath
|
isUrl(this.options.build.publicPath) ? '' : this.options.build.publicPath
|
||||||
)
|
)
|
||||||
this.generatedRoutes = new Set()
|
this.generatedRoutes = new Set()
|
||||||
|
|
||||||
|
// Shared payload
|
||||||
|
this._payload = null
|
||||||
|
this.setPayload = (payload) => {
|
||||||
|
this._payload = defu(payload, this._payload)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async generate ({ build = true, init = true } = {}) {
|
async generate ({ build = true, init = true } = {}) {
|
||||||
@ -47,6 +54,7 @@ export default class Generator {
|
|||||||
|
|
||||||
// Done hook
|
// Done hook
|
||||||
await this.nuxt.callHook('generate:done', this, errors)
|
await this.nuxt.callHook('generate:done', this, errors)
|
||||||
|
await this.nuxt.callHook('export:done', this, { errors })
|
||||||
|
|
||||||
return { errors }
|
return { errors }
|
||||||
}
|
}
|
||||||
@ -57,6 +65,7 @@ export default class Generator {
|
|||||||
|
|
||||||
// Call before hook
|
// Call before hook
|
||||||
await this.nuxt.callHook('generate:before', this, this.options.generate)
|
await this.nuxt.callHook('generate:before', this, this.options.generate)
|
||||||
|
await this.nuxt.callHook('export:before', this)
|
||||||
|
|
||||||
if (build) {
|
if (build) {
|
||||||
// Add flag to set process.static
|
// Add flag to set process.static
|
||||||
@ -115,6 +124,7 @@ export default class Generator {
|
|||||||
|
|
||||||
// extendRoutes hook
|
// extendRoutes hook
|
||||||
await this.nuxt.callHook('generate:extendRoutes', routes)
|
await this.nuxt.callHook('generate:extendRoutes', routes)
|
||||||
|
await this.nuxt.callHook('export:extendRoutes', { routes })
|
||||||
|
|
||||||
return routes
|
return routes
|
||||||
}
|
}
|
||||||
@ -223,6 +233,7 @@ export default class Generator {
|
|||||||
|
|
||||||
consola.info(`Generating output directory: ${path.basename(this.distPath)}/`)
|
consola.info(`Generating output directory: ${path.basename(this.distPath)}/`)
|
||||||
await this.nuxt.callHook('generate:distRemoved', this)
|
await this.nuxt.callHook('generate:distRemoved', this)
|
||||||
|
await this.nuxt.callHook('export:distCopied', this)
|
||||||
|
|
||||||
// Copy static and built files
|
// Copy static and built files
|
||||||
if (await fsExtra.exists(this.staticRoutes)) {
|
if (await fsExtra.exists(this.staticRoutes)) {
|
||||||
@ -241,6 +252,7 @@ export default class Generator {
|
|||||||
fsExtra.writeFile(nojekyllPath, '')
|
fsExtra.writeFile(nojekyllPath, '')
|
||||||
|
|
||||||
await this.nuxt.callHook('generate:distCopied', this)
|
await this.nuxt.callHook('generate:distCopied', this)
|
||||||
|
await this.nuxt.callHook('export:distCopied', this)
|
||||||
}
|
}
|
||||||
|
|
||||||
decorateWithPayloads (routes, generateRoutes) {
|
decorateWithPayloads (routes, generateRoutes) {
|
||||||
@ -265,6 +277,18 @@ export default class Generator {
|
|||||||
let html
|
let html
|
||||||
const pageErrors = []
|
const pageErrors = []
|
||||||
|
|
||||||
|
const setPayload = (_payload) => {
|
||||||
|
payload = defu(_payload, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply shared payload
|
||||||
|
if (this._payload) {
|
||||||
|
payload = defu(payload, this._payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.nuxt.callHook('generate:route', { route, setPayload })
|
||||||
|
await this.nuxt.callHook('export:route', { route, setPayload })
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const renderContext = {
|
const renderContext = {
|
||||||
payload,
|
payload,
|
||||||
@ -301,10 +325,8 @@ export default class Generator {
|
|||||||
pageErrors.push({ type: 'unhandled', route, error: err })
|
pageErrors.push({ type: 'unhandled', route, error: err })
|
||||||
errors.push(...pageErrors)
|
errors.push(...pageErrors)
|
||||||
|
|
||||||
await this.nuxt.callHook('generate:routeFailed', {
|
await this.nuxt.callHook('generate:routeFailed', { route, errors: pageErrors })
|
||||||
route,
|
await this.nuxt.callHook('export:routeFailed', { route, errors: pageErrors })
|
||||||
errors: pageErrors
|
|
||||||
})
|
|
||||||
consola.error(this._formatErrors(pageErrors))
|
consola.error(this._formatErrors(pageErrors))
|
||||||
|
|
||||||
return false
|
return false
|
||||||
@ -332,6 +354,7 @@ export default class Generator {
|
|||||||
// Call hook to let user update the path & html
|
// Call hook to let user update the path & html
|
||||||
const page = { route, path: fileName, html }
|
const page = { route, path: fileName, html }
|
||||||
await this.nuxt.callHook('generate:page', page)
|
await this.nuxt.callHook('generate:page', page)
|
||||||
|
await this.nuxt.callHook('export:page', { page })
|
||||||
|
|
||||||
page.path = path.join(this.distPath, page.path)
|
page.path = path.join(this.distPath, page.path)
|
||||||
|
|
||||||
@ -339,11 +362,8 @@ export default class Generator {
|
|||||||
await fsExtra.mkdirp(path.dirname(page.path))
|
await fsExtra.mkdirp(path.dirname(page.path))
|
||||||
await fsExtra.writeFile(page.path, page.html, 'utf8')
|
await fsExtra.writeFile(page.path, page.html, 'utf8')
|
||||||
|
|
||||||
await this.nuxt.callHook('generate:routeCreated', {
|
await this.nuxt.callHook('generate:routeCreated', { route, path: page.path, errors: pageErrors })
|
||||||
route,
|
await this.nuxt.callHook('export:routeCreated', { route, path: page.path, errors: pageErrors })
|
||||||
path: page.path,
|
|
||||||
errors: pageErrors
|
|
||||||
})
|
|
||||||
|
|
||||||
if (pageErrors.length) {
|
if (pageErrors.length) {
|
||||||
consola.error('Error generating ' + route)
|
consola.error('Error generating ' + route)
|
||||||
|
@ -14,3 +14,7 @@ export const createNuxt = () => ({
|
|||||||
render: {}
|
render: {}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export function hookCalls (nuxt, name) {
|
||||||
|
return nuxt.callHook.mock.calls.filter(c => c[0] === name).map(c => c.splice(1))
|
||||||
|
}
|
||||||
|
@ -57,7 +57,6 @@ describe('generator: generate routes', () => {
|
|||||||
expect(generator.generateRoutes).toBeCalledTimes(1)
|
expect(generator.generateRoutes).toBeCalledTimes(1)
|
||||||
expect(generator.generateRoutes).toBeCalledWith(routes)
|
expect(generator.generateRoutes).toBeCalledWith(routes)
|
||||||
expect(generator.afterGenerate).toBeCalledTimes(1)
|
expect(generator.afterGenerate).toBeCalledTimes(1)
|
||||||
expect(nuxt.callHook).toBeCalledTimes(1)
|
|
||||||
expect(nuxt.callHook).toBeCalledWith('generate:done', generator, errors)
|
expect(nuxt.callHook).toBeCalledWith('generate:done', generator, errors)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import fsExtra from 'fs-extra'
|
|||||||
import { flatRoutes, isString, isUrl, promisifyRoute } from '@nuxt/utils'
|
import { flatRoutes, isString, isUrl, promisifyRoute } from '@nuxt/utils'
|
||||||
|
|
||||||
import Generator from '../src/generator'
|
import Generator from '../src/generator'
|
||||||
import { createNuxt } from './__utils__'
|
import { createNuxt, hookCalls } from './__utils__'
|
||||||
|
|
||||||
jest.mock('path')
|
jest.mock('path')
|
||||||
jest.mock('fs-extra')
|
jest.mock('fs-extra')
|
||||||
@ -63,8 +63,7 @@ describe('generator: initialize', () => {
|
|||||||
await generator.initiate()
|
await generator.initiate()
|
||||||
|
|
||||||
expect(nuxt.ready).toBeCalledTimes(1)
|
expect(nuxt.ready).toBeCalledTimes(1)
|
||||||
expect(nuxt.callHook).toBeCalledTimes(1)
|
expect(hookCalls(nuxt, 'generate:before')[0]).toMatchObject([generator, { dir: generator.distPath }])
|
||||||
expect(nuxt.callHook).toBeCalledWith('generate:before', generator, { dir: generator.distPath })
|
|
||||||
expect(builder.forGenerate).toBeCalledTimes(1)
|
expect(builder.forGenerate).toBeCalledTimes(1)
|
||||||
expect(builder.build).toBeCalledTimes(1)
|
expect(builder.build).toBeCalledTimes(1)
|
||||||
expect(generator.initDist).toBeCalledTimes(1)
|
expect(generator.initDist).toBeCalledTimes(1)
|
||||||
@ -82,8 +81,7 @@ describe('generator: initialize', () => {
|
|||||||
await generator.initiate({ build: false, init: false })
|
await generator.initiate({ build: false, init: false })
|
||||||
|
|
||||||
expect(nuxt.ready).toBeCalledTimes(1)
|
expect(nuxt.ready).toBeCalledTimes(1)
|
||||||
expect(nuxt.callHook).toBeCalledTimes(1)
|
expect(hookCalls(nuxt, 'generate:before')[0]).toMatchObject([generator, { dir: generator.distPath }])
|
||||||
expect(nuxt.callHook).toBeCalledWith('generate:before', generator, { dir: generator.distPath })
|
|
||||||
expect(builder.forGenerate).not.toBeCalled()
|
expect(builder.forGenerate).not.toBeCalled()
|
||||||
expect(builder.build).not.toBeCalled()
|
expect(builder.build).not.toBeCalled()
|
||||||
expect(generator.initDist).not.toBeCalled()
|
expect(generator.initDist).not.toBeCalled()
|
||||||
@ -117,8 +115,7 @@ describe('generator: initialize', () => {
|
|||||||
expect(flatRoutes).toBeCalledWith(['/index', '/about', '/test'])
|
expect(flatRoutes).toBeCalledWith(['/index', '/about', '/test'])
|
||||||
expect(generator.decorateWithPayloads).toBeCalledTimes(1)
|
expect(generator.decorateWithPayloads).toBeCalledTimes(1)
|
||||||
expect(generator.decorateWithPayloads).toBeCalledWith(['/index', '/about'], ['/foo', '/foo/bar'])
|
expect(generator.decorateWithPayloads).toBeCalledWith(['/index', '/about'], ['/foo', '/foo/bar'])
|
||||||
expect(nuxt.callHook).toBeCalledTimes(1)
|
expect(hookCalls(nuxt, 'generate:extendRoutes')[0][0]).toBe('decoratedRoutes')
|
||||||
expect(nuxt.callHook).toBeCalledWith('generate:extendRoutes', 'decoratedRoutes')
|
|
||||||
expect(routes).toEqual('decoratedRoutes')
|
expect(routes).toEqual('decoratedRoutes')
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -147,8 +144,7 @@ describe('generator: initialize', () => {
|
|||||||
expect(flatRoutes).not.toBeCalled()
|
expect(flatRoutes).not.toBeCalled()
|
||||||
expect(generator.decorateWithPayloads).toBeCalledTimes(1)
|
expect(generator.decorateWithPayloads).toBeCalledTimes(1)
|
||||||
expect(generator.decorateWithPayloads).toBeCalledWith(['/'], [])
|
expect(generator.decorateWithPayloads).toBeCalledWith(['/'], [])
|
||||||
expect(nuxt.callHook).toBeCalledTimes(1)
|
expect(hookCalls(nuxt, 'generate:extendRoutes')[0][0]).toBe('decoratedRoutes')
|
||||||
expect(nuxt.callHook).toBeCalledWith('generate:extendRoutes', 'decoratedRoutes')
|
|
||||||
expect(routes).toEqual('decoratedRoutes')
|
expect(routes).toEqual('decoratedRoutes')
|
||||||
|
|
||||||
promisifyRoute.mockReset()
|
promisifyRoute.mockReset()
|
||||||
@ -184,8 +180,7 @@ describe('generator: initialize', () => {
|
|||||||
|
|
||||||
expect(fsExtra.emptyDir).toBeCalledTimes(1)
|
expect(fsExtra.emptyDir).toBeCalledTimes(1)
|
||||||
expect(fsExtra.emptyDir).toBeCalledWith(generator.distPath)
|
expect(fsExtra.emptyDir).toBeCalledWith(generator.distPath)
|
||||||
expect(nuxt.callHook).toBeCalledTimes(2)
|
expect(hookCalls(nuxt, 'generate:distRemoved')[0][0]).toMatchObject(generator)
|
||||||
expect(nuxt.callHook).nthCalledWith(1, 'generate:distRemoved', generator)
|
|
||||||
expect(fsExtra.exists).toBeCalledTimes(1)
|
expect(fsExtra.exists).toBeCalledTimes(1)
|
||||||
expect(fsExtra.exists).toBeCalledWith(generator.staticRoutes)
|
expect(fsExtra.exists).toBeCalledWith(generator.staticRoutes)
|
||||||
expect(fsExtra.copy).toBeCalledTimes(1)
|
expect(fsExtra.copy).toBeCalledTimes(1)
|
||||||
@ -194,7 +189,7 @@ describe('generator: initialize', () => {
|
|||||||
expect(path.resolve).toBeCalledWith(generator.distPath, '.nojekyll')
|
expect(path.resolve).toBeCalledWith(generator.distPath, '.nojekyll')
|
||||||
expect(fsExtra.writeFile).toBeCalledTimes(1)
|
expect(fsExtra.writeFile).toBeCalledTimes(1)
|
||||||
expect(fsExtra.writeFile).toBeCalledWith(`resolve(${generator.distPath}, .nojekyll)`, '')
|
expect(fsExtra.writeFile).toBeCalledWith(`resolve(${generator.distPath}, .nojekyll)`, '')
|
||||||
expect(nuxt.callHook).nthCalledWith(2, 'generate:distCopied', generator)
|
expect(hookCalls(nuxt, 'generate:distCopied')[0][0]).toMatchObject(generator)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should copy static routes if path exists', async () => {
|
test('should copy static routes if path exists', async () => {
|
||||||
|
@ -4,7 +4,7 @@ import fsExtra from 'fs-extra'
|
|||||||
import htmlMinifier from 'html-minifier'
|
import htmlMinifier from 'html-minifier'
|
||||||
|
|
||||||
import Generator from '../src/generator'
|
import Generator from '../src/generator'
|
||||||
import { createNuxt } from './__utils__'
|
import { createNuxt, hookCalls } from './__utils__'
|
||||||
|
|
||||||
jest.mock('path')
|
jest.mock('path')
|
||||||
jest.mock('fs-extra')
|
jest.mock('fs-extra')
|
||||||
@ -47,17 +47,19 @@ describe('generator: generate route', () => {
|
|||||||
expect(path.join).toBeCalledTimes(2)
|
expect(path.join).toBeCalledTimes(2)
|
||||||
expect(path.join).nthCalledWith(1, '[sep]', '/foo.html')
|
expect(path.join).nthCalledWith(1, '[sep]', '/foo.html')
|
||||||
expect(path.join).nthCalledWith(2, generator.distPath, 'join([sep], /foo.html)')
|
expect(path.join).nthCalledWith(2, generator.distPath, 'join([sep], /foo.html)')
|
||||||
expect(nuxt.callHook).toBeCalledTimes(2)
|
|
||||||
expect(nuxt.callHook).nthCalledWith(1, 'generate:page', {
|
expect(hookCalls(nuxt, 'generate:page')[0][0]).toMatchObject({
|
||||||
route,
|
route,
|
||||||
html: 'rendered html',
|
html: 'rendered html',
|
||||||
path: `join(${generator.distPath}, join([sep], /foo.html))`
|
path: `join(${generator.distPath}, join([sep], /foo.html))`
|
||||||
})
|
})
|
||||||
expect(nuxt.callHook).nthCalledWith(2, 'generate:routeCreated', {
|
|
||||||
|
expect(hookCalls(nuxt, 'generate:routeCreated')[0][0]).toMatchObject({
|
||||||
route,
|
route,
|
||||||
errors: [],
|
errors: [],
|
||||||
path: `join(${generator.distPath}, join([sep], /foo.html))`
|
path: `join(${generator.distPath}, join([sep], /foo.html))`
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(fsExtra.mkdirp).toBeCalledTimes(1)
|
expect(fsExtra.mkdirp).toBeCalledTimes(1)
|
||||||
expect(fsExtra.mkdirp).toBeCalledWith(`dirname(join(${generator.distPath}, join([sep], /foo.html)))`)
|
expect(fsExtra.mkdirp).toBeCalledWith(`dirname(join(${generator.distPath}, join([sep], /foo.html)))`)
|
||||||
expect(fsExtra.writeFile).toBeCalledTimes(1)
|
expect(fsExtra.writeFile).toBeCalledTimes(1)
|
||||||
@ -82,7 +84,6 @@ describe('generator: generate route', () => {
|
|||||||
|
|
||||||
expect(nuxt.server.renderRoute).toBeCalledTimes(1)
|
expect(nuxt.server.renderRoute).toBeCalledTimes(1)
|
||||||
expect(nuxt.server.renderRoute).toBeCalledWith('/foo', { payload })
|
expect(nuxt.server.renderRoute).toBeCalledWith('/foo', { payload })
|
||||||
expect(nuxt.callHook).toBeCalledTimes(1)
|
|
||||||
expect(nuxt.callHook).toBeCalledWith('generate:routeFailed', {
|
expect(nuxt.callHook).toBeCalledWith('generate:routeFailed', {
|
||||||
route,
|
route,
|
||||||
errors: [{ type: 'unhandled', route, error }]
|
errors: [{ type: 'unhandled', route, error }]
|
||||||
|
17
test/fixtures/full-static/nuxt.config.js
vendored
17
test/fixtures/full-static/nuxt.config.js
vendored
@ -1,3 +1,18 @@
|
|||||||
export default {
|
export default {
|
||||||
target: 'static'
|
target: 'static',
|
||||||
|
export: {
|
||||||
|
payload: {
|
||||||
|
config: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hooks: {
|
||||||
|
export: {
|
||||||
|
before ({ setPayload }) {
|
||||||
|
setPayload({ shared: true })
|
||||||
|
},
|
||||||
|
route ({ route, setPayload }) {
|
||||||
|
setPayload({ myRoute: route })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
13
test/fixtures/full-static/pages/payload.vue
vendored
Normal file
13
test/fixtures/full-static/pages/payload.vue
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<template>
|
||||||
|
<div v-text="JSON.stringify(payload)" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
asyncData ({ payload }) {
|
||||||
|
return {
|
||||||
|
payload
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
Loading…
Reference in New Issue
Block a user