From c93ea7691ee2c696bef29585326b767ed48746f4 Mon Sep 17 00:00:00 2001 From: Alice Gaudon Date: Wed, 28 Apr 2021 14:07:11 +0200 Subject: [PATCH] ViewEngine: demote buildDir and publicDir fields --- src/components/FrontendToolsComponent.ts | 14 ++++------ src/frontend/SvelteViewEngine.ts | 33 ++++++++++++++++-------- src/frontend/ViewEngine.ts | 32 ++++++++--------------- 3 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/components/FrontendToolsComponent.ts b/src/components/FrontendToolsComponent.ts index f962ce0..fb81432 100644 --- a/src/components/FrontendToolsComponent.ts +++ b/src/components/FrontendToolsComponent.ts @@ -12,6 +12,7 @@ export default class FrontendToolsComponent extends ApplicationComponent { private readonly publicAssetsCache: FileCache = new FileCache(); public constructor( + private readonly publicAssetsDir: string, private readonly viewEngine: ViewEngine, ) { super(); @@ -20,9 +21,9 @@ export default class FrontendToolsComponent extends ApplicationComponent { public async start(app: Express): Promise { // Cache public assets if (config.get('asset_cache')) { - logger.info('Caching assets from', this.viewEngine.getPublicDir(), '...'); + logger.info('Caching assets from', this.publicAssetsDir, '...'); await readdirRecursively( - this.viewEngine.getPublicDir(), + this.publicAssetsDir, async file => await this.publicAssetsCache.load(file), ); } else { @@ -30,12 +31,7 @@ export default class FrontendToolsComponent extends ApplicationComponent { } // Setup express view engine - app.engine(this.viewEngine.getExtension(), (path, options, callback) => { - this.viewEngine.render(path, options as Record, callback) - .catch(err => callback(err)); - }); - app.set('views', this.viewEngine.getViewPaths()); - app.set('view engine', 'svelte'); + this.viewEngine.setup(app, true); } public async stop(): Promise { @@ -45,7 +41,7 @@ export default class FrontendToolsComponent extends ApplicationComponent { public async handle(router: Router): Promise { router.use((req, res, next) => { res.locals.inlineAsset = (urlPath: string) => { - return this.publicAssetsCache.getOrFail(path.join(this.viewEngine.getPublicDir(), urlPath)); + return this.publicAssetsCache.getOrFail(path.join(this.publicAssetsDir, urlPath)); }; next(); diff --git a/src/frontend/SvelteViewEngine.ts b/src/frontend/SvelteViewEngine.ts index 246f98d..4f52ca8 100644 --- a/src/frontend/SvelteViewEngine.ts +++ b/src/frontend/SvelteViewEngine.ts @@ -10,6 +10,7 @@ import {sveltePreprocess} from "svelte-preprocess/dist/autoProcess"; import requireFromString from "require-from-string"; import {CssResult} from "svelte/types/compiler/interfaces"; import * as child_process from "child_process"; +import fs from "fs"; const BACKEND_CODE_PREFIX = 'swaf.'; const COMPILED_SVELTE_EXTENSION = '.swafview'; @@ -33,13 +34,23 @@ export default class SvelteViewEngine extends ViewEngine { private rollup?: child_process.ChildProcess; + /** + * @param buildDir A temporary directory that will contain any non-final or final non-public asset. + * @param publicDir The output directory that should contain all final and public assets. + * @param devWatchedViewDir see {@link ViewEngine}. + * @param additionalViewPaths see {@link ViewEngine}. + */ public constructor( - buildDir: string, - publicDir: string, - devWatchedViewPath: string, + private readonly buildDir: string, + private readonly publicDir: string, + devWatchedViewDir: string, ...additionalViewPaths: string[] ) { - super(buildDir, publicDir, devWatchedViewPath, ...additionalViewPaths); + super(devWatchedViewDir, ...additionalViewPaths); + + if (!fs.existsSync(this.buildDir)) { + fs.mkdirSync(this.buildDir, {recursive: true}); + } } public getExtension(): string { @@ -57,7 +68,7 @@ export default class SvelteViewEngine extends ViewEngine { const canonicalViewName = this.toCanonicalName(file); // View - const actualFile = path.join(this.getBuildDir(), canonicalViewName + COMPILED_SVELTE_EXTENSION); + const actualFile = path.join(this.buildDir, canonicalViewName + COMPILED_SVELTE_EXTENSION); const view = await this.fileCache.get(actualFile, !config.get('view.cache')); // Root template @@ -139,7 +150,7 @@ export default class SvelteViewEngine extends ViewEngine { public async preCompile(canonicalName: string, alsoCompileDependents: boolean): Promise { const file = await this.resolveFileFromCanonicalName(canonicalName); - const intermediateFile = path.join(this.getBuildDir(), canonicalName); + const intermediateFile = path.join(this.buildDir, canonicalName); logger.info(canonicalName + ' > ', 'Pre-compiling', file, '->', intermediateFile); const source = await this.fileCache.get(file, !config.get('view.cache')); @@ -163,7 +174,7 @@ export default class SvelteViewEngine extends ViewEngine { ssr.css.code, ].join(separator); - const swafViewFile = path.join(this.getBuildDir(), canonicalName + COMPILED_SVELTE_EXTENSION); + const swafViewFile = path.join(this.buildDir, canonicalName + COMPILED_SVELTE_EXTENSION); await afs.mkdir(path.dirname(swafViewFile), {recursive: true}); await afs.writeFile(swafViewFile, finalCode); @@ -208,7 +219,7 @@ export default class SvelteViewEngine extends ViewEngine { } // mkdir output file dir - const outputFile = path.join(this.getBuildDir(), canonicalViewName); + const outputFile = path.join(this.buildDir, canonicalViewName); await afs.mkdir(path.dirname(outputFile), {recursive: true}); // Read source file if code was not already provided @@ -350,17 +361,17 @@ export default class SvelteViewEngine extends ViewEngine { // Prepare output dir for (const name of canonicalViewNames) { - await afs.mkdir(path.dirname(path.join(this.getPublicDir(), 'js', name)), {recursive: true}); + await afs.mkdir(path.dirname(path.join(this.publicDir, 'js', name)), {recursive: true}); } const production = !config.get('view.dev'); - const input = canonicalViewNames.map(name => path.join(this.getBuildDir(), name)); + const input = canonicalViewNames.map(name => path.join(this.buildDir, name)); if (!this.rollup) { const args = [ 'rollup', '-c', 'rollup.config.js', - '--environment', `ENV:${production ? 'production' : 'dev'},BUILD_DIR:${this.getBuildDir()},PUBLIC_DIR:${this.getPublicDir()},INPUT:${input.join(':')}`, + '--environment', `ENV:${production ? 'production' : 'dev'},BUILD_DIR:${this.buildDir},PUBLIC_DIR:${this.publicDir},INPUT:${input.join(':')}`, ]; if (watch) args.push('--watch'); this.rollup = child_process.spawn('yarn', args, {stdio: [process.stdin, process.stdout, process.stderr]}); diff --git a/src/frontend/ViewEngine.ts b/src/frontend/ViewEngine.ts index 9e2ddc6..21db594 100644 --- a/src/frontend/ViewEngine.ts +++ b/src/frontend/ViewEngine.ts @@ -21,16 +21,12 @@ export default abstract class ViewEngine { private watcher?: FSWatcher; /** - * @param buildDir A temporary directory that will contain any non-final or final non-public asset. - * @param publicDir The output directory that should contain all final and public assets. * @param devWatchedViewDir The directory that should be watched in dev environment. * @param additionalViewPaths By order of priority, the directories that contain all the views of the app. * Swaf provided views and default ./view directory are automatically added (don't add them yourself). * @protected */ protected constructor( - private readonly buildDir: string, - private readonly publicDir: string, private readonly devWatchedViewDir: string, ...additionalViewPaths: string[] ) { @@ -40,21 +36,18 @@ export default abstract class ViewEngine { path.resolve(__dirname, '../../views'), path.resolve(__dirname, '../views'), ].filter(dir => fs.existsSync(dir)); - - if (!fs.existsSync(this.buildDir)) { - fs.mkdirSync(this.buildDir, {recursive: true}); - } } public abstract getExtension(): string; + public abstract render( file: string, locals: Record, callback: (err: Error | null, output?: string) => void, ): Promise; - public setup(app: Express): void { + public setup(app: Express, main: boolean): void { app.engine(this.getExtension(), (path, options, callback) => { // Props (locals) const locals = Object.assign(ViewEngine.getGlobals(), options); @@ -62,24 +55,21 @@ export default abstract class ViewEngine { this.render(path, locals, callback) .catch(err => callback(err)); }); + + const existingViewPaths = app.get('views'); + app.set('views', existingViewPaths ? + [...existingViewPaths, ...this.getViewPaths()] : + this.getViewPaths()); + + if (main) { + app.set('view engine', this.getExtension()); + } } public getViewPaths(): string[] { return this.viewPaths; } - public getBuildDir(): string { - return this.buildDir; - } - - public getPublicDir(): string { - return this.publicDir; - } - - public getDevWatchedViewDir(): string { - return this.devWatchedViewDir; - } - public preCompile?(canonicalName: string, alsoCompileDependents: boolean): Promise; public afterPreCompile?(watch: boolean): Promise;