2021-04-29 11:51:54 +00:00
|
|
|
import { join, relative, resolve } from 'upath'
|
2020-08-17 18:02:10 +00:00
|
|
|
import fsExtra from 'fs-extra'
|
2020-08-18 12:27:51 +00:00
|
|
|
import { debounce } from 'lodash'
|
2021-04-02 11:47:01 +00:00
|
|
|
import { Nuxt } from '@nuxt/kit'
|
|
|
|
|
2020-08-18 12:27:51 +00:00
|
|
|
import {
|
|
|
|
templateData,
|
|
|
|
compileTemplates,
|
|
|
|
scanTemplates,
|
|
|
|
NuxtTemplate
|
|
|
|
} from './template'
|
2021-04-04 22:15:34 +00:00
|
|
|
import { createWatcher, WatchCallback } 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
|
|
|
|
2020-08-17 15:25:06 +00:00
|
|
|
export class Builder {
|
2020-07-30 23:40:16 +00:00
|
|
|
nuxt: Nuxt
|
2021-04-02 11:47:01 +00:00
|
|
|
globals: any
|
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
|
|
|
|
2021-04-04 22:15:34 +00:00
|
|
|
constructor (nuxt: Nuxt) {
|
2020-07-02 13:02:35 +00:00
|
|
|
this.nuxt = nuxt
|
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
|
|
|
}
|
|
|
|
|
2020-08-17 15:25:06 +00:00
|
|
|
build () {
|
2021-03-28 21:12:16 +00:00
|
|
|
return _build(this)
|
2020-07-02 13:02:35 +00:00
|
|
|
}
|
2020-10-01 10:11:15 +00:00
|
|
|
|
|
|
|
close () {
|
|
|
|
// TODO: close watchers
|
|
|
|
}
|
2020-08-17 15:25:06 +00:00
|
|
|
}
|
2020-07-02 13:02:35 +00:00
|
|
|
|
2020-08-17 15:25:06 +00:00
|
|
|
// Extends VueRouter
|
2021-03-28 21:12:16 +00:00
|
|
|
async function _build (builder: Builder) {
|
2020-08-17 15:25:06 +00:00
|
|
|
const { nuxt } = builder
|
2020-07-02 13:02:35 +00:00
|
|
|
|
2021-04-15 19:17:44 +00:00
|
|
|
if (!nuxt.options.dev) {
|
|
|
|
await fsExtra.emptyDir(nuxt.options.buildDir)
|
|
|
|
}
|
2021-04-29 11:51:54 +00:00
|
|
|
await fsExtra.emptyDir(resolve(nuxt.options.buildDir, 'dist'))
|
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
|
|
|
|
2020-08-17 15:25:06 +00:00
|
|
|
await bundle(builder)
|
2021-01-18 11:49:50 +00:00
|
|
|
|
2021-04-02 11:47:01 +00:00
|
|
|
await nuxt.callHook('build:done', builder)
|
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
|
2020-08-18 12:27:51 +00:00
|
|
|
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
|
2021-02-19 01:08:45 +00:00
|
|
|
// TODO: handle multiples app dirs
|
2021-04-04 22:15:34 +00:00
|
|
|
const appPattern = `${builder.app.dir}/**/*{${nuxt.options.extensions.join(',')}}`
|
2020-08-19 13:11:52 +00:00
|
|
|
const appWatcher = createWatcher(appPattern, { ...options, cwd: builder.app.dir }, ignore)
|
2020-08-18 12:27:51 +00:00
|
|
|
// 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'])
|
2020-08-18 12:27:51 +00:00
|
|
|
// Watch for page changes
|
2020-08-18 17:08:06 +00:00
|
|
|
appWatcher.watch(new RegExp(`^${nuxt.options.dir.pages}/`), refreshTemplates, ['add', 'unlink'])
|
2021-02-19 01:08:45 +00:00
|
|
|
// Watch for plugins changes
|
|
|
|
appWatcher.watch(/^plugins/, refreshTemplates, ['add', 'unlink'])
|
2021-01-22 22:02:33 +00:00
|
|
|
|
|
|
|
// Shared Watcher
|
2021-04-04 22:15:34 +00:00
|
|
|
const watchHook: WatchCallback = (event, path) => builder.nuxt.callHook('builder:watch', event, path)
|
|
|
|
const watchHookDebounced = debounce(watchHook, 100)
|
2021-01-22 22:02:33 +00:00
|
|
|
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)
|
2021-02-19 01:08:45 +00:00
|
|
|
// Todo: Call app:created hook
|
2020-08-17 18:02:10 +00:00
|
|
|
|
|
|
|
const templatesDir = join(builder.nuxt.options.appDir, '_templates')
|
2020-08-18 12:27:51 +00:00
|
|
|
const appTemplates = await scanTemplates(templatesDir, templateData(builder))
|
2021-02-19 01:08:45 +00:00
|
|
|
// Todo: Call app:templates hook
|
2020-08-17 18:02:10 +00:00
|
|
|
|
2020-08-18 12:27:51 +00:00
|
|
|
builder.templates = [...appTemplates]
|
2020-08-17 18:02:10 +00:00
|
|
|
|
|
|
|
await compileTemplates(builder.templates, nuxt.options.buildDir)
|
|
|
|
}
|
|
|
|
|
2020-08-17 15:25:06 +00:00
|
|
|
async function bundle ({ nuxt }: Builder) {
|
2021-01-22 22:02:33 +00:00
|
|
|
// @ts-ignore
|
|
|
|
const useVite = !!nuxt.options.vite
|
2021-04-03 13:38:07 +00:00
|
|
|
const { bundle } = await (useVite ? import('@nuxt/vite-builder') : import('@nuxt/webpack-builder'))
|
2021-01-22 22:02:33 +00:00
|
|
|
return bundle(nuxt)
|
2020-08-17 15:25:06 +00:00
|
|
|
}
|
2021-03-28 21:12:16 +00:00
|
|
|
|
|
|
|
export function getBuilder (nuxt: Nuxt) {
|
|
|
|
return new Builder(nuxt)
|
|
|
|
}
|
|
|
|
|
|
|
|
export function build (nuxt: Nuxt) {
|
|
|
|
return getBuilder(nuxt).build()
|
|
|
|
}
|