JSPM

html-bundler-webpack-plugin

0.2.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 13307
  • Score
    100M100P100Q141643F
  • License ISC

HTML bundler plugin for webpack, extracts CSS, JS, images from their sources loaded in HTML.

Package Exports

  • html-bundler-webpack-plugin
  • html-bundler-webpack-plugin/src/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (html-bundler-webpack-plugin) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

npm node node

This is a modern plugin that does exactly what you want, automatically extracts JS, CSS, images, fonts from their sources loaded directly in HTML using <link> <script> <img> <source> tags and replaces the source filenames with output hashed version of the files. The plugin enable to use an HTML file as entry-point in Webpack.

Note

The purpose of this plugin is to make the developer's life much easier than it was using html-webpack-plugin mini-css-extract-plugin and other plugins.

Note

The plugin is under continuous development. Many new killer features will be implemented soon.

Кeep your finger on the pulse.

This plugin works like the pug-plugin but the entry point is a HTML file.

💡 Highlights:

  • Define your HTML pages in Webpack entry.
  • The HTML file is the entry-point for all source scripts and styles.
  • Source scripts and styles should be loaded directly in HTML using tags.
  • All JS and CSS files will be extracted from their sources specified in HTML tags.

Specify the HTML files in the Webpack entry:

const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');
module.exports = {
  entry: {
    // define HTML files here
    index: './src/views/home/index.html',  // output dist/index.html
  },
  plugins: [
    // enable processing of HTML files defined in Webpack entry
    new HtmlBundlerPlugin(),
  ],
  module: {
    rules: [
      {
        test: /.html/,
        loader: HtmlBundlerPlugin.loader, // HTML loader
      },
      // ... other rules, e.g. for styles, images, fonts, etc.
    ],
  },
};

Add source scripts and styles directly to HTML using relative path or Webpack alias:

<html>
  <head>
    <link href="./style.scss" rel="stylesheet">
    <script src="./main.js" defer="defer"></script>
  </head>
  <body>
    <h1>Hello World!</h1>
  </body>
</html>

The generated HTML contains hashed output CSS and JS filenames:

<html>
  <head>
    <link href="/assets/css/style.05e4dd86.css" rel="stylesheet">
    <script src="/assets/js/main.f4b855d8.js" defer="defer"></script>
  </head>
  <body>
    <h1>Hello World!</h1>
  </body>
</html>

The <link> and <script> tags stay where they are written. This can be very important in some cases, as opposed to using other plugins like html-webpack-plugin and mini-css-extract-plugin that injects these tags somewhere in the HTML.

Just one HTML bundler plugin replaces the functionality of the plugins and loaders:

Package Features
html-webpack-plugin extract HTML and save in a file
mini-css-extract-plugin extract CSS and save in a file
webpack-remove-empty-scripts remove empty JS files generated by the mini-css-extract-plugin
resolve-url-loader resolve url in CSS
svg-url-loader encode SVG data-URL as utf8
posthtml-inline-svg inline SVG icons in HTML
html-loader exports HTML as string

Contents


  1. Install and Quick start
  2. Features
  3. Plugin options
  4. Recipes

Features

  • compiles HTML files defined in Webpack entry
  • HTML file is entry-point for all resources (styles, scripts)
  • extracts CSS from source style loaded in HTML via a <link> tag
  • extracts JS from source script loaded in HTML via a <script> tag
  • processes the images, fonts from source files loaded in HTML via <link>, <img> or <source> tags
  • generated HTML contains hashed CSS, JS, images, fonts output filenames
  • resolves source files of URLs in CSS and extract resolved resources to output path
    not need more additional plugin such as resolve-url-loader
  • support the auto publicPath
  • support the inline CSS in HTML from processed source style
  • support the inline JavaScript in HTML from compiled source script
  • support the module types asset/resource asset/inline asset
  • support the inline image as base64 encoding of binary images (png, jpg, etc.) in HTML and CSS
  • support the inline SVG as SVG tag in HTML
  • support the inline SVG as data-URL in CSS
    background: url('./icons/iphone.svg') // CSS: url("data:image/svg+xml,<svg>...</svg>")

Install and Quick start

Install the html-bundler-webpack-plugin:

npm install html-bundler-webpack-plugin --save-dev

Install additional packages for styles:

