mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-11 08:33:53 +00:00
chore: start parsing pages
This commit is contained in:
parent
e892f5f019
commit
d14d695190
@ -1,7 +1,12 @@
|
|||||||
import { resolve } from 'path'
|
import { resolve } from 'path'
|
||||||
|
import globby from 'globby'
|
||||||
|
import { Builder } from './builder'
|
||||||
|
|
||||||
export interface NuxtRoute {
|
export interface NuxtRoute {
|
||||||
path: ''
|
name?: string
|
||||||
|
path: string
|
||||||
|
component: string
|
||||||
|
children?: NuxtRoute[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NuxtApp {
|
export interface NuxtApp {
|
||||||
@ -11,12 +16,18 @@ export interface NuxtApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Scan project structure
|
// Scan project structure
|
||||||
export function resolveApp (nuxt, srcDir: string): NuxtApp {
|
export async function resolveApp (builder: Builder, srcDir: string): Promise<NuxtApp> {
|
||||||
|
const { nuxt } = builder
|
||||||
// resolve App.vue
|
// resolve App.vue
|
||||||
const main = nuxt.resolver.tryResolvePath('~/App') ||
|
const main = nuxt.resolver.tryResolvePath('~/App') ||
|
||||||
nuxt.resolver.tryResolvePath('~/app') ||
|
nuxt.resolver.tryResolvePath('~/app') ||
|
||||||
resolve(nuxt.options.appDir, 'app.vue')
|
resolve(nuxt.options.appDir, 'app.vue')
|
||||||
|
|
||||||
|
const pagesPattern = `${nuxt.options.dir.pages}/**/*.{${nuxt.options.extensions.join(',')}}`
|
||||||
|
const pages = await resolveFiles(builder, pagesPattern, srcDir)
|
||||||
|
const routes = buildRoutes(pages, srcDir, nuxt.options.dir.pages, nuxt.options.extensions)
|
||||||
|
|
||||||
|
console.log('routes', routes)
|
||||||
// TODO: Read pages/ and create routes
|
// TODO: Read pages/ and create routes
|
||||||
// TODO: Detect store
|
// TODO: Detect store
|
||||||
// Use hooks?
|
// Use hooks?
|
||||||
@ -32,3 +43,97 @@ export function resolveApp (nuxt, srcDir: string): NuxtApp {
|
|||||||
routes: []
|
routes: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function resolveFiles (builder: Builder, pattern: string, srcDir: string) {
|
||||||
|
const { nuxt } = builder
|
||||||
|
|
||||||
|
return builder.ignore.filter(await globby(pattern, {
|
||||||
|
cwd: srcDir,
|
||||||
|
followSymbolicLinks: nuxt.options.build.followSymlinks
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
const isDynamicRoute = (s: string) => /^\[.+\]$/.test(s)
|
||||||
|
|
||||||
|
export function buildRoutes (
|
||||||
|
files: string[],
|
||||||
|
srcDir: string,
|
||||||
|
pagesDir: string,
|
||||||
|
extensions: string[]
|
||||||
|
) {
|
||||||
|
const routes: NuxtRoute[] = []
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
const pathParts = file
|
||||||
|
.replace(new RegExp(`^${pagesDir}`), '')
|
||||||
|
.replace(new RegExp(`\\.(${extensions.join('|')})$`), '')
|
||||||
|
.split('/')
|
||||||
|
.slice(1) // removing the pagesDir means that the path begins with a '/'
|
||||||
|
|
||||||
|
const route: NuxtRoute = {
|
||||||
|
name: '',
|
||||||
|
path: '',
|
||||||
|
component: resolve(srcDir, file)
|
||||||
|
}
|
||||||
|
|
||||||
|
let parent = routes
|
||||||
|
|
||||||
|
for (let i = 0; i < pathParts.length; i++) {
|
||||||
|
const part = pathParts[i]
|
||||||
|
// Remove square brackets at the start and end.
|
||||||
|
const isDynamicPart = isDynamicRoute(part)
|
||||||
|
const normalizedPart = (isDynamicPart
|
||||||
|
? part.replace(/^\[(\.{3})?/, '').replace(/\]$/, '')
|
||||||
|
: part
|
||||||
|
).toLowerCase()
|
||||||
|
|
||||||
|
route.name += route.name ? `-${normalizedPart}` : normalizedPart
|
||||||
|
|
||||||
|
const child = parent.find(
|
||||||
|
parentRoute => parentRoute.name === route.name
|
||||||
|
)
|
||||||
|
if (child) {
|
||||||
|
child.children = child.children || []
|
||||||
|
parent = child.children
|
||||||
|
route.path = ''
|
||||||
|
} else if (normalizedPart === 'index' && !route.path) {
|
||||||
|
route.path += '/'
|
||||||
|
} else if (normalizedPart !== 'index') {
|
||||||
|
if (isDynamicPart) {
|
||||||
|
route.path += `/:${normalizedPart}`
|
||||||
|
|
||||||
|
// Catch-all route
|
||||||
|
if (/^\[\.{3}/.test(part)) {
|
||||||
|
route.path += '(.*)'
|
||||||
|
} else if (i === pathParts.length - 1) {
|
||||||
|
route.path += '?'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
route.path += `/${normalizedPart}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.push(route)
|
||||||
|
}
|
||||||
|
|
||||||
|
return prepareRoutes(routes)
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareRoutes (routes: NuxtRoute[], hasParent = false) {
|
||||||
|
for (const route of routes) {
|
||||||
|
if (route.name) {
|
||||||
|
route.name = route.name.replace(/-index$/, '')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasParent) {
|
||||||
|
route.path = route.path.replace(/^\//, '').replace(/\?$/, '')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (route.children) {
|
||||||
|
delete route.name
|
||||||
|
route.children = prepareRoutes(route.children, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return routes
|
||||||
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { join, relative } from 'path'
|
import { join, relative } from 'path'
|
||||||
import fsExtra from 'fs-extra'
|
import fsExtra from 'fs-extra'
|
||||||
import consola from 'consola'
|
|
||||||
import { debounce } from 'lodash'
|
import { debounce } from 'lodash'
|
||||||
import { BundleBuilder } from 'src/webpack'
|
import { BundleBuilder } from 'src/webpack'
|
||||||
import { Nuxt } from '../core'
|
import { Nuxt } from '../core'
|
||||||
@ -16,11 +15,18 @@ import Ignore from './ignore'
|
|||||||
|
|
||||||
export class Builder {
|
export class Builder {
|
||||||
nuxt: Nuxt
|
nuxt: Nuxt
|
||||||
|
ignore: Ignore
|
||||||
app: NuxtApp
|
app: NuxtApp
|
||||||
templates: NuxtTemplate[]
|
templates: NuxtTemplate[]
|
||||||
|
|
||||||
constructor (nuxt) {
|
constructor (nuxt) {
|
||||||
this.nuxt = nuxt
|
this.nuxt = nuxt
|
||||||
|
this.ignore = new Ignore({
|
||||||
|
rootDir: nuxt.options.srcDir,
|
||||||
|
ignoreArray: nuxt.options.ignore.concat(
|
||||||
|
relative(nuxt.options.rootDir, nuxt.options.buildDir)
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
build () {
|
build () {
|
||||||
@ -42,46 +48,29 @@ async function build (builder: Builder) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function watch (builder: Builder) {
|
function watch (builder: Builder) {
|
||||||
const { nuxt } = builder
|
const { nuxt, ignore } = builder
|
||||||
const ignore = new Ignore({
|
|
||||||
rootDir: nuxt.options.srcDir,
|
|
||||||
ignoreArray: nuxt.options.ignore.concat(
|
|
||||||
relative(nuxt.options.rootDir, nuxt.options.buildDir)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Watch internal templates
|
// Watch internal templates
|
||||||
const options = nuxt.options.watchers.chokidar
|
const options = nuxt.options.watchers.chokidar
|
||||||
const nuxtAppWatcher = createWatcher(nuxt.options.appDir, options, ignore)
|
const nuxtAppWatcher = createWatcher(nuxt.options.appDir, { ...options, cwd: nuxt.options.appDir }, ignore)
|
||||||
nuxtAppWatcher.watchAll(async () => {
|
nuxtAppWatcher.watchAll(debounce(() => compileTemplates(builder.templates, nuxt.options.buildDir), 100))
|
||||||
consola.log('Re-generate templates')
|
|
||||||
await compileTemplates(builder.templates, nuxt.options.buildDir)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Watch user app
|
// Watch user app
|
||||||
const appWatcher = createWatcher(builder.app.srcDir, options, ignore)
|
const appPattern = `${builder.app.srcDir}/**/*.{${nuxt.options.extensions.join(',')}}`
|
||||||
// Watch for App.vue creation
|
const appWatcher = createWatcher(appPattern, { ...options, cwd: builder.app.srcDir }, ignore)
|
||||||
// appWatcher.debug('srcDir')
|
// appWatcher.debug('srcDir')
|
||||||
appWatcher.watch(
|
const refreshTemplates = debounce(() => generate(builder), 100)
|
||||||
/^(A|a)pp\.[a-z]{2,3}/,
|
// Watch for App.vue creation
|
||||||
debounce(({ event }) => {
|
appWatcher.watch(/^(A|a)pp\.[a-z]{2,3}/, refreshTemplates, ['add', 'unlink'])
|
||||||
if (['add', 'unlink'].includes(event)) {
|
|
||||||
generate(builder)
|
|
||||||
}
|
|
||||||
}, 50)
|
|
||||||
)
|
|
||||||
// Watch for page changes
|
// Watch for page changes
|
||||||
appWatcher.watch('pages/', async () => {
|
appWatcher.watch(new RegExp(`^${nuxt.options.dir.pages}/`), refreshTemplates, ['add', 'unlink'])
|
||||||
consola.log('Re-generate routes')
|
|
||||||
await compileTemplates(builder.templates, nuxt.options.buildDir)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function generate (builder: Builder) {
|
export async function generate (builder: Builder) {
|
||||||
const { nuxt } = builder
|
const { nuxt } = builder
|
||||||
|
|
||||||
await fsExtra.mkdirp(nuxt.options.buildDir)
|
await fsExtra.mkdirp(nuxt.options.buildDir)
|
||||||
builder.app = resolveApp(nuxt, nuxt.options.srcDir)
|
builder.app = await resolveApp(builder, nuxt.options.srcDir)
|
||||||
|
|
||||||
const templatesDir = join(builder.nuxt.options.appDir, '_templates')
|
const templatesDir = join(builder.nuxt.options.appDir, '_templates')
|
||||||
const appTemplates = await scanTemplates(templatesDir, templateData(builder))
|
const appTemplates = await scanTemplates(templatesDir, templateData(builder))
|
||||||
|
@ -4,15 +4,15 @@ import consola from 'consola'
|
|||||||
import Ignore from './ignore'
|
import Ignore from './ignore'
|
||||||
|
|
||||||
export function createWatcher (
|
export function createWatcher (
|
||||||
dir: string,
|
pattern: string,
|
||||||
options?: WatchOptions,
|
options?: WatchOptions,
|
||||||
ignore?: Ignore
|
ignore?: Ignore
|
||||||
) {
|
) {
|
||||||
const opts = defu({ cwd: dir }, options, {
|
const opts = defu(options, {
|
||||||
ignored: [],
|
ignored: [],
|
||||||
ignoreInitial: true
|
ignoreInitial: true
|
||||||
})
|
})
|
||||||
const watcher = chokidar.watch(dir, opts)
|
const watcher = chokidar.watch(pattern, opts)
|
||||||
const watchAll = (cb: Function, filter?: Function) => {
|
const watchAll = (cb: Function, filter?: Function) => {
|
||||||
watcher.on('all', (event, path: string) => {
|
watcher.on('all', (event, path: string) => {
|
||||||
if (ignore && ignore.ignores(path)) {
|
if (ignore && ignore.ignores(path)) {
|
||||||
@ -25,11 +25,11 @@ export function createWatcher (
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const watch = (pattern: string | RegExp, cb: Function) =>
|
const watch = (pattern: string | RegExp, cb: Function, events?: string[]) =>
|
||||||
watchAll(cb, e => e.path.match(pattern))
|
watchAll(cb, ({ event, path }) => path.match(pattern) && (!events || events.includes(event)))
|
||||||
|
|
||||||
const debug = (tag: string = '[Watcher]') => {
|
const debug = (tag: string = '[Watcher]') => {
|
||||||
consola.log(tag, 'Watching ', dir)
|
consola.log(tag, 'Watching ', pattern)
|
||||||
watchAll((e) => {
|
watchAll((e) => {
|
||||||
consola.log(tag, e.event, e.path)
|
consola.log(tag, e.event, e.path)
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user