I needed a quick an dirty way to inline css in all html files within a folder structure such as this:
dist
├── assets
│ ├── another.css
│ └── style.css
├── a
│ └── 1.html
├── b
│ ├── 1.html
│ ├── 2.html
│ └── 3.html
└── c
├── 1.html
├── 2.html
└── c1
└── c11.htmlThe following script will modifiy all the html files and replace the stylessheets <link> elements with a single <style> tag containing all the encountered css rules.
Note, that if you are working on a bigger site, that does have a frontend build pipeline, you probably want use something like netlify-plugin-inline-critical-css, critical or Penthouse to extract only the critical css and inline it.
'use strict';
let glob = require('glob');
let fs = require('fs');
let path = require('path');
let cheerio = require('cheerio');
let base = 'dist';
glob('/**/*.html', { root: base }, (err, files) => {
if (err) throw err;
files.forEach(filePath => {
let css = [];
const html = fs.readFileSync(filePath, 'utf8');
const $ = cheerio.load(html);
$('link[rel=stylesheet]').each((_, link) => {
const $link = $(link);
const cssPath = $link.attr('href')
if(cssPath.match('^https?://')){
return;
}
const dir = path.dirname(filePath);
const absPath = path.join(dir, cssPath)
const data = fs.readFileSync(absPath, 'utf8')
css.push(data)
$link.remove()
})
const cssOutput = css.join('\n')
const style = $('<style>').text(cssOutput)
$('head').append(style)
fs.writeFileSync(filePath, $.html())
console.log('Wrote', filePath)
});
});
Line 10: Get file paths of all html files within dist and its subfolders
Line 19: Iterate trough all linked stylesheets of the page. See the cheerio library which provides a jQuery compatible interface for nodejs
Line 28: The css files are mostly linked trough relatives paths. Join them with the directory of the current html file to the the absolute path of the css file. E.g.:
join(dirname("/home/test/dist/a/b/a.html"), "../../assets/style.css")
> `/home/test/dist/assets/style.css`Line 33: Remove stylesheet from DOM.
Line 36: Create inline style element with the css collected from the external files. Inserted them in same order should avoid problems with the css rules therein.
Line 40: Overwrite existing html