Nuxt/packages/nuxt3/src/builder.ts

118 lines
3.3 KiB
TypeScript
Raw Normal View History

import { join, relative } from 'path'
2020-08-17 18:02:10 +00:00
import fsExtra from 'fs-extra'
import { debounce } from 'lodash'
import { DeterminedGlobals, determineGlobals } from '@nuxt/kit'
2021-03-29 09:33:38 +00:00
import { Nuxt } from './nuxt'
import {
templateData,
compileTemplates,
scanTemplates,
NuxtTemplate
} from './template'
2020-08-17 18:02:10 +00:00
import { createWatcher } from './watch'
2020-08-19 13:11:52 +00:00
import { createApp, NuxtApp } from './app'
2021-03-29 09:33:38 +00:00
import Ignore from './utils/ignore'
2020-07-02 13:02:35 +00:00
export class Builder {
2020-07-30 23:40:16 +00:00
nuxt: Nuxt
2020-10-01 10:11:15 +00:00
globals: DeterminedGlobals
2020-08-18 17:08:06 +00:00
ignore: Ignore
2020-08-17 18:02:10 +00:00
templates: NuxtTemplate[]
2020-10-01 10:11:15 +00:00
app: NuxtApp
2020-08-04 10:26:22 +00:00
constructor (nuxt) {
2020-07-02 13:02:35 +00:00
this.nuxt = nuxt
2020-10-01 10:11:15 +00:00
this.globals = determineGlobals(nuxt.options.globalName, nuxt.options.globals)
2020-08-18 17:08:06 +00:00
this.ignore = new Ignore({
rootDir: nuxt.options.srcDir,
ignoreArray: nuxt.options.ignore.concat(
relative(nuxt.options.rootDir, nuxt.options.buildDir)
)
})
2020-07-02 13:02:35 +00:00
}
build () {
return _build(this)
2020-07-02 13:02:35 +00:00
}
2020-10-01 10:11:15 +00:00
close () {
// TODO: close watchers
}
}
2020-07-02 13:02:35 +00:00
// Extends VueRouter
async function _build (builder: Builder) {
const { nuxt } = builder
2020-07-02 13:02:35 +00:00
await fsExtra.emptyDir(nuxt.options.buildDir)
2020-08-17 18:02:10 +00:00
await generate(builder)
if (nuxt.options.dev) {
watch(builder)
}
2020-07-02 13:02:35 +00:00
await bundle(builder)
2021-01-18 11:49:50 +00:00
await nuxt.callHook('build:done')
2020-07-02 13:02:35 +00:00
}
2020-08-17 18:45:32 +00:00
function watch (builder: Builder) {
2020-08-18 17:08:06 +00:00
const { nuxt, ignore } = builder
2020-08-17 18:02:10 +00:00
// Watch internal templates
const options = nuxt.options.watchers.chokidar
2020-08-18 17:08:06 +00:00
const nuxtAppWatcher = createWatcher(nuxt.options.appDir, { ...options, cwd: nuxt.options.appDir }, ignore)
nuxtAppWatcher.watchAll(debounce(() => compileTemplates(builder.templates, nuxt.options.buildDir), 100))
2020-08-17 18:02:10 +00:00
// Watch user app
// TODO: handle multiples app dirs
2020-08-19 13:11:52 +00:00
const appPattern = `${builder.app.dir}/**/*.{${nuxt.options.extensions.join(',')}}`
const appWatcher = createWatcher(appPattern, { ...options, cwd: builder.app.dir }, ignore)
// appWatcher.debug('srcDir')
2020-08-18 17:08:06 +00:00
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
2020-08-18 17:08:06 +00:00
appWatcher.watch(new RegExp(`^${nuxt.options.dir.pages}/`), refreshTemplates, ['add', 'unlink'])
// Watch for plugins changes
appWatcher.watch(/^plugins/, refreshTemplates, ['add', 'unlink'])
// Shared Watcher
const watchHookDebounced = debounce((event, file) => builder.nuxt.callHook('builder:watch', event, file), 100)
appWatcher.watchAll(watchHookDebounced)
nuxtAppWatcher.watchAll(watchHookDebounced)
2020-08-17 18:02:10 +00:00
}
2020-08-17 18:45:32 +00:00
export async function generate (builder: Builder) {
2020-08-17 18:02:10 +00:00
const { nuxt } = builder
2020-08-19 13:11:52 +00:00
builder.app = await createApp(builder)
// Todo: Call app:created hook
2020-08-17 18:02:10 +00:00
const templatesDir = join(builder.nuxt.options.appDir, '_templates')
const appTemplates = await scanTemplates(templatesDir, templateData(builder))
// Todo: Call app:templates hook
2020-08-17 18:02:10 +00:00
builder.templates = [...appTemplates]
2020-08-17 18:02:10 +00:00
await compileTemplates(builder.templates, nuxt.options.buildDir)
}
async function bundle ({ nuxt }: Builder) {
// @ts-ignore
const useVite = !!nuxt.options.vite
const bundle = await (useVite
? import('./vite/vite' /* webpackChunkName: "vite" */)
: import('./webpack/webpack' /* webpackChunkName: "webpack" */))
.then(p => p.bundle)
return bundle(nuxt)
}
export function getBuilder (nuxt: Nuxt) {
return new Builder(nuxt)
}
export function build (nuxt: Nuxt) {
return getBuilder(nuxt).build()
}