Add svelte as a view engine to swaf #33
@ -7,7 +7,6 @@ import {promises as fs} from 'fs';
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
import requireFromString from "require-from-string";
|
import requireFromString from "require-from-string";
|
||||||
import {compile, preprocess} from "svelte/compiler";
|
import {compile, preprocess} from "svelte/compiler";
|
||||||
import {CssResult} from "svelte/types/compiler/interfaces";
|
|
||||||
import {sveltePreprocess} from "svelte-preprocess/dist/autoProcess.js";
|
import {sveltePreprocess} from "svelte-preprocess/dist/autoProcess.js";
|
||||||
|
|
||||||
import {logger} from "../Logger.js";
|
import {logger} from "../Logger.js";
|
||||||
@ -31,6 +30,7 @@ export default class SvelteViewEngine extends ViewEngine {
|
|||||||
private readonly fileCache: FileCache = new FileCache();
|
private readonly fileCache: FileCache = new FileCache();
|
||||||
private readonly dependencyCache: Record<string, Set<string>> = {};
|
private readonly dependencyCache: Record<string, Set<string>> = {};
|
||||||
private readonly preprocessingCache: Record<string, PreprocessingCacheEntry> = {};
|
private readonly preprocessingCache: Record<string, PreprocessingCacheEntry> = {};
|
||||||
|
private readonly cssCache: Record<string, string[] | undefined> = {};
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
targetDir: string,
|
targetDir: string,
|
||||||
@ -96,24 +96,20 @@ export default class SvelteViewEngine extends ViewEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async preCompile(canonicalName: string, alsoCompileDependents: boolean): Promise<void> {
|
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 {backendCalls} = await this.preprocess(canonicalName);
|
||||||
|
|
||||||
const allBackendCalls: string[] = [];
|
|
||||||
|
|
||||||
const {backendCalls, code} = await this.preprocess(canonicalName);
|
|
||||||
allBackendCalls.push(...backendCalls);
|
|
||||||
|
|
||||||
// Server Side Render (initial HTML and CSS, no-js)
|
// 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 separator = SvelteViewEngine.getPreCompileSeparator(canonicalName);
|
||||||
const finalCode = [
|
const finalCode = [
|
||||||
[...new Set<string>(allBackendCalls).values()].join('\n'),
|
[...new Set<string>(backendCalls).values()].join('\n'),
|
||||||
ssr.head,
|
ssr.head,
|
||||||
ssr.html,
|
ssr.html,
|
||||||
ssr.css.code,
|
ssr.css,
|
||||||
].join(separator);
|
].join(separator);
|
||||||
|
|
||||||
const swafViewFile = path.join(this.targetDir, canonicalName + COMPILED_SVELTE_EXTENSION);
|
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,
|
head: string,
|
||||||
css: CssResult,
|
css: string,
|
||||||
html: 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
|
// Svelte compile
|
||||||
logger.info(canonicalName + ' > ', 'Compiling svelte ssr', file);
|
|
||||||
const svelteSsr = compile(code, {
|
const svelteSsr = compile(code, {
|
||||||
dev: config.get<boolean>('view.dev'),
|
dev: config.get<boolean>('view.dev'),
|
||||||
generate: 'ssr',
|
generate: 'ssr',
|
||||||
format: 'cjs',
|
format: 'cjs',
|
||||||
cssOutputFilename: file + '.css',
|
cssOutputFilename: targetFile + '.css',
|
||||||
});
|
});
|
||||||
|
|
||||||
// Load locals into locals store
|
// Load locals into locals store
|
||||||
@ -287,9 +301,22 @@ export default class SvelteViewEngine extends ViewEngine {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Load module and render
|
// Load module and render
|
||||||
const moduleId = path.resolve(file);
|
const moduleId = path.resolve(targetFile);
|
||||||
clearModule.single(moduleId);
|
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(
|
private compileBackendCalls(
|
||||||
|
Loading…
Reference in New Issue
Block a user