Coder Social home page Coder Social logo

mattlewis92 / script-ext-html-webpack-plugin Goto Github PK

View Code? Open in Web Editor NEW

This project forked from numical/script-ext-html-webpack-plugin

0.0 3.0 0.0 95 KB

Enhances html-webpack-plugin functionality with different deployment options for your scripts including 'async', 'preload', 'prefetch', 'defer', 'module', custom attributes, and inlining.

License: MIT License

JavaScript 100.00%

script-ext-html-webpack-plugin's Introduction

Script Extension for HTML Webpack Plugin

npm version Dependency Status Build status js-semistandard-style

NPM

Enhances html-webpack-plugin functionality with different deployment options for your scripts including:

This is an extension plugin for the webpack plugin html-webpack-plugin - a plugin that simplifies the creation of HTML files to serve your webpack bundles.

The raw html-webpack-plugin incorporates all webpack-generated javascipt as synchronous<script> elements in the generated html. This plugin allows you to:

  • add standard and custom attributes to these elements;
  • inline the code in the elements;
  • add prefetch and preload resource hints for initial and dynamically loaded scripts.

Installation

You must be running webpack (1.x or 2.x) )on node 4+.

Install the plugin with npm:

$ npm install --save-dev script-ext-html-webpack-plugin

You may see an UNMET PEER DEPENDENCY warning for webpack.

This is fine; in testing, we dynamically download multiple versions of webpack (via the dynavers module).

Basic Usage

Add the plugin to your webpack config as follows:

plugins: [
  new HtmlWebpackPlugin(),
  new ScriptExtHtmlWebpackPlugin()
]  

The above configuration will actually do nothing due to the configuration defaults. Some more useful scenarios:

All scripts set to async:

plugins: [
  new HtmlWebpackPlugin(),
  new ScriptExtHtmlWebpackPlugin({
    defaultAttribute: 'async'
  })
]  

All scripts set to async except 'first.js' which is sync:

plugins: [
  new HtmlWebpackPlugin(),
  new ScriptExtHtmlWebpackPlugin({
    sync: 'first.js',
    defaultAttribute: 'async'
  })
]  

Configuration offers much more complex options:

Configuration

You must pass a hash of configuration options to the plugin to cause the addition of attributes:

  • inline: a script matching pattern defining scripts that should be inlined in the html (default: []);
  • sync: a script matching pattern defining script names that should have no attribute (default: []);
  • async: a script matching pattern defining script names that should have an async attribute (default: []);
  • defer: a script matching pattern defining script names that should have a defer attribute (default: []);
  • defaultAttribute: 'sync' | 'async' | 'defer' The default attribute to set - 'sync' actually results in no attribute (default: 'sync');
  • module: a script matching pattern defining script names that should have a type="module" attribute (default: []);
  • preload: a script matching pattern defining scripts that should have accompanying preload resource hints (default: []);
  • prefetch: a script matching pattern defining scripts that should have accompanying prefetch resource hints (default: []);
  • custom: a single hash or an array of hashes with the following structure:
    • test: a script matching pattern defining scripts that should have a custom attribute added;
    • attribute: a String attribute to add;
    • value: (optional) a String value for the attribute; if not set the attribute has no value set (equivalent of true).

A script matching pattern matches against a script's name. It can be one of:

  • a String- matches if it is a substring of the script name;
  • a RegExp;
  • an array of String's and/or RegExp's - matches if any one element matches;
  • a hash with property test with a value of one of the above.

