refactor: externalize CSS and JS compilation to avoid Eleventy execution order issues

This commit is contained in:
boulangerseb 2025-07-25 22:35:03 +02:00
parent 5c265ec707
commit a82733048c
5 changed files with 96 additions and 86 deletions

View file

@ -20,8 +20,19 @@ import events from './src/_config/events.js';
import filters from './src/_config/filters.js';
import plugins from './src/_config/plugins.js';
import shortcodes from './src/_config/shortcodes.js';
import {buildAllCss} from './src/_config/plugins/css-config.js';
import {buildAllJs} from './src/_config/plugins/js-config.js';
export default async function (eleventyConfig) {
eleventyConfig.on('eleventy.before', async () => {
await buildAllCss();
await buildAllJs();
});
eleventyConfig.addWatchTarget('./src/assets/**/*.{css,js,svg,png,jpeg}');
eleventyConfig.addWatchTarget('./src/_includes/**/*.{webc}');
@ -38,8 +49,6 @@ export default async function (eleventyConfig) {
// --------------------- Plugins
eleventyConfig.addPlugin(plugins.htmlConfig);
eleventyConfig.addPlugin(plugins.cssConfig);
eleventyConfig.addPlugin(plugins.jsConfig);
eleventyConfig.addPlugin(plugins.drafts);
eleventyConfig.addPlugin(plugins.EleventyRenderPlugin);

View file

@ -25,13 +25,14 @@
"url": "https://github.com/madrilene/eleventy-excellent.git"
},
"dependencies": {
"@11ty/eleventy": "^3.1.1",
"@11ty/eleventy": "^3.1.2",
"@11ty/eleventy-fetch": "^5.1.0",
"@11ty/eleventy-img": "^6.0.4",
"@11ty/eleventy-plugin-rss": "^2.0.4",
"@11ty/eleventy-plugin-syntaxhighlight": "^5.0.1",
"@11ty/eleventy-plugin-webc": "^0.11.2",
"@11ty/is-land": "^4.0.1",
"fast-glob": "^3.3.3",
"lite-youtube-embed": "^0.3.3",
"tailwindcss": "^3.4.17"
},

View file

@ -12,10 +12,6 @@ import {drafts} from './plugins/drafts.js';
// Custom transforms
import {htmlConfig} from './plugins/html-config.js';
// Custom template language
import {cssConfig} from './plugins/css-config.js';
import {jsConfig} from './plugins/js-config.js';
export default {
EleventyRenderPlugin,
rss,
@ -24,7 +20,5 @@ export default {
eleventyImageTransformPlugin,
markdownLib,
drafts,
htmlConfig,
cssConfig,
jsConfig
htmlConfig
};

View file

@ -6,43 +6,53 @@ import postcssImportExtGlob from 'postcss-import-ext-glob';
import tailwindcss from 'tailwindcss';
import autoprefixer from 'autoprefixer';
import cssnano from 'cssnano';
import fg from 'fast-glob';
export const cssConfig = eleventyConfig => {
eleventyConfig.addTemplateFormats('css');
const buildCss = async (inputPath, outputPaths) => {
const inputContent = await fs.readFile(inputPath, 'utf-8');
eleventyConfig.addExtension('css', {
outputFileExtension: 'css',
compile: async (inputContent, inputPath) => {
const paths = [];
if (inputPath.endsWith('/src/assets/css/global/global.css')) {
paths.push('src/_includes/css/global.css');
} else if (inputPath.includes('/src/assets/css/local/')) {
const baseName = path.basename(inputPath);
paths.push(`src/_includes/css/${baseName}`);
} else if (inputPath.includes('/src/assets/css/components/')) {
const baseName = path.basename(inputPath);
paths.push(`dist/assets/css/components/${baseName}`);
} else {
return;
}
const result = await postcss([
postcssImportExtGlob,
postcssImport,
tailwindcss,
autoprefixer,
cssnano
]).process(inputContent, { from: inputPath });
return async () => {
let result = await postcss([
postcssImportExtGlob,
postcssImport,
tailwindcss,
autoprefixer,
cssnano
]).process(inputContent, {from: inputPath});
for (const outputPath of outputPaths) {
await fs.mkdir(path.dirname(outputPath), { recursive: true });
await fs.writeFile(outputPath, result.css);
}
// Write the output to all specified paths
for (const outputPath of paths) {
await fs.mkdir(path.dirname(outputPath), {recursive: true});
await fs.writeFile(outputPath, result.css);
}
return result.css;
}
return result.css;
};
}
});
};
export const buildAllCss = async () => {
const tasks = [];
tasks.push(
buildCss(
'src/assets/css/global/global.css',
['src/_includes/css/global.css']
)
);
const localCssFiles = await fg(['src/assets/css/local/*.css']);
for (const inputPath of localCssFiles) {
const baseName = path.basename(inputPath);
tasks.push(
buildCss(inputPath, [`src/_includes/css/${baseName}`])
);
}
const componentCssFiles = await fg(['src/assets/css/components/*.css']);
for (const inputPath of componentCssFiles) {
const baseName = path.basename(inputPath);
tasks.push(
buildCss(inputPath, [`dist/assets/css/components/${baseName}`])
);
}
await Promise.all(tasks);
}

View file

@ -1,45 +1,41 @@
import esbuild from 'esbuild';
import fs from 'node:fs/promises';
import path from 'node:path';
import fg from 'fast-glob';
import esbuild from 'esbuild';
export const jsConfig = eleventyConfig => {
eleventyConfig.addTemplateFormats('js');
eleventyConfig.addExtension('js', {
outputFileExtension: 'js',
compile: async (content, inputPath) => {
// Skip processing if not in the designated scripts directories
if (!inputPath.startsWith('./src/assets/scripts/')) {
return;
}
// Inline scripts processing
if (inputPath.startsWith('./src/assets/scripts/bundle/')) {
const filename = path.basename(inputPath);
const outputFilename = filename;
const outputPath = `./src/_includes/scripts/${outputFilename}`;
await esbuild.build({
target: 'es2020',
entryPoints: [inputPath],
outfile: outputPath,
bundle: true,
minify: true
});
return;
}
// Default handling for other scripts, excluding inline scripts
return async () => {
let output = await esbuild.build({
target: 'es2020',
entryPoints: [inputPath],
bundle: true,
minify: true,
write: false
});
return output.outputFiles[0].text;
};
}
export const buildJs = async (inputPath, outputPath) => {
const result = await esbuild.build({
target: 'es2020',
entryPoints: [inputPath],
bundle: true,
minify: true,
write: false
});
const output = result.outputFiles[0].text;
await fs.mkdir(path.dirname(outputPath), { recursive: true });
await fs.writeFile(outputPath, output);
return output;
};
export const buildAllJs = async () => {
const tasks = [];
const inlineBundleFiles = await fg(['src/assets/scripts/bundle/*.js']);
for (const inputPath of inlineBundleFiles) {
const baseName = path.basename(inputPath);
const outputPath = `src/_includes/scripts/${baseName}`;
tasks.push(buildJs(inputPath, outputPath));
}
const componentFiles = await fg(['src/assets/scripts/components/*.js']);
for (const inputPath of componentFiles) {
const baseName = path.basename(inputPath);
const outputPath = `dist/assets/scripts/components/${baseName}`;
tasks.push(buildJs(inputPath, outputPath));
}
await Promise.all(tasks);
};