Skip to content

Instantly share code, notes, and snippets.

@coreequip
Created September 20, 2022 12:57
Show Gist options
  • Save coreequip/42afdd2f157cc0e747ce4916cea4678d to your computer and use it in GitHub Desktop.
Save coreequip/42afdd2f157cc0e747ce4916cea4678d to your computer and use it in GitHub Desktop.
Generate HTML rollup.js plugin

Generate HTML Rollup.js Plugin

Usage

generateHtml(templatePath, outputFilename, contect, doCompress

Example:

// rollup.config.js plugin part

generateHtml('path/to/your/index.html', 'outputname.html', {
    htmlTitle: 'My HTML',
    favicon: 'favicon.ico'
}, production),

  // ...  

In the HTML template use ES6 template iteral style. The htmlTitle from the example is accessed like: ${this.htmlTitle}.

File inlining can be realized with: //inline/MIMETYPE;PATH_TO_FILE, ex.: //inline/image/svg+xml;src/assets/logotext.svg

import {readFileSync} from 'fs'
import {minify} from 'html-minifier'
const MINIFY_OPTIONS = {
collapseWhitespace: true,
removeOptionalTags: true,
minifyCSS: {level: {1: {specialComments: 0}}},
ignoreCustomComments: []
}
const replaceInline = (src) =>
src.replace(/(["(>])\/\/inline\/(.+?);(.+?)([")<])/g, (full, begin, mimetype, path, end) => {
try {
// TODO figure out mimetype by file ext
return `${begin}data:${mimetype};base64,` + readFileSync(path).toString('base64') + end
} catch (e) {
console.error('GenerateHTML REPLACE: Error reading file "%s"', path)
return null
}
})
const generatePreload = (src) => [...src.matchAll(/\("?(\/[/\w\d-]+?\.woff2)/g)]
.map(m => `<link rel="preload" href="${m[1]}" as="font" type="font/woff2" crossorigin>`)
.join('')
export default function generateHtml(inPath, outFile, env = {}, compress = true) {
return {
name: 'generate-html',
generateBundle(_, bundle) {
env.jsFileName = Object.values(bundle)[0].fileName
env.styleSheet = global.generatedStyle || ''
env.preload = generatePreload(env.styleSheet)
const template = readFileSync(inPath).toString()
const output = replaceInline(Function(`"use strict"; return \`${template}\``).call(env))
this.emitFile({
type: 'asset',
fileName: outFile,
source: compress ? minify(output, MINIFY_OPTIONS) : output
})
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment