Add svelte as a view engine to swaf #33
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user