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 globby from 'globby'
|
||||
import { Builder } from './builder'
|
||||
|
||||
export interface NuxtRoute {
|
||||
path: ''
|
||||
name?: string
|
||||
path: string
|
||||
component: string
|
||||
children?: NuxtRoute[]
|
||||
}
|
||||
|
||||
export interface NuxtApp {
|
||||
@ -11,12 +16,18 @@ export interface NuxtApp {
|
||||
}
|
||||
|
||||
// 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
|
||||
const main = nuxt.resolver.tryResolvePath('~/App') ||
|
||||
nuxt.resolver.tryResolvePath('~/app') ||
|
||||
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: Detect store
|
||||
// Use hooks?
|
||||
@ -32,3 +43,97 @@ export function resolveApp (nuxt, srcDir: string): NuxtApp {
|
||||
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 fsExtra from 'fs-extra'
|
||||
import consola from 'consola'
|
||||
import { debounce } from 'lodash'
|
||||
import { BundleBuilder } from 'src/webpack'
|
||||
import { Nuxt } from '../core'
|
||||
@ -16,11 +15,18 @@ import Ignore from './ignore'
|
||||
|
||||
export class Builder {
|
||||
nuxt: Nuxt
|
||||
ignore: Ignore
|
||||
app: NuxtApp
|
||||
templates: NuxtTemplate[]
|
||||
|
||||
constructor (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 () {
|
||||
@ -42,46 +48,29 @@ async function build (builder: Builder) {
|
||||
}
|
||||
|
||||
function watch (builder: Builder) {
|
||||
const { nuxt } = builder
|
||||
const ignore = new Ignore({
|
||||
rootDir: nuxt.options.srcDir,
|
||||
ignoreArray: nuxt.options.ignore.concat(
|
||||
relative(nuxt.options.rootDir, nuxt.options.buildDir)
|
||||
)
|
||||
})
|
||||
const { nuxt, ignore } = builder
|
||||
|
||||
// Watch internal templates
|
||||
const options = nuxt.options.watchers.chokidar
|
||||
const nuxtAppWatcher = createWatcher(nuxt.options.appDir, options, ignore)
|
||||
nuxtAppWatcher.watchAll(async () => {
|
||||
consola.log('Re-generate templates')
|
||||
await compileTemplates(builder.templates, nuxt.options.buildDir)
|
||||
})
|
||||
const nuxtAppWatcher = createWatcher(nuxt.options.appDir, { ...options, cwd: nuxt.options.appDir }, ignore)
|
||||
nuxtAppWatcher.watchAll(debounce(() => compileTemplates(builder.templates, nuxt.options.buildDir), 100))
|
||||
|
||||
// Watch user app
|
||||
const appWatcher = createWatcher(builder.app.srcDir, options, ignore)
|
||||
// Watch for App.vue creation
|
||||
const appPattern = `${builder.app.srcDir}/**/*.{${nuxt.options.extensions.join(',')}}`
|
||||
const appWatcher = createWatcher(appPattern, { ...options, cwd: builder.app.srcDir }, ignore)
|
||||
// appWatcher.debug('srcDir')
|
||||
appWatcher.watch(
|
||||
/^(A|a)pp\.[a-z]{2,3}/,
|
||||
debounce(({ event }) => {
|
||||
if (['add', 'unlink'].includes(event)) {
|
||||
generate(builder)
|
||||
}
|
||||
}, 50)
|
||||
)
|
||||
const refreshTemplates = debounce(() => generate(builder), 100)
|
||||
// Watch for App.vue creation
|
||||
appWatcher.watch(/^(A|a)pp\.[a-z]{2,3}/, refreshTemplates, ['add', 'unlink'])
|
||||
// Watch for page changes
|
||||
appWatcher.watch('pages/', async () => {
|
||||
consola.log('Re-generate routes')
|
||||
await compileTemplates(builder.templates, nuxt.options.buildDir)
|
||||
})
|
||||
appWatcher.watch(new RegExp(`^${nuxt.options.dir.pages}/`), refreshTemplates, ['add', 'unlink'])
|
||||
}
|
||||
|
||||
export async function generate (builder: Builder) {
|
||||
const { nuxt } = builder
|
||||
|
||||
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 appTemplates = await scanTemplates(templatesDir, templateData(builder))
|
||||
|
@ -4,15 +4,15 @@ import consola from 'consola'
|
||||
import Ignore from './ignore'
|
||||
|
||||
export function createWatcher (
|
||||
dir: string,
|
||||
pattern: string,
|
||||
options?: WatchOptions,
|
||||
ignore?: Ignore
|
||||
) {
|
||||
const opts = defu({ cwd: dir }, options, {
|
||||
const opts = defu(options, {
|
||||
ignored: [],
|
||||
ignoreInitial: true
|
||||
})
|
||||
const watcher = chokidar.watch(dir, opts)
|
||||
const watcher = chokidar.watch(pattern, opts)
|
||||
const watchAll = (cb: Function, filter?: Function) => {
|
||||
watcher.on('all', (event, path: string) => {
|
||||
if (ignore && ignore.ignores(path)) {
|
||||
@ -25,11 +25,11 @@ export function createWatcher (
|
||||
})
|
||||
}
|
||||
|
||||
const watch = (pattern: string | RegExp, cb: Function) =>
|
||||
watchAll(cb, e => e.path.match(pattern))
|
||||
const watch = (pattern: string | RegExp, cb: Function, events?: string[]) =>
|
||||
watchAll(cb, ({ event, path }) => path.match(pattern) && (!events || events.includes(event)))
|
||||
|
||||
const debug = (tag: string = '[Watcher]') => {
|
||||
consola.log(tag, 'Watching ', dir)
|
||||
consola.log(tag, 'Watching ', pattern)
|
||||
watchAll((e) => {
|
||||
consola.log(tag, e.event, e.path)
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user