npm install css-loader sass sass-loader --save-dev

Change your webpack.config.js according to the following minimal configuration:

const path = require('path');
const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');

module.exports = {
  output: {
    path: path.join(__dirname, 'dist/'),
    publicPath: '/',
  },

  entry: {
    // define HTML files here
    index: './src/views/home/index.html',  // output dist/index.html
    'pages/about': './src/views/about/index.html', // output dist/pages/about.html
    // ...
  },

  plugins: [
    new HtmlBundlerPlugin({
      js: {
        // output filename of extracted JS from source script loaded in HTML via `<script>` tag
        filename: 'assets/js/[name].[contenthash:8].js',
      },
      css: {
        // output filename of extracted CSS from source style loaded in HTML via `<link>` tag
        filename: 'assets/css/[name].[contenthash:8].css',
      },
    }),
  ],

  module: {
    rules: [
      {
        test: /\.html$/,
        loader: HtmlBundlerPlugin.loader, // HTML loader
      },
      {
        test: /\.(css|sass|scss)$/,
        use: ['css-loader', 'sass-loader'],
      },
    ],
  },
};

Plugin options

verbose

Type: boolean Default: false
Display the file information at processing.

outputPath

Type: string Default: webpack.options.output.path
The output directory for processed file. This directory can be relative by webpack.options.output.path or absolute.

filename

Type: string | Function Default: [name].html
The name of output file.

  • If type is string then following substitutions (see output.filename for chunk-level) are available in template string:
    • [id] The ID of the chunk.
    • [name] Only filename without extension or path.
    • [contenthash] The hash of the content.
    • [contenthash:nn] The nn is the length of hashes (defaults to 20).
  • If type is Function then following arguments are available in the function:
    • @param {PathData} pathData has the useful properties (see the type PathData):
      • pathData.filename the full path to source file
      • pathData.chunk.name the name of entry key
    • @param {AssetInfo} assetInfo Mostly this object is empty.
    • @return {string} The name or template string of output file.

css

Type: Object
Default properties:

{
  test: /\.(css|scss|sass|less|styl)$/,
  enabled: true,
  verbose: false,
  filename: '[name].css',
  outputPath: null,
}

The filename property see by filename option. The outputPath property see by outputPath option.

The option to extract CSS from a style source file loaded in the HTML tag:

<link href="./style.scss" rel="stylesheet">

Warning

Don't import source styles in JavaScript! Styles must be loaded directly in HTML.

The default CSS output filename is [name].css. You can specify your own filename using webpack filename substitutions:

const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');
module.exports = {
  plugins: [
    new HtmlBundlerPlugin({
      css: {
        filename: 'assets/css/[name].[contenthash:8].css',
      },
    }),
  ],
};

The name is the filename of a loaded style. For example, if source file is style.scss, then output filename will be assets/css/style.1234abcd.css.
If you want to have a different output filename, you can use the filename options as the function.

Warning

Don't use mini-css-extract-plugin or style-loader, they are not required more.
The html-bundler-webpack-plugin extracts CSS much faster than other plugins and resolves all asset URLs in CSS, therefore the resolve-url-loader is redundant too.

js

Type: Object
Default properties:

{
  verbose: false,
  filename: '[name].js', 
  outputPath: null,
}

The filename property see by filename option. The outputPath property see by outputPath option.

Note

  • the extract js module is always enabled
  • the test property not exist because all loaded scripts are automatically detected

The option to extract JS from a script source file loaded in the HTML tag:

<script src="./main.js"></script>

The default JS output filename is [name].js. You can specify your own filename using webpack filename substitutions:

const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');
module.exports = {
  plugins: [
    new HtmlBundlerPlugin({
      js: {
        filename: 'assets/js/[name].[contenthash:8].js',
      },
    }),
  ],
};

The name is the filename of a loaded script. For example, if source file is main.js, then output filename will be assets/js/main.1234abcd.js.
If you want to have a different output filename, you can use the filename options as the function.


How to inline CSS in HTML

For example, the style.scss:

$color: red;
h1 {
  color: $color;
}

Add the ?inline query to the source filename which you want inline:

<html>
  <head>
    <!-- load style as file -->
    <link href="./main.scss" rel="stylesheet" />
    <!-- inline style -->
    <link href="./main.scss?inline" rel="stylesheet" />
  </head>
  <body>
    <h1>Hello World!</h1>
  </body>
