chore: wip

This commit is contained in:
Sébastien Chopin 2020-08-17 20:02:10 +02:00
parent daaa8eda8c
commit dc84429d67
6 changed files with 143 additions and 32 deletions

View File

@ -1,4 +1,5 @@
import { resolve } from 'path'
import { createWatcher } from './watch'
export interface NuxtRoute {
path: ''

View File

@ -1,11 +1,15 @@
import { join } from 'path'
import fsExtra from 'fs-extra'
import { BundleBuilder } from 'src/webpack'
import { Nuxt } from '../core'
import { copyTemplates } from './template'
import { compileTemplates, scanTemplates, NuxtTemplate } from './template'
import { createWatcher } from './watch'
import { resolveApp, NuxtApp } from './app'
export class Builder {
nuxt: Nuxt
app: NuxtApp
templates: NuxtTemplate[]
constructor (nuxt) {
this.nuxt = nuxt
@ -17,15 +21,64 @@ export class Builder {
}
// Extends VueRouter
async function build (builder: Builder) {
async function build(builder: Builder) {
const { nuxt } = builder
builder.app = resolveApp(nuxt, nuxt.options.srcDir)
await copyTemplates(builder)
await generate(builder)
if (nuxt.options.dev) {
watch(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) {
// TODO: get rid of this context and directly pass nuxt to BundleBuilder
const bundleBuilder = new BundleBuilder({

View File

@ -1,26 +1,40 @@
import { resolve, join, sep } from 'path'
import { join, relative, dirname } from 'path'
import fsExtra from 'fs-extra'
import globby from 'globby'
import lodashTemplate from 'lodash/template'
import { Builder } from './builder'
export async function copyTemplates ({ nuxt, app }: Builder) {
// Resolve appDir
const templatesDir = join(nuxt.options.appDir, '_templates')
const templateFiles = (await globby(join(templatesDir, '/**')))
.map(f => f.replace(templatesDir + sep, ''))
await fsExtra.mkdirp(nuxt.options.buildDir)
for (const template of templateFiles) {
const src = resolve(templatesDir, template)
const dst = resolve(nuxt.options.buildDir, template)
const templateData = { app: Object.freeze(app) }
const srcContents = await fsExtra.readFile(src, 'utf-8')
const compiledSrc = lodashTemplate(srcContents, {})(templateData)
await fsExtra.writeFile(dst, compiledSrc)
}
interface NuxtTemplate {
src: string // Absolute path to source file
path: string // Relative path of destination
data?: any
}
async function compileTemplate({ src, path, data }: NuxtTemplate, destDir: string) {
const srcContents = await fsExtra.readFile(src, 'utf-8')
const compiledSrc = lodashTemplate(srcContents, {})(data)
const dest = join(destDir, path)
console.log('Compile template', dest)
await fsExtra.mkdirp(dirname(dest))
await fsExtra.writeFile(dest, compiledSrc)
}
export async function compileTemplates(templates: NuxtTemplate[], destDir: string) {
return Promise.all(templates.map(t => compileTemplate(t, destDir)))
}
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
}

View 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>

View File

@ -4,7 +4,8 @@ import TimeFixPlugin from 'time-fix-plugin'
import cloneDeep from 'lodash/cloneDeep'
import escapeRegExp from 'lodash/escapeRegExp'
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 WebpackBar from 'webpackbar'
import env from 'std-env'
@ -398,7 +399,7 @@ export default class WebpackBaseConfig {
// CSS extraction)
if (buildOptions.extractCSS) {
plugins.push(new ExtractCssChunksPlugin(Object.assign({
plugins.push(new MiniCssExtractPlugin(Object.assign({
filename: this.getFileName('css'),
chunkFilename: this.getFileName('css')
}, buildOptions.extractCSS)))
@ -446,7 +447,7 @@ export default class WebpackBaseConfig {
// CSS extraction
if (this.buildContext.buildOptions.extractCSS) {
plugins.push(new ExtractCssChunksPlugin(Object.assign({
plugins.push(new MiniCssExtractPlugin(Object.assign({
filename: this.getFileName('css'),
chunkFilename: this.getFileName('css'),
// TODO: https://github.com/faceyspacey/extract-css-chunks-webpack-plugin/issues/132

View File

@ -1,5 +1,6 @@
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'
@ -20,8 +21,9 @@ export default class StyleLoader {
return this.buildContext.buildOptions.extractCSS
}
get onlyLocals () {
return Boolean(this.isServer && this.extractCSS)
get onlyLocals() {
// Not supported anymore by css-loader
return false // Boolean(this.isServer && this.extractCSS)
}
normalize (loaders) {
@ -86,7 +88,7 @@ export default class StyleLoader {
if (this.extractCSS) {
const isDev = this.buildContext.options.dev
return {
loader: ExtractCssChunksPlugin.loader,
loader: MiniCssExtractPlugin.loader,
options: {
// 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