feat(kit, nuxt3): add pages:extend and extendPages (#1740)

Co-authored-by: Pooya Parsa <pyapar@gmail.com>
Co-authored-by: fgiraud <hello@florent.dev>
This commit is contained in:
Daniel Roe 2021-11-09 10:16:23 +00:00 committed by GitHub
parent 82d1741d52
commit 95cbe67f99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 79 additions and 13 deletions

View File

@ -0,0 +1,15 @@
import { defineNuxtModule, extendPages } from '@nuxt/kit'
import { resolve } from 'pathe'
export default defineNuxtModule({
setup () {
extendPages((pages) => {
// Add /test page
pages.push({
name: 'Test',
path: '/test',
file: resolve(__dirname, './pages/test.vue')
})
})
}
})

View File

@ -0,0 +1,5 @@
<template>
<div>
Test page added by module
</div>
</template>

View File

@ -0,0 +1,7 @@
import { defineNuxtConfig } from 'nuxt3'
export default defineNuxtConfig({
buildModules: [
'~/modules/pages'
]
})

View File

@ -0,0 +1,12 @@
{
"name": "example-module-extend-pages",
"private": true,
"devDependencies": {
"nuxt3": "latest"
},
"scripts": {
"dev": "nuxi dev",
"build": "nuxi build",
"start": "node .output/server/index.mjs"
}
}

View File

@ -0,0 +1,7 @@
<template>
<div>
Go to <NuxtLink to="/test">
Test Page
</NuxtLink>
</div>
</template>

View File

@ -0,0 +1,3 @@
{
"extends": "./.nuxt/tsconfig.json"
}

View File

@ -2,7 +2,8 @@ import { parse, relative } from 'pathe'
import consola from 'consola'
import type { Nuxt, NuxtPluginTemplate, NuxtTemplate } from '../types/nuxt'
import { chainFn } from '../utils/task'
import { addTemplate, addPluginTemplate, addServerMiddleware } from './utils'
import { resolveAlias } from '../utils/resolve'
import { addTemplate, addPluginTemplate, addServerMiddleware, extendPages } from './utils'
import { installModule } from './install'
/** Legacy ModuleContainer for backwards compatibility with existing Nuxt 2 modules. */
@ -103,7 +104,7 @@ export function createModuleContainer (nuxt: Nuxt) {
/** Allows extending routes by chaining `options.build.extendRoutes` function. */
extendRoutes (fn) {
nuxt.options.router.extendRoutes = chainFn(nuxt.options.router.extendRoutes, fn)
extendPages(routes => fn(routes, resolveAlias))
},
/** `requireModule` is a shortcut for `addModule` */

View File

@ -11,6 +11,7 @@ import { Nuxt } from '../types/nuxt'
import { useNuxt } from '../nuxt'
import type { NuxtTemplate, NuxtPlugin, NuxtPluginTemplate } from '../types/nuxt'
import type { ComponentsDir, Component } from '../types/components'
import type { NuxtHooks } from '../types/hooks'
/**
* Renders given template using lodash template during build into the project buildDir
@ -351,6 +352,11 @@ export function addComponent (opts: AddComponentOptions) {
})
}
export function extendPages (cb: NuxtHooks['pages:extend']) {
const nuxt = useNuxt()
nuxt.hook('pages:extend', cb)
}
const serialize = (data: any) => JSON.stringify(data, null, 2).replace(/"{(.+)}"/g, '$1')
const importName = (src: string) => `${camelCase(basename(src, extname(src))).replace(/[^a-zA-Z?\d\s:]/g, '')}_${hash(src)}`

View File

@ -31,12 +31,20 @@ type RenderResult = {
// https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html
export type TSReference = { types: string } | { path: string }
export type NuxtPage = {
name?: string,
path: string,
file: string,
children?: NuxtPage[]
}
export interface NuxtHooks {
// nuxt3
'app:resolve': (app: NuxtApp) => HookResult
'app:templates': (app: NuxtApp) => HookResult
'app:templatesGenerated': (app: NuxtApp) => HookResult
'builder:generateApp': () => HookResult
'pages:extend': (pages: NuxtPage[]) => HookResult
// Auto imports
'autoImports:sources': (autoImportSources: AutoImportSource[]) => HookResult

View File

@ -44,8 +44,9 @@ export default defineNuxtModule({
addTemplate({
filename: 'routes.mjs',
async getContents () {
const routes = await resolvePagesRoutes(nuxt)
const serializedRoutes = addComponentToRoutes(routes)
const pages = await resolvePagesRoutes(nuxt)
await nuxt.callHook('pages:extend', pages)
const serializedRoutes = addComponentToRoutes(pages)
return `export default ${JSON.stringify(serializedRoutes, null, 2).replace(/"{(.+)}"/g, '$1')}`
}
})

View File

@ -1,15 +1,8 @@
import { basename, extname, relative, resolve } from 'pathe'
import { encodePath } from 'ufo'
import { Nuxt, resolveFiles } from '@nuxt/kit'
import { Nuxt, resolveFiles, NuxtRoute } from '@nuxt/kit'
import { kebabCase } from 'scule'
export interface NuxtRoute {
name?: string
path: string
file: string
children: NuxtRoute[]
}
enum SegmentParserState {
initial,
static,
@ -234,7 +227,7 @@ export async function resolveLayouts (nuxt: Nuxt) {
export function addComponentToRoutes (routes: NuxtRoute[]) {
return routes.map(route => ({
...route,
children: addComponentToRoutes(route.children),
children: route.children ? addComponentToRoutes(route.children) : [],
component: `{() => import('${route.file}')}`
}))
}

View File

@ -9661,6 +9661,14 @@ __metadata:
languageName: unknown
linkType: soft
"example-module-extend-pages@workspace:examples/module-extend-pages":
version: 0.0.0-use.local
resolution: "example-module-extend-pages@workspace:examples/module-extend-pages"
dependencies:
nuxt3: latest
languageName: unknown
linkType: soft
"example-use-async-data@workspace:examples/use-async-data":
version: 0.0.0-use.local
resolution: "example-use-async-data@workspace:examples/use-async-data"