src/lib/rollup.ts (95 lines of code) (raw):
import fs from 'fs';
import alias from '@rollup/plugin-alias';
import commonjs from '@rollup/plugin-commonjs';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import terser from '@rollup/plugin-terser';
import typescript from '@rollup/plugin-typescript';
import type { Plugin, RollupOutput } from 'rollup';
import { rollup } from 'rollup';
import css from 'rollup-plugin-css-only';
import svelte from 'rollup-plugin-svelte';
import preprocess from 'svelte-preprocess';
import type { Props } from './svelte';
const virtual = (template: string, props: Props): Plugin => ({
name: 'virtual-template',
resolveId(source: string) {
if (source === 'ssr' || source === 'dom') return source;
return null;
},
load(id: string) {
if (id === 'ssr') {
return [
`import Template from "./src/templates/ssr/${template}/index.svelte"`,
`setShare(Template.render(${JSON.stringify(props)}))`,
].join('\n');
}
if (id === 'dom') {
return `import Template from "./src/templates/csr/${template}/index.svelte";
new Template({
target: document.querySelector('#svelte'),
props: ${JSON.stringify(props)},
});`;
}
return null;
},
});
/**
* Builds and minifies the JS & CSS from the svelte templates using Rollup.
*
* @param template the `id` of the template, matching its directory name.
* @param mode `dom` for dynamic templates, `ssr` for static ones.
* @param props GAM variables used to build the template.
* @returns Rollup chunks of the compiled JS & CSS.
*/
const build = async (
template: string,
mode: 'ssr' | 'dom',
props: Props = {},
): Promise<{
styles: string;
chunks: RollupOutput['output'];
}> => {
console.info(
`Building ${mode === 'dom' ? 'Dynamic' : 'Static'} template “${template}”`,
);
let styles = '';
let input: ['ssr' | 'dom'] | ['ssr', `${string}/index.ts`] = [mode];
if (mode === 'ssr') {
if (fs.existsSync(`src/templates/ssr/${template}/index.ts`)) {
input = ['ssr', `src/templates/ssr/${template}/index.ts`];
}
}
const build = await rollup({
input,
plugins: [
virtual(template, props),
svelte({
preprocess: preprocess(),
emitCss: mode === 'dom',
compilerOptions: {
generate: mode,
immutable: true,
},
}),
typescript({ sourceMap: false }),
commonjs(),
alias({
entries: [
{
find: '$lib',
replacement: 'src/lib',
},
{
find: '$templates',
replacement: 'src/templates',
},
],
}),
nodeResolve(),
terser(),
css({
output: (processedStyles: string) => {
styles = processedStyles
.replaceAll(/\s+/g, ' ')
.replaceAll('\t', ' ');
return false;
},
}),
],
});
const output = await build.generate({}).then((output) => output.output);
return { styles, chunks: output };
};
export { build };