mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-13 09:33:54 +00:00
chore: wip
This commit is contained in:
parent
daaa8eda8c
commit
dc84429d67
@ -1,4 +1,5 @@
|
|||||||
import { resolve } from 'path'
|
import { resolve } from 'path'
|
||||||
|
import { createWatcher } from './watch'
|
||||||
|
|
||||||
export interface NuxtRoute {
|
export interface NuxtRoute {
|
||||||
path: ''
|
path: ''
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
|
import { join } from 'path'
|
||||||
|
import fsExtra from 'fs-extra'
|
||||||
import { BundleBuilder } from 'src/webpack'
|
import { BundleBuilder } from 'src/webpack'
|
||||||
import { Nuxt } from '../core'
|
import { Nuxt } from '../core'
|
||||||
import { copyTemplates } from './template'
|
import { compileTemplates, scanTemplates, NuxtTemplate } from './template'
|
||||||
|
import { createWatcher } from './watch'
|
||||||
import { resolveApp, NuxtApp } from './app'
|
import { resolveApp, NuxtApp } from './app'
|
||||||
|
|
||||||
export class Builder {
|
export class Builder {
|
||||||
nuxt: Nuxt
|
nuxt: Nuxt
|
||||||
app: NuxtApp
|
app: NuxtApp
|
||||||
|
templates: NuxtTemplate[]
|
||||||
|
|
||||||
constructor (nuxt) {
|
constructor (nuxt) {
|
||||||
this.nuxt = nuxt
|
this.nuxt = nuxt
|
||||||
@ -17,15 +21,64 @@ export class Builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Extends VueRouter
|
// Extends VueRouter
|
||||||
async function build (builder: Builder) {
|
async function build(builder: Builder) {
|
||||||
const { nuxt } = builder
|
const { nuxt } = builder
|
||||||
|
|
||||||
builder.app = resolveApp(nuxt, nuxt.options.srcDir)
|
await generate(builder)
|
||||||
await copyTemplates(builder)
|
|
||||||
|
if (nuxt.options.dev) {
|
||||||
|
watch(builder)
|
||||||
|
}
|
||||||
|
|
||||||
await bundle(builder)
|
await bundle(builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function watch(builder: Builder) {
|
||||||
|
const { nuxt } = builder
|
||||||
|
|
||||||
|
// Watch internal templates
|
||||||
|
const nuxtAppWatcher = createWatcher(nuxt.options.appDir)
|
||||||
|
// nuxtAppWatcher.debug()
|
||||||
|
nuxtAppWatcher.watchAll(async () => {
|
||||||
|
console.log('Re-generate templates')
|
||||||
|
await compileTemplates(builder.templates, nuxt.options.buildDir)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Watch user app
|
||||||
|
const appWatcher = createWatcher(builder.app.srcDir, {
|
||||||
|
ignored: [
|
||||||
|
nuxt.options.buildDir
|
||||||
|
]
|
||||||
|
})
|
||||||
|
// appWatcher.debug()
|
||||||
|
appWatcher.watch(/(A|a)pp\.[a-z]{2,3}/, async () => {
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 200))
|
||||||
|
await generate(builder)
|
||||||
|
})
|
||||||
|
appWatcher.watch('pages/', async () => {
|
||||||
|
console.log('Re-generate routes')
|
||||||
|
await compileTemplates(builder.templates, nuxt.options.buildDir)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function generate(builder: Builder) {
|
||||||
|
const { nuxt } = builder
|
||||||
|
|
||||||
|
await fsExtra.mkdirp(nuxt.options.buildDir)
|
||||||
|
builder.app = resolveApp(nuxt, nuxt.options.srcDir)
|
||||||
|
|
||||||
|
const templatesDir = join(builder.nuxt.options.appDir, '_templates')
|
||||||
|
const appTemplates = await scanTemplates(templatesDir, {
|
||||||
|
app: builder.app
|
||||||
|
})
|
||||||
|
|
||||||
|
builder.templates = [
|
||||||
|
...appTemplates
|
||||||
|
]
|
||||||
|
|
||||||
|
await compileTemplates(builder.templates, nuxt.options.buildDir)
|
||||||
|
}
|
||||||
|
|
||||||
async function bundle ({ nuxt }: Builder) {
|
async function bundle ({ nuxt }: Builder) {
|
||||||
// TODO: get rid of this context and directly pass nuxt to BundleBuilder
|
// TODO: get rid of this context and directly pass nuxt to BundleBuilder
|
||||||
const bundleBuilder = new BundleBuilder({
|
const bundleBuilder = new BundleBuilder({
|
||||||
|
@ -1,26 +1,40 @@
|
|||||||
import { resolve, join, sep } from 'path'
|
import { join, relative, dirname } from 'path'
|
||||||
import fsExtra from 'fs-extra'
|
import fsExtra from 'fs-extra'
|
||||||
import globby from 'globby'
|
import globby from 'globby'
|
||||||
import lodashTemplate from 'lodash/template'
|
import lodashTemplate from 'lodash/template'
|
||||||
import { Builder } from './builder'
|
|
||||||
|
|
||||||
export async function copyTemplates ({ nuxt, app }: Builder) {
|
interface NuxtTemplate {
|
||||||
// Resolve appDir
|
src: string // Absolute path to source file
|
||||||
const templatesDir = join(nuxt.options.appDir, '_templates')
|
path: string // Relative path of destination
|
||||||
|
data?: any
|
||||||
const templateFiles = (await globby(join(templatesDir, '/**')))
|
}
|
||||||
.map(f => f.replace(templatesDir + sep, ''))
|
|
||||||
|
async function compileTemplate({ src, path, data }: NuxtTemplate, destDir: string) {
|
||||||
await fsExtra.mkdirp(nuxt.options.buildDir)
|
const srcContents = await fsExtra.readFile(src, 'utf-8')
|
||||||
|
const compiledSrc = lodashTemplate(srcContents, {})(data)
|
||||||
for (const template of templateFiles) {
|
const dest = join(destDir, path)
|
||||||
const src = resolve(templatesDir, template)
|
console.log('Compile template', dest)
|
||||||
const dst = resolve(nuxt.options.buildDir, template)
|
await fsExtra.mkdirp(dirname(dest))
|
||||||
|
await fsExtra.writeFile(dest, compiledSrc)
|
||||||
const templateData = { app: Object.freeze(app) }
|
}
|
||||||
const srcContents = await fsExtra.readFile(src, 'utf-8')
|
|
||||||
const compiledSrc = lodashTemplate(srcContents, {})(templateData)
|
export async function compileTemplates(templates: NuxtTemplate[], destDir: string) {
|
||||||
|
return Promise.all(templates.map(t => compileTemplate(t, destDir)))
|
||||||
await fsExtra.writeFile(dst, compiledSrc)
|
}
|
||||||
}
|
|
||||||
|
export async function scanTemplates (dir: string, data?: Object) {
|
||||||
|
const templateFiles = (await globby(join(dir, '/**')))
|
||||||
|
|
||||||
|
return templateFiles.map(src => ({
|
||||||
|
src,
|
||||||
|
path: relative(dir, src),
|
||||||
|
data
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function watchTemplate(template: NuxtTemplate, watcher: any, cb: Function) {
|
||||||
|
template.data = new Proxy(template.data, {
|
||||||
|
// TODO: deep watch option changes
|
||||||
|
})
|
||||||
|
// TODO: Watch fs changes
|
||||||
}
|
}
|
||||||
|
40
packages/nuxt3/src/builder/watch.ts
Normal file
40
packages/nuxt3/src/builder/watch.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import chokidar, { WatchOptions } from 'chokidar'
|
||||||
|
import { relative } from 'path'
|
||||||
|
|
||||||
|
export function createWatcher(dir: string|string[], options?: WatchOptions) {
|
||||||
|
const watcher = chokidar.watch(dir, {
|
||||||
|
ignored: [],
|
||||||
|
ignoreInitial: true,
|
||||||
|
...options
|
||||||
|
})
|
||||||
|
|
||||||
|
const watchAll = (cb: Function, filter?: Function) => {
|
||||||
|
watcher.on('raw', (event, path: string, details) => {
|
||||||
|
if (options.ignored.find(ignore => path.match(ignore))) {
|
||||||
|
return // 🖕 chokidar ignored option
|
||||||
|
}
|
||||||
|
path = relative(dir, path)
|
||||||
|
const _event = { event, path }
|
||||||
|
if (!filter || filter(_event)) {
|
||||||
|
cb(_event)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const watch = (pattern: string| RegExp, cb: Function) => watchAll(cb, e => e.path.match(pattern))
|
||||||
|
|
||||||
|
const debug = (tag: string = '[Watcher]') => {
|
||||||
|
console.log(tag, 'Watching ', dir)
|
||||||
|
watchAll((e) => {
|
||||||
|
console.log(tag, e.event, e.path)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
watchAll,
|
||||||
|
watch,
|
||||||
|
debug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Watcher = ReturnType<typeof createWatcher>
|
@ -4,7 +4,8 @@ import TimeFixPlugin from 'time-fix-plugin'
|
|||||||
import cloneDeep from 'lodash/cloneDeep'
|
import cloneDeep from 'lodash/cloneDeep'
|
||||||
import escapeRegExp from 'lodash/escapeRegExp'
|
import escapeRegExp from 'lodash/escapeRegExp'
|
||||||
import VueLoaderPlugin from 'vue-loader/dist/pluginWebpack5'
|
import VueLoaderPlugin from 'vue-loader/dist/pluginWebpack5'
|
||||||
import ExtractCssChunksPlugin from 'extract-css-chunks-webpack-plugin'
|
// import ExtractCssChunksPlugin from 'extract-css-chunks-webpack-plugin'
|
||||||
|
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
|
||||||
import TerserWebpackPlugin from 'terser-webpack-plugin'
|
import TerserWebpackPlugin from 'terser-webpack-plugin'
|
||||||
import WebpackBar from 'webpackbar'
|
import WebpackBar from 'webpackbar'
|
||||||
import env from 'std-env'
|
import env from 'std-env'
|
||||||
@ -398,7 +399,7 @@ export default class WebpackBaseConfig {
|
|||||||
|
|
||||||
// CSS extraction)
|
// CSS extraction)
|
||||||
if (buildOptions.extractCSS) {
|
if (buildOptions.extractCSS) {
|
||||||
plugins.push(new ExtractCssChunksPlugin(Object.assign({
|
plugins.push(new MiniCssExtractPlugin(Object.assign({
|
||||||
filename: this.getFileName('css'),
|
filename: this.getFileName('css'),
|
||||||
chunkFilename: this.getFileName('css')
|
chunkFilename: this.getFileName('css')
|
||||||
}, buildOptions.extractCSS)))
|
}, buildOptions.extractCSS)))
|
||||||
@ -446,7 +447,7 @@ export default class WebpackBaseConfig {
|
|||||||
|
|
||||||
// CSS extraction
|
// CSS extraction
|
||||||
if (this.buildContext.buildOptions.extractCSS) {
|
if (this.buildContext.buildOptions.extractCSS) {
|
||||||
plugins.push(new ExtractCssChunksPlugin(Object.assign({
|
plugins.push(new MiniCssExtractPlugin(Object.assign({
|
||||||
filename: this.getFileName('css'),
|
filename: this.getFileName('css'),
|
||||||
chunkFilename: this.getFileName('css'),
|
chunkFilename: this.getFileName('css'),
|
||||||
// TODO: https://github.com/faceyspacey/extract-css-chunks-webpack-plugin/issues/132
|
// TODO: https://github.com/faceyspacey/extract-css-chunks-webpack-plugin/issues/132
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
import ExtractCssChunksPlugin from 'extract-css-chunks-webpack-plugin'
|
// import ExtractCssChunksPlugin from 'extract-css-chunks-webpack-plugin'
|
||||||
|
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
|
||||||
|
|
||||||
import { wrapArray } from 'src/utils'
|
import { wrapArray } from 'src/utils'
|
||||||
|
|
||||||
@ -20,8 +21,9 @@ export default class StyleLoader {
|
|||||||
return this.buildContext.buildOptions.extractCSS
|
return this.buildContext.buildOptions.extractCSS
|
||||||
}
|
}
|
||||||
|
|
||||||
get onlyLocals () {
|
get onlyLocals() {
|
||||||
return Boolean(this.isServer && this.extractCSS)
|
// Not supported anymore by css-loader
|
||||||
|
return false // Boolean(this.isServer && this.extractCSS)
|
||||||
}
|
}
|
||||||
|
|
||||||
normalize (loaders) {
|
normalize (loaders) {
|
||||||
@ -86,7 +88,7 @@ export default class StyleLoader {
|
|||||||
if (this.extractCSS) {
|
if (this.extractCSS) {
|
||||||
const isDev = this.buildContext.options.dev
|
const isDev = this.buildContext.options.dev
|
||||||
return {
|
return {
|
||||||
loader: ExtractCssChunksPlugin.loader,
|
loader: MiniCssExtractPlugin.loader,
|
||||||
options: {
|
options: {
|
||||||
// TODO: https://github.com/faceyspacey/extract-css-chunks-webpack-plugin/issues/132
|
// TODO: https://github.com/faceyspacey/extract-css-chunks-webpack-plugin/issues/132
|
||||||
// https://github.com/faceyspacey/extract-css-chunks-webpack-plugin/issues/161#issuecomment-500162574
|
// https://github.com/faceyspacey/extract-css-chunks-webpack-plugin/issues/161#issuecomment-500162574
|
||||||
|
Loading…
Reference in New Issue
Block a user