Make css properly passed from children to parents with cache and dedup

This commit is contained in:
Alice Gaudon 2021-05-31 11:14:56 +02:00
parent c6b8c48a72
commit eb6ed8f2d2
1 changed files with 44 additions and 17 deletions

View File

@ -7,7 +7,6 @@ import {promises as fs} from 'fs';
import path from "path";
import requireFromString from "require-from-string";
import {compile, preprocess} from "svelte/compiler";
import {CssResult} from "svelte/types/compiler/interfaces";
import {sveltePreprocess} from "svelte-preprocess/dist/autoProcess.js";
import {logger} from "../Logger.js";
@ -31,6 +30,7 @@ export default class SvelteViewEngine extends ViewEngine {
private readonly fileCache: FileCache = new FileCache();
private readonly dependencyCache: Record<string, Set<string>> = {};
private readonly preprocessingCache: Record<string, PreprocessingCacheEntry> = {};
private readonly cssCache: Record<string, string[] | undefined> = {};
public constructor(
targetDir: string,
@ -96,24 +96,20 @@ export default class SvelteViewEngine extends ViewEngine {
}
public async preCompile(canonicalName: string, alsoCompileDependents: boolean): Promise<void> {
const intermediateFile = path.join(this.targetDir, canonicalName);
const targetFile = path.join(this.targetDir, canonicalName);
logger.info(canonicalName + ' > ', 'Pre-compiling', canonicalName, '->', targetFile);
logger.info(canonicalName + ' > ', 'Pre-compiling', canonicalName, '->', intermediateFile);
const allBackendCalls: string[] = [];
const {backendCalls, code} = await this.preprocess(canonicalName);
allBackendCalls.push(...backendCalls);
const {backendCalls} = await this.preprocess(canonicalName);
// Server Side Render (initial HTML and CSS, no-js)
const ssr = await this.compileSsr(canonicalName, intermediateFile, code, allBackendCalls);
const ssr = await this.compileSsr(canonicalName);
const separator = SvelteViewEngine.getPreCompileSeparator(canonicalName);
const finalCode = [
[...new Set<string>(allBackendCalls).values()].join('\n'),
[...new Set<string>(backendCalls).values()].join('\n'),
ssr.head,
ssr.html,
ssr.css.code,
ssr.css,
].join(separator);
const swafViewFile = path.join(this.targetDir, canonicalName + COMPILED_SVELTE_EXTENSION);
@ -261,18 +257,36 @@ export default class SvelteViewEngine extends ViewEngine {
};
}
private async compileSsr(canonicalName: string, file: string, code: string, backendCalls: string[]): Promise<{
private async compileSsr(canonicalName: string): Promise<{
head: string,
css: CssResult,
css: string,
html: string,
}> {
const targetFile = path.join(this.targetDir, canonicalName);
const {backendCalls, code} = await this.preprocess(canonicalName);
// Get dependencies css
const dependenciesCss: string[] = [];
for (const dependency of this.resolveDependencies(code, canonicalName)) {
if (this.cssCache[dependency] === undefined) {
await this.compileSsr(dependency);
}
const css = this.cssCache[dependency];
if (css === undefined) {
logger.error(typeof this.cssCache[dependency], !!this.cssCache[dependency]);
throw new Error(`Compiling ssr of ${dependency} didn't cache its css.`);
}
dependenciesCss.push(...css);
}
logger.info(canonicalName + ' > ', 'Compiling svelte ssr', targetFile);
// Svelte compile
logger.info(canonicalName + ' > ', 'Compiling svelte ssr', file);
const svelteSsr = compile(code, {
dev: config.get<boolean>('view.dev'),
generate: 'ssr',
format: 'cjs',
cssOutputFilename: file + '.css',
cssOutputFilename: targetFile + '.css',
});
// Load locals into locals store
@ -287,9 +301,22 @@ export default class SvelteViewEngine extends ViewEngine {
});
// Load module and render
const moduleId = path.resolve(file);
const moduleId = path.resolve(targetFile);
clearModule.single(moduleId);
return requireFromString(svelteSsr.js.code, moduleId).default.render();
const {
head,
css,
html,
} = requireFromString(svelteSsr.js.code, moduleId).default.render();
const cssFragments = css.code === '' ?
dependenciesCss :
[...dependenciesCss, css.code];
this.cssCache[canonicalName] = cssFragments;
return {
head,
css: [...new Set(cssFragments)].join(''),
html,
};
}
private compileBackendCalls(