Skip to content

esbuild plugin that allows HTML files to be used as entry points

License

Notifications You must be signed in to change notification settings

markwainwright/esbuild-plugin-html-entry

Repository files navigation

esbuild-plugin-html-entry

An esbuild plugin that allows HTML files to be used as entry points.

<script> and <link> tags with relative src/href attribute values will be added to the build and the value will be replaced with the path of the built file.

This path will be absolute if the esbuild publicPath option is set, or relative if not.

There are a few similar plugins out there already, but this one has a few benefits at time of writing:

  • Optionally supports Subresource Integrity by adding integrity attribute to <script> and <link> tags
  • Optionally allows the JS and CSS filenames to be customized independently of assetNames and chunkNames
  • Automatically inserts <link> tags for CSS bundles immediately before the <script> tag they belong to
  • Supports efficient code splitting:
    • When splitting is enabled, the plugin gathers JS files referenced by <script type="module"> tags in all HTML entry points and passes them to a single esbuild run. This means code shared between multiple files can be extracted even if those files don't always appear together in each HTML entry point. It also results in the least amount of top-level JS files possible being created, which is good for caching
    • If you have any feedback on this behaviour, please feel free to open an issue
  • Populates result metafile and outputFiles as similarly to JS/CSS entry points as possible
  • Handles as many esbuild options as possible – e.g. external, lineLimit, charset – and provides equivalent options to banner and footer
  • Allows JS and CSS entry points alongside HTML entry points as normal
  • Runs the fewest number of sub-builds possible:
    • One if you only use <script type="module"> or <script type="text/javascript">, two if you mix both
  • Supports ES module and CommonJS projects
  • Comprehensive test coverage (snapshot style)

Usage

import * as esbuild from "esbuild";
import { esbuildPluginHtmlEntry } from "esbuild-plugin-html-entry";

esbuild.build({
  entryPoints: ["src/index.html", "src/other.html"],
  plugins: [esbuildPluginHtmlEntry({ integrity: "sha256" })],
});

Plugin options

  • integrity (optional) – the hash algorithm to use for Subresource Integrity
    • Browsers currently support sha256, sha384, and sha512
    • If omitted, Subresource Integrity will not be enabled
  • subresourceNames (optional) – filename format for top-level JS and CSS files
    • Default: value of assetNames
    • See esbuild docs for placeholder format
  • minifyOptions (optional) – options passed to html-minifier-terser if minify is true
    • Default: { collapseWhitespace: true }
  • banner (optional) – prepend a string to each output HTML file – see banner
  • footer (optional) – append a string to each output HTML file – see footer

esbuild options

This plugin is designed to work with as many combinations of esbuild options as possible. However there are a couple of requirements to be aware of:

  1. outdir must be set. The plugin validates this.
  2. Since the plugin generates JS & CSS files in a separate build, to use serve mode, you need to configure esbuild to write to disk and serve from there, i.e.:
    1. write cannot be set to false
    2. servedir must be set equal to outdir

Known issues/limitations

  1. Does not support an equivalent of esbuild outExtension option for HTML files.
    • Output HTML files will always have the same extension as input HTML files (.html or .htm)
    • PRs welcome!
  2. In metafile, inputs[].imports[].kind for HTML → JS/CSS imports will always be set to "import-statement"
    • Something like "script-tag" | "link-tag" would be possible, but I'm not sure how safe introducing new values would be
  3. Inline <script> and <style> tags are not currently supported
  4. Images and other types of subresources are not currently supported
  5. It should play nicely with other plugins but this hasn't been tested yet