6dcc45c5fb13829f66f7db17fab945e2f31f4111f621f3ccb7e09f4b2999586328e0cc5a7b2ce0590b007a7cd305359bd945a90b7dc41d3777fbd56eebcfe7 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. Script Extension for HTML Webpack Plugin
  2. ========================================
  3. [![npm version](https://badge.fury.io/js/script-ext-html-webpack-plugin.svg)](http://badge.fury.io/js/script-ext-html-webpack-plugin) [![Dependency Status](https://david-dm.org/numical/script-ext-html-webpack-plugin.svg)](https://david-dm.org/numical/script-ext-html-webpack-plugin) [![Build status](https://travis-ci.org/numical/script-ext-html-webpack-plugin.svg)](https://travis-ci.org/numical/script-ext-html-webpack-plugin) [![js-semistandard-style](https://img.shields.io/badge/code%20style-semistandard-brightgreen.svg?style=flat-square)](https://github.com/Flet/semistandard)
  4. [![NPM](https://nodei.co/npm/script-ext-html-webpack-plugin.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/script-ext-html-webpack-plugin/)
  5. Deprecation Warning
  6. -------------------
  7. **tl;dr**
  8. This project is no longer maintained. It does not support Webpack 5.
  9. **A bit more detail**
  10. Any look at the [project activity](https://github.com/numical/script-ext-html-webpack-plugin/pulse) will show that I have not been able to maintain this project adequately.
  11. The advent of version 5 of Webpack requires another bout of refactoring that I simply have no time for.
  12. Consequently v2.15.0 will be the last version of this plugin.
  13. My thanks to all users, and especially to all contributors, of this plugin over the years.
  14. My apologies to all those whose webpack 5 migration has been made more complicated by this decision.
  15. **But I still want to use the plugin...**
  16. Feel free!
  17. My last update works with versions of v4.44.2 of webpack and v4.5.0 of html-webpack-plugin.
  18. Forkers feel free! That's what the licence is for.
  19. In fact, if you fork with an intention to support on-going development, let me know!
  20. I'll happily link to your repository here and offer some tips (main one: ditch backward compatibility - it's a pain).
  21. I will formally archive this repository at the end of the 2020.
  22. Summary
  23. -------
  24. Enhances [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin)
  25. functionality with different deployment options for your scripts including:
  26. - [`async`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#Attributes) attribute;
  27. - [`defer`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#Attributes) attribute;
  28. - [`type="module"`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#Attributes) attribute;
  29. - any custom attributes you wish to add;
  30. - inlining;
  31. - [`preload`](https://www.w3.org/TR/preload/) resource hint;
  32. - [`prefetch`](https://www.w3.org/TR/resource-hints/#dfn-prefetch) resource hint
  33. This is an extension plugin for the [webpack](http://webpack.github.io) plugin [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) - a plugin that simplifies the creation of HTML files to serve your webpack bundles.
  34. The raw [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) incorporates all webpack-generated javascipt as synchronous`<script>` elements in the generated html. This plugin allows you to:
  35. - add standard and custom attributes to these elements;
  36. - inline the code in the elements;
  37. - add prefetch and preload resource hints for initial and dynamically loaded scripts.
  38. Installation
  39. ------------
  40. You must be running webpack (1.x, 2.x, 3.x, 4.x) on node 6+.
  41. Install the plugin with npm:
  42. ```shell
  43. $ npm install --save-dev script-ext-html-webpack-plugin
  44. ```
  45. Not that you will need v3.0.6+ or v4.x of [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin)
  46. For those requiring earlier versions of node, please use the [last 1.x version](https://github.com/numical/script-ext-html-webpack-plugin/tree/v1.8.8) of this plugin. However please note this does not have webpack 4.x support:
  47. ```shell
  48. $ npm install --save-dev script-ext-html-webpack-plugin@1.8.8
  49. ```
  50. You may see an `UNMET PEER DEPENDENCY` warnings for webpack and various plugins.
  51. This is fine; in testing, we dynamically download multiple versions of webpack (via the [dynavers](https://github.com/numical/dynavers) module).
  52. Basic Usage
  53. -----------
  54. Add the plugin to your webpack config as follows:
  55. ```javascript
  56. plugins: [
  57. new HtmlWebpackPlugin(),
  58. new ScriptExtHtmlWebpackPlugin()
  59. ]
  60. ```
  61. The order is important - the plugin must come **after** HtmlWebpackPlugin.
  62. The above configuration will actually do nothing due to the configuration defaults.
  63. Some more useful scenarios:
  64. All scripts set to `async`:
  65. ```javascript
  66. plugins: [
  67. new HtmlWebpackPlugin(),
  68. new ScriptExtHtmlWebpackPlugin({
  69. defaultAttribute: 'async'
  70. })
  71. ]
  72. ```
  73. All scripts set to `async` except 'first.js' which is sync:
  74. ```javascript
  75. plugins: [
  76. new HtmlWebpackPlugin(),
  77. new ScriptExtHtmlWebpackPlugin({
  78. sync: 'first.js',
  79. defaultAttribute: 'async'
  80. })
  81. ]
  82. ```
  83. Configuration offers much more complex options:
  84. Configuration
  85. -------------
  86. You must pass a hash of configuration options to the plugin to cause the addition of attributes:
  87. - `inline`: a __script matching pattern__ defining scripts that should be inlined in the html (default: `[]`);
  88. - `sync`: a __script matching pattern__ defining script names that should have no attribute (default: `[]`);
  89. - `async`: a __script matching pattern__ defining script names that should have an `async` attribute (default: `[]`);
  90. - `defer`: a __script matching pattern__ defining script names that should have a `defer` attribute (default: `[]`);
  91. - `defaultAttribute`: `'sync' | 'async' | 'defer'` The default attribute to set - `'sync'` actually results in no attribute (default: `'sync'`);
  92. - `module`: a __script matching pattern__ defining script names that should have a
  93. `type="module"` attribute (default: `[]`);
  94. - `preload`: a __script matching pattern__ defining scripts that should have accompanying preload resource hints (default: `[]`);
  95. - `prefetch`: a __script matching pattern__ defining scripts that should have accompanying prefetch resource hints (default: `[]`);
  96. - `custom`: a single hash or an array of hashes with the following structure:
  97. - `test`: a **script matching pattern** defining scripts that should have a custom attribute added;
  98. - `attribute`: a `String` attribute to add;
  99. - `value`: (optional) a `String` value for the attribute; if not set the attribute has no value set (equivalent of `true`).
  100. A __script matching pattern__ matches against a script's name. It can be one of:
  101. - a `String`- matches if it is a substring of the script name;
  102. - a `RegExp`;
  103. - an array of `String`'s and/or `RegExp`'s - matches if any one element matches;
  104. - a hash with property `test` with a value of one of the above.
  105. 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:
  106. 1. if a script name matches the`inline` script matching pattern, it will be inlined;
  107. 2. if a script name matches the `sync` script matching pattern, it will have no attribute, *unless* it matched condition 1;
  108. 3. if a script name the `async` script matching pattern, it will have the `async` attribute, *unless* it matched conditions 1 or 2;
  109. 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;
  110. 5. if a script name does not match any of the previous conditions, it will have the `defaultAttribute' attribute.
  111. The `module` attribute is independent of conditions 2-5, but will be ignored if the script isinlined.
  112. Dynamically Loaded Scripts
  113. --------------------------
  114. 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:
  115. - `initial`: default behaviour, no asynchronour scripts;
  116. - `async`: only asynchronouse scripts;
  117. - `all`: all scripts
  118. Note that you must still supply a `test` __script matching pattern__ which is also applied when selecting scripts.
  119. Configuration Examples
  120. ---------------------
  121. All scripts with 'important' in their name are sync and all others set to `defer`:
  122. ```javascript
  123. plugins: [
  124. new HtmlWebpackPlugin(),
  125. new ScriptExtHtmlWebpackPlugin({
  126. sync: 'important',
  127. defaultAttribute: 'defer'
  128. })
  129. ]
  130. ```
  131. Alternatively, using a regular expression:
  132. ```javascript
  133. plugins: [
  134. new HtmlWebpackPlugin(),
  135. new ScriptExtHtmlWebpackPlugin({
  136. sync: /important/,
  137. defaultAttribute: 'defer'
  138. })
  139. ]
  140. ```
  141. 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):
  142. ```javascript
  143. plugins: [
  144. new HtmlWebpackPlugin(),
  145. new ScriptExtHtmlWebpackPlugin({
  146. async: 'mod',
  147. module: 'mod'
  148. })
  149. ]
  150. ```
  151. Script 'startup.js' is inlined whilst all other scripts are async and preloaded:
  152. ```javascript
  153. plugins: [
  154. new HtmlWebpackPlugin(),
  155. new ScriptExtHtmlWebpackPlugin({
  156. inline: 'startup',
  157. preload: /\.js$/,
  158. defaultAttribute: 'async'
  159. })
  160. ]
  161. ```
  162. All scripts are preloaded with a ```crossorigin``` attribute set to enable CDN's:
  163. ```javascript
  164. plugins: [
  165. new HtmlWebpackPlugin(),
  166. new ScriptExtHtmlWebpackPlugin({
  167. custom: {
  168. test: /\.js$/,
  169. attribute: 'crossorigin',
  170. value: 'anonymous'
  171. },
  172. preload: {
  173. test: /\.js$/
  174. }
  175. })
  176. ]
  177. ```
  178. All asynchronous scripts are added as `preload` resource hints. All other scripts are `async`:
  179. ```javascript
  180. plugins: [
  181. new HtmlWebpackPlugin(),
  182. new ScriptExtHtmlWebpackPlugin({
  183. async: /\.js$/,
  184. preload: {
  185. test: /\.js$/,
  186. chunks: 'async'
  187. }
  188. })
  189. ]
  190. ```
  191. All scripts have custom attribute `type='text/paperscript'` and ui.js also has a custom attribute of `id='1235'`:
  192. ```javascript
  193. plugins: [
  194. new HtmlWebpackPlugin(),
  195. new ScriptExtHtmlWebpackPlugin({
  196. custom: [
  197. {
  198. test: /\.js$/,
  199. attribute: 'type',
  200. value: 'text/paperscript'
  201. },
  202. {
  203. test: 'ui.js',
  204. attribute: 'id',
  205. value: '12345'
  206. }
  207. ]
  208. })
  209. ]
  210. ```
  211. And so on, to craziness:
  212. ```javascript
  213. plugins: [
  214. new HtmlWebpackPlugin(),
  215. new ScriptExtHtmlWebpackPlugin({
  216. inline: 'startup',
  217. sync: [/imp(1|2){1,3}}/, 'initial'],
  218. defer: ['slow', /big.*andslow/],
  219. module: [/^((?!sync).)*/, 'mod'],
  220. prefetch: 'indirectly-referenced.js',
  221. defaultAttribute: 'async'
  222. })
  223. ]
  224. ```
  225. Any problems with real-world examples, just raise an issue.
  226. A Note on Script Names
  227. ----------------------
  228. 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](https://webpack.js.org/concepts/entry-points/#object-syntax) to create aliases that the plugin will then use for its pattern matching. Your `webpack.config.js` will look something like this:
  229. ```javascript
  230. entry: {
  231. a: path.join(__dirname, 'lib/myFunctions.js'),
  232. b: path.join(__dirname, 'lib/otherFunctions.js'),
  233. c: path.join(__dirname, 'lib/criticalFuntions.js')
  234. },
  235. output: {
  236. ...
  237. filename: '[name].js'
  238. }
  239. plugins: [
  240. new HtmlWebpackPlugin(),
  241. new ScriptExtHtmlWebpackPlugin({
  242. inline: ['c'],
  243. defer: ['a', 'b']
  244. })
  245. ]
  246. ```
  247. Inlining
  248. --------
  249. Several notes and caveats apply:
  250. * This feature is for `<script>`'s only. If you wish to inline css please see the sister plugin
  251. [style-ext-html-webpack-plugin](https://github.com/numical/style-ext-html-webpack-plugin).
  252. * Even the simplest script will be wrapped with webpack boilerplate; ensure you minify your javascript if you want your output html to be legible!
  253. * Hot replacement of inlined scripts will only work if caching is [switched off](https://github.com/jantimon/html-webpack-plugin#configuration) for html-webpack-plugin:
  254. ```javascript
  255. plugins: [
  256. new HtmlWebpackPlugin({
  257. cache: false
  258. }),
  259. new ScriptExtHtmlWebpackPlugin({
  260. inline: ['myinlinedscript.js']
  261. })
  262. ]
  263. ```
  264. * An alternative approach, based on jade templates is illustrated in the [HtmlWebpackPlugin inline example](https://github.com/jantimon/html-webpack-plugin/tree/master/examples/inline).
  265. Resource Hints
  266. --------------
  267. In most cases, modern browsers will intelligently preload referenced script assets.
  268. However if you wish, this plugin can add resource hint elements to the `<head>` element of the form:
  269. ```html
  270. <link rel="[preload|prefetch]" href="[scriptname]" as="script">
  271. ```
  272. Use the `preload` and `prefetch` configuration options.
  273. Where `preload` and `prefetch` patterns overlap, `preload` takes precedence.
  274. Possibly a more compelling use case is to preload/prefetch dynamically loaded scripts generated by Webpack's [code splitting](https://webpack.js.org/guides/code-splitting-require). Since v1.7.0, this plugin can do this - see 'Dynamically Loaded Scripts' above.
  275. Notes:
  276. - custom attributes will be added to resource hints with the same *script matching pattern*. This is useful for adding such attributes as ```crossorigin="anonymous"``` - see the Configuration Examples above;
  277. - for more on resource hints, see the [`w3c`](https://www.w3.org/TR/resource-hints) definition;
  278. - for a more complete solution that allows the preloading\fetching of assets other than scripts, see the [resource-hints-webpack-plugin](https://github.com/jantimon/resource-hints-webpack-plugin).
  279. Change History
  280. --------------
  281. v2.1.5
  282. * end of life version
  283. * updated all dependencies
  284. * fixes some tests to accomodate change in html-webpack-plugin output
  285. * added end-of-life section to README.
  286. v2.1.x
  287. * support for changes in html-webpack-plugin 4.x since alpha and beta
  288. * custom attributes now added to resource hints too (see [pull request 53](https://github.com/numical/script-ext-html-webpack-plugin/pull/53) for discussion)
  289. * update dependencies
  290. v2.0.x
  291. * support html-webpack-plugin 4.x - huge thanks to [@snadn](https://github.com/snadn)
  292. * support webpack 4.x - huge thanks to [@sherlock1982](https://github.com/sherlock1982)
  293. * node 9.x 10,x, 11.x testing
  294. * remove support for node 4.x and 5.x
  295. * remove Appveyor config
  296. * temporary remove Handlebars test until loader supports webpack 4.x
  297. v1.8.x
  298. * added custom attributes - now works on inline scripts as well e.g. for CSP nonces, -thanks [@niieani](https://github.com/niieani) and [@phallguy](https://github.com/phallguy)
  299. * compatible with [webpack-config](https://www.npmjs.com/package/webpack-config) - thanks [@avaly](https://github.com/avaly)
  300. * node v8+ and webback 3.x testing
  301. * resource hints handle public paths without end separators - thanks [@albv](https://githun.com/albv)
  302. * updated dependencies (including dev and peer) - thanks [@ai](https://github.com/ai), [@malikshahzad228](https://github.com/malikshahzad228)
  303. * windows-proofed public paths - thanks [@mstijak](https://github.com/mstijak), [@Jesseyx](https://github.com/Jesseyx)
  304. * added appveyor support for windows build and testing - CURRENTLY SWITCHED OFF
  305. v1.7.x
  306. * updated for Webpack 2.5.x and updated all dependencies
  307. * adds asynchronous script resource hints
  308. * fixed [issue 13](https://github.com/numical/script-ext-html-webpack-plugin/issues/13) - inline functionality not working with HtmlWebpackPlugin hashing
  309. * fixed [issue 16](https://github.com/numical/script-ext-html-webpack-plugin/issues/16) - unnecessary <link> closing tag
  310. * fixed [issue 18](https://github.com/numical/script-ext-html-webpack-plugin/issues/18) - added defensive coding against unpopulated event arguments
  311. * refactored for better handling of `publicPath` - thanks [@koalaink](https://github.com/koalaink)
  312. v1.6.x
  313. * works with webpack 2.2.1
  314. * enhanced API (no need to use array), fully backwardly compatible
  315. * refactor in preparation for v2
  316. v1.5.x
  317. * added resource hints
  318. * works with webpack 2.2.0
  319. v1.4.x
  320. * updated internal mechanism to use new(ish) [HtmlWebpackPlugin event](https://github.com/jantimon/html-webpack-plugin#events)
  321. * improved test mechanism and enhanced test coverage
  322. * added support for `publicPath` for inline scripts - thanks [@JustAboutJeff](https://github.com/JustAboutJeff)
  323. * works with 'webpack -p' - thanks [@brandongoode](https://github.com/brandongoode)
  324. v1.3.x
  325. * added `type="text/javascript"` by default, in response to [Safari 9.1.1 bug](https://github.com/jantimon/html-webpack-plugin/issues/309)
  326. * removed experimental status of inline option
  327. * added weback 2.2.x beta support
  328. v1.2.x
  329. * added inline option
  330. v1.1.x
  331. * added `type="module"` option
  332. v1.0.x
  333. * initial release