</html>

The generated HTML contains inline CSS already processed via Webpack:

<html>
  <head>
    <!-- load style as file -->
    <link href="/assets/css/style.05e4dd86.css" rel="stylesheet">
    <!-- inline style -->
    <style>
      h1{color: red;}
    </style>
  </head>
  <body>
    <h1>Hello World!</h1>
  </body>
</html>

How to inline JS in HTML

For example, the main.js:

console.log('Hello JS!');

Add the ?inline query to the source filename which you want inline:

<html>
  <head>
    <!-- load script as file -->
    <script src="./main.js" defer="defer"></script>
    <!-- inline script -->
    <script src="./main.js?inline"></script>
  </head>
  <body>
    <h1>Hello World!</h1>
  </body>
</html>

The generated HTML contains inline JS already compiled via Webpack:

<html>
  <head>
    <!-- load style as file -->
    <script src="assets/js/main.992ba657.js" defer="defer"></script>
    <!-- inline script -->
    <script>
      (()=>{"use strict";console.log("Hello JS!")})();
    </script>
  </head>
  <body>
    <h1>Hello World!</h1>
  </body>
</html>

How to use source images in HTML

Add to Webpack config the rule:

 module: {
  rules: [
    {
      test: /\.(png|jpe?g|ico)/,
      type: 'asset/resource',
      generator: {
        filename: 'assets/img/[name].[hash:8][ext]',
      },
    },
  ],

Add a source file using a relative path or Webpack alias in HTML:

<html>
  <head>
    <link href="./favicon.ico" rel="icon" />
  </head>
  <body>
    <img src="./apple.png" srcset="./apple1.png 320w, ./apple2.png 640w" alt="apple">
    <picture>
      <source srcset="./fig1.jpg, ./fig2.jpg 320w, ./fig3.jpg 640w">
    </picture>
  </body>
</html>

The generated HTML contains hashed output images filenames:

<html>
  <head>
    <link href="/assets/img/favicon.05e4dd86.ico" rel="icon" />
  </head>
  <body>
    <img src="/assets/img/apple.f4b855d8.png" srcset="/assets/img/apple1.855f4bd8.png 320w, /assets/img/apple2.d8f4b855.png 640w" alt="apple">
    <picture>
      <source srcset="/assets/img/fig1.605e4dd8.jpg, /assets/img/fig2.8605e4dd.jpg 320w, /assets/img/fig3.e4605dd8.jpg 640w">
    </picture>
  </body>
</html>

How to preload source fonts in HTML

Add to Webpack config the rule:

 module: {
  rules: [
    {
      test: /\.(eot|ttf|woff|woff2)/,
      type: 'asset/resource',
      generator: {
        filename: 'assets/fonts/[name][ext]',
      },
    },
  ],

Add a source file using a relative path or Webpack alias in HTML:

<html>
  <head>
    <link href="./font1.woff2" rel="preload" as="font" type="font/woff2" />
    <link href="./font2.woff2" rel="preload" as="font" type="font/woff2" />
  </head>
  <body>
    <h1>Hello World!</h1>
  </body>
</html>

The generated HTML contains output fonts filenames:

<html>
  <head>
    <link href="/assets/fonts/font1.woff2" rel="preload" as="font" type="font/woff2" />
    <link href="/assets/fonts/font2.woff2" rel="preload" as="font" type="font/woff2" />
  </head>
  <body>
    <h1>Hello World!</h1>
  </body>
</html>

Note

Now you don't need a plugin to copy files from source directory to public.

HMR live reload

To enable live reload by changes any file add in the Webpack config the devServer option:

module.exports = {
  // enable HMR with live reload
  devServer: {
    static: {
      directory: path.join(__dirname, 'dist'),
    },
    watchFiles: {
      paths: ['src/**/*.*'],
      options: {
        usePolling: true,
      },
    },
  },
};

Note

Live reload works only if in HTML used a JS file. If your HTML has not a JS, then create one empty JS file, e.g. hmr.js and add it in the HTML:

<script src="./hmr.js"></script>

Also See

  • ansis - The Node.js lib for ANSI color styling of text in terminal
  • pug-loader The Pug loader for Webpack
  • pug-plugin The Pug plugin for Webpack

License

ISC