diff --git a/src/frontend/SvelteViewEngine.ts b/src/frontend/SvelteViewEngine.ts index 985b747..7114085 100644 --- a/src/frontend/SvelteViewEngine.ts +++ b/src/frontend/SvelteViewEngine.ts @@ -30,10 +30,7 @@ export default class SvelteViewEngine extends ViewEngine { private readonly fileCache: FileCache = new FileCache(); private readonly dependencyCache: Record> = {}; - private readonly backendCallsCache: Record = {}; + private readonly preprocessingCache: Record = {}; public constructor( targetDir: string, @@ -43,12 +40,12 @@ export default class SvelteViewEngine extends ViewEngine { } public async onFileChange(file: string): Promise { - delete this.backendCallsCache[this.toCanonicalName(file)]; + delete this.preprocessingCache[this.toCanonicalName(file)]; } public async onFileRemove(file: string): Promise { const canonicalName = this.toCanonicalName(file); - delete this.backendCallsCache[canonicalName]; + delete this.preprocessingCache[canonicalName]; delete this.dependencyCache[canonicalName]; Object.values(this.dependencyCache).forEach(set => set.delete(canonicalName)); await super.onFileRemove(file); @@ -124,14 +121,14 @@ export default class SvelteViewEngine extends ViewEngine { const allBackendCalls: string[] = []; for (const dependency of this.resolveDependencies(source, canonicalName)) { - allBackendCalls.push(...(await this.replaceBackendCalls(dependency)).backendCalls); + allBackendCalls.push(...(await this.preprocess(dependency)).backendCalls); } - const {replacedBackendCall, backendCalls} = await this.replaceBackendCalls(canonicalName, source); + const {backendCalls, code} = await this.preprocess(canonicalName, source); allBackendCalls.push(...backendCalls); // Server Side Render (initial HTML and CSS, no-js) - const ssr = await this.compileSsr(canonicalName, intermediateFile, replacedBackendCall); + const ssr = await this.compileSsr(canonicalName, intermediateFile, code); const separator = SvelteViewEngine.getPreCompileSeparator(canonicalName); const finalCode = [ @@ -176,34 +173,59 @@ export default class SvelteViewEngine extends ViewEngine { return dependencies; } - private async replaceBackendCalls(canonicalViewName: string, code?: string): Promise<{ - replacedBackendCall: string, - backendCalls: string[], - }> { + private async preprocess(canonicalName: string, code?: string): Promise { // Cache - if (Object.keys(this.backendCallsCache).indexOf(canonicalViewName) >= 0) { - return this.backendCallsCache[canonicalViewName]; + if (Object.keys(this.preprocessingCache).indexOf(canonicalName) >= 0) { + return this.preprocessingCache[canonicalName]; } + const file = await this.resolveFileFromCanonicalName(canonicalName); + logger.info(canonicalName + ' > ', `Preprocessing ${file}`); + // mkdir output file dir - const outputFile = path.join(this.targetDir, canonicalViewName); + const outputFile = path.join(this.targetDir, canonicalName); await fs.mkdir(path.dirname(outputFile), {recursive: true}); // Read source file if code was not already provided if (!code) { - const file = await this.resolveFileFromCanonicalName(canonicalViewName); code = await this.fileCache.get(file, !config.get('view.cache')); } + // Replace backend calls + const replacedBackendCalls = await this.replaceBackendCalls(canonicalName, code); + + // Preprocess svelte + logger.info(canonicalName + ' > ', 'Svelte preprocessing'); + const preprocessed = await preprocess( + replacedBackendCalls.code, + sveltePreprocess({ + typescript: { + tsconfigFile: 'tsconfig.svelte.json', + }, + }), + { + filename: outputFile, + }, + ); + + // Write to output file + await fs.writeFile(outputFile, preprocessed.code); + + return this.preprocessingCache[canonicalName] = { + backendCalls: replacedBackendCalls.backendCalls, + code: preprocessed.code, + }; + } + + private async replaceBackendCalls(canonicalName: string, code: string): Promise { + logger.info(canonicalName + ' > ', 'Replacing backend calls'); + // Skip replace if there is no swaf export if (!code.match(/export[ \n]+let[ \n]+locals[ \n]*=[ \n]*{[ \n]*}/)) { - const generated = { - replacedBackendCall: code, + return { backendCalls: [], + code: code, }; - await fs.writeFile(outputFile, generated.replacedBackendCall); - this.backendCallsCache[canonicalViewName] = generated; - return generated; } @@ -251,14 +273,10 @@ export default class SvelteViewEngine extends ViewEngine { } output = output.split(BACKEND_CODE_PREFIX_TEMPORARY_HOLDER).join(BACKEND_CODE_PREFIX); - const generated = { - replacedBackendCall: output, + return { backendCalls: [...backendCalls], + code: output, }; - await fs.writeFile(outputFile, generated.replacedBackendCall); - this.backendCallsCache[canonicalViewName] = generated; - - return generated; } private async compileSsr(canonicalName: string, file: string, code: string): Promise<{ @@ -266,23 +284,9 @@ export default class SvelteViewEngine extends ViewEngine { css: CssResult, html: string, }> { - // Svelte preprocess - logger.info(canonicalName + ' > ', 'Preprocessing svelte', file); - const preprocessed = await preprocess( - code, - sveltePreprocess({ - typescript: { - tsconfigFile: 'tsconfig.svelte.json', - }, - }), - { - filename: file, - }, - ); - // Svelte compile logger.info(canonicalName + ' > ', 'Compiling svelte ssr', file); - const svelteSsr = compile(preprocessed.code, { + const svelteSsr = compile(code, { dev: config.get('view.dev'), generate: 'ssr', format: 'cjs', @@ -299,3 +303,7 @@ export default class SvelteViewEngine extends ViewEngine { } } +type PreprocessingCacheEntry = { + backendCalls: string[], + code: string, +};