In more complicated use cases it may prove difficult to ensure that the pattern matching for different attributes are mutually exclusive. To prevent confusion, the plugin operates a simple precedence model:

  1. if a script name matches theinline script matching pattern, it will be inlined;

  2. if a script name matches the sync script matching pattern, it will have no attribute, unless it matched condition 1;

  3. if a script name the async script matching pattern, it will have the async attribute, unless it matched conditions 1 or 2;

  4. if a script name matches the defer script matching pattern, it will have the defer attribute, unless it matched conditions 1, 2 or 3;

  5. if a script name does not match any of the previous conditions, it will have the `defaultAttribute' attribute.

The module attribute is independent of conditions 2-5, but will be ignored if the script isinlined.

Dynamically Loaded Scripts

The preload and prefetch configuration also have allow an additional property in the hash form that can be passed to include dynamically loaded (asynchronous) scripts. This property is chunks and can have one of the following String values:

  • initial: default behaviour, no asynchronour scripts;
  • async: only asynchronouse scripts;
  • all: all scripts Note that you must still supply a test script matching pattern which is also applied when selecting scripts.

Configuration Examples

All scripts with 'important' in their name are sync and all others set to defer:

plugins: [
  new HtmlWebpackPlugin(),
  new ScriptExtHtmlWebpackPlugin({
    sync: 'important'
    defaultAttribute: 'defer'
  })
]  

Alternatively, using a regular expression:

plugins: [
  new HtmlWebpackPlugin(),
  new ScriptExtHtmlWebpackPlugin({
    sync: /important/,
    defaultAttribute: 'defer'
  })
]  

All scripts with 'mod' in their name are async and type 'module', all others are sync (no explicit setting for this as it is the default):

plugins: [
  new HtmlWebpackPlugin(),
  new ScriptExtHtmlWebpackPlugin({
    async: 'mod',
    module: 'mod'
  })
]  

Script 'startup.js' is inlined whilst all other scripts are async and preloaded:

plugins: [
  new HtmlWebpackPlugin(),
  new ScriptExtHtmlWebpackPlugin({
    inline: 'startup',
    preload: /\.js$/,
    defaultAttribute: 'async'
  })
]  

All asynchronous scripts are added as preload resource hints. All other scripts are async:

plugins: [
  new HtmlWebpackPlugin(),
  new ScriptExtHtmlWebpackPlugin({
    async: /\.js$/
    preload: {
      test: /\.js$/,
      chunks: 'async'
    }
  })
]  

All scripts have custom attribute type='text/paperscript' and ui.js also has a custom attribute of id='1235':

plugins: [
  new HtmlWebpackPlugin(),
  new ScriptExtHtmlWebpackPlugin({
    custom: [
      {
        test: /\.js$/,
        attribute: 'type',
        value: 'text/paperscript'
      },
      {
        test: 'ui.js',
        attribute: 'id',
        value: '12345'
      }
    ]
  })
]  

And so on, to craziness:

plugins: [
  new HtmlWebpackPlugin(),
  new ScriptExtHtmlWebpackPlugin({
    inline: 'startup',  
    sync: [/imp(1|2){1,3}}/, 'initial'],
    defer: ['slow', /big.*andslow/],
    module: [/^((?!sync).)*/, 'mod'],
    prefetch: 'indirectly-referenced.js',
    defaultAttribute: 'async'
  })
]  

Any problems with real-world examples, just raise an issue.

A Note on Script Names

In the above examples the actual script names are used to select the deployment option. You may not wish to couple asset names to your deployment like this. Instead you can use Webpack's entry configuration to create aliases that the plugin will then use for its pattern matching. Your webpack.config.js will look something like this:

entry: {
  a: path.join(__dirname, 'lib/myFunctions.js'),
  b: path.join(__dirname, 'lib/otherFunctions.js'),
  c: path.join(__dirname, 'lib/criticalFuntions.js')
},
output: {
  ...
  filename: '[name].js'
}
plugins: [
  new HtmlWebpackPlugin(),
  new ScriptExtHtmlWebpackPlugin({
    inline: ['c'],  
    defer: ['a', 'b']
  })
]  

Inlining

Several notes and caveats apply:

  • This feature is for <script>'s only. If you wish to inline css please see the sister plugin style-ext-html-webpack-plugin.
  • Even the simplest script will be wrapped with webpack boilerplate; ensure you minify your javascript if you want your output html to be legible!
  • Hot replacement of inlined scripts will only work if caching is switched off for html-webpack-plugin:
plugins: [
    new HtmlWebpackPlugin({
      cache: false
    }),
    new ScriptExtHtmlWebpackPlugin({
      inline: ['myinlinedscript.js']
    })
]

Resource Hints

In most cases, modern browsers will intelligently preload referenced script assets. However if you wish, this plugin can add resource hint elements to the <head> element of the form:

<link rel="[preload|prefetch]" href="[scriptname]" as="script">

Use the preload and prefetch configuration options. Where preload and prefetch patterns overlap, preload takes precedence.

Possibly a more compelling use case is to preload/prefetch dynamically loaded scripts generated by Webpack's code splitting. Since v1.7.0, this plugin can do this - see 'Dynamically Loaded Scripts' above.

Notes:

  • for more on resource hints, see the w3c definition;
  • for a more complete solution that allows the preloading\fetching of assets other than scripts, see the resource-hints-webpack-plugin.

Change History

v1.8.x

  • added custom attributes
  • compatible with webpack-config - thank s @avaly

v1.7.x

  • updated for Webpack 2.5.x and updated all dependencies
  • adds asynchronous script resource hints
  • fixed issue 13 - inline functionality not working with HtmlWebpackPlugin hashing
  • fixed issue 16 - unnecessary closing tag
  • fixed issue 18 - added defensive coding against unpopulated event arguments
  • refactored for better handling of publicPath - thanks @koalaink

v1.6.x

  • works with webpack 2.2.1
  • enhanced API (no need to use array), fully backwardly compatible
  • refactor in preparation for v2

v1.5.x

  • added resource hints
  • works with webpack 2.2.0

v1.4.x

  • updated internal mechanism to use new(ish) HtmlWebpackPlugin event
  • improved test mechanism and enhanced test coverage
  • added support for publicPath for inline scripts (thanks @JustAboutJeff)
  • works with 'webpack -p' (thanks @brandongoode)

v1.3.x

  • added type="text/javascript" by default, in response to Safari 9.1.1 bug
  • removed experimental status of inline option
  • added weback 2.2.x beta support

v1.2.x

  • added inline option

v1.1.x

  • added type="module" option

v1.0.x

  • initial release

script-ext-html-webpack-plugin's People

Contributors

avaly avatar numical avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.