- Notifications
You must be signed in to change notification settings - Fork31
lets you define html tags to inject with html-webpack-plugin
License
jharris4/html-webpack-tags-plugin
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Enhanceshtml-webpack-pluginby letting you specify script or link tags to inject.
html-webpack-tags-plugin
requiresNode >= 10 andwebpack
&html-webpack-plugin
versions>= 5.- For older versions of webpack and node, please useversion 2.x of this plugin.
- This plugin used to be called
html-webpack-include-assets-plugin
. - For versions of Node older than
8.6
, please installhtml-webpack-include-assets-plugin version 1.x.
When using a plugin such ascopy-webpack-plugin you may have assets output to your build directory that are not detected/output by the html-webpack-plugin.
This plugin lets you manually resolve such issues, and also lets you inject the webpackpublicPath
or compilationhash
into your tag paths if you so choose.
You must be running webpack on node 8.x or higher
Install the plugin with npm:
$ npm install --save-dev html-webpack-tags-plugin
html-webpack-deploy-plugin is a plugin that enhances this plugin with capabilities such as:
- copying your local files and injecting them as html tags with easy to use syntax
- copying package files from your local node_modules and having them versioned automatically as they are injected as html tags
- easy configuration to stop webpack from processing certain node_modules packages so you can handle shipping certain package bundles yourself
- easy to use CDN settings so you can inject package tags that serve from a CDN for optimal performance
Require the plugin in your webpack config:
varHtmlWebpackTagsPlugin=require('html-webpack-tags-plugin');
Add the plugin to your webpack config:
output:{publicPath:'/abc/'},plugins:[newHtmlWebpackPlugin(),newHtmlWebpackTagsPlugin({tags:['a.js','b.css'],append:true})]
Which will generate html like this:
<head><!-- other head content --><linkrel="stylesheet"href="/abc/b.css"/></head><body><!-- other body content --><scripttype="text/javascript"src="/abc/a.js"></script></body>
This plugin will run and do nothing if no options are provided.
The default options for this plugin are shown below:
consturl=require('url');constDEFAULT_OPTIONS={append:true,prependExternals:true,jsExtensions:['.js'],cssExtensions:['.css'],useHash:false,addHash:(assetPath,hash)=>assetPath+'?'+hash,hash:undefined,usePublicPath:true,addPublicPath:(assetPath,publicPath)=>url.resolve(publicPath,assetPath),publicPath:undefined,tags:[],links:[],scripts:[],metas:undefined};
All options for this plugin are validated as soon as the plugin is instantiated.
The available options are:
Name | Type | Default | Description |
---|---|---|---|
append | {Boolean} | true | Whether to prepend or append the injected tags relative to any existing or webpack bundle tags (should be set tofalse when using anyscript tagexternal ) |
prependExternals | {Boolean} | true | Whether to defaultappend tofalse for any<script> tag that has anexternal option specified |
files | {Array<String>} | [] | If specified this plugin will only inject tags into the html-webpack-plugin instances that are injecting into these files (usesminimatch) |
jsExtensions | {String|Array<String>} | ['.js'] | The file extensions to use when determining if atag in thetags option is ascript |
cssExtensions | {String|Array<String>} | ['.css'] | The file extensions to use when determining if atag in thetags option is alink |
useHash | {Boolean} | false | Whether to inject the webpackcompilation.hash into the tag paths |
addHash | {Function(assetPath:String, hash:String):String} | see above | The function to call when injecting thehash into the tag paths |
hash | {Boolean|String|Function} | undefined | Shortcut to specifyinguseHash andaddHash |
usePublicPath | {Boolean} | true | Whether to inject the (webpack)publicPath into the tag paths |
addPublicPath | {Function(assetPath:String, publicPath:String):String} | see above | Whether to inject thepublicPath into the tag paths |
publicPath | {Boolean|String|Function} | undefined | Shortcut to specifyingusePublicPath andaddPublicPath |
links | {String|Object|Array<String|Object>} | [] | The tags to inject as<link> html tags |
scripts | {String|Object|Array<String|Object>} | [] | The tags to inject as<script> html tags |
tags | {String|Object|Array<String|Object>} | [] | The tags to inject as<link> or<script> html tags depending on the tagtype |
metas | {Object|Array<Object>} | undefined | The tags to inject as<meta> html tags |
Theappend
option controls whether tags are injected before or afterwebpack
ortemplate
tags.
If multiple plugins are used withappend
set tofalse then thetags will be injected in reverse order.
This option has no effect onmeta
tags.
This sampleindex.html
template:
<html><head><linkhref="template-link"></head><body><scriptsrc="template-script"></script></body></html>
And this samplewebpack
config:
{entry:{'app':'app.js','style':'style.css'// also generates style.js},plugins:[newHtmlWebpackTagsPlugin({append:false,links:'plugin-a-link',scripts:'plugin-a-script'}),newHtmlWebpackTagsPlugin({append:false,links:'plugin-b-link',scripts:'plugin-b-script'}),newHtmlWebpackTagsPlugin({append:true,links:'plugin-c-link',scripts:'plugin-c-script'}),newHtmlWebpackTagsPlugin({append:true,links:'plugin-d-link',scripts:'plugin-d-script'})]}
Will generate approximately this html:
<head><linkhref="plugin-b-link"><linkhref="plugin-a-link"><linkhref="template-link"><linkhref="style.css"><linkhref="plugin-c-link"><linkhref="plugin-d-link"></head><body><scriptsrc="plugin-b-script"></script><scriptsrc="plugin-a-script"></script><scriptsrc="template-script"></script><scriptsrc="app.js"></script><scriptsrc="style.js"></script><scriptsrc="plugin-c-link"></script><scriptsrc="plugin-d-link"></script></body>
Thehash
option is a shortcut that overrides theuseHash
andaddHash
options:
constshortcutFunction={hash:(path,hash)=>path+'?'+hash}constisTheSameAsFunction={useHash:true,addHash:(path,hash)=>path+'?'+hash}constshortcutDisabled={hash:false}constisTheSameAsDisabled={useHash:false,}
ThepublicPath
option is a shortcut that overrides theusePublicPath
andaddPublicPath
options:
constshortcutFunction={publicPath:(path,publicPath)=>publicPath+path}constisTheSameAsFunction={usePublicPath:true,addPublicPath:(path,publicPath)=>publicPath+path}constshortcutDisabled={publicPath:false}constisTheSameAsDisabled={usePublicPath:false,}constshortcutString={publicPath:'myValue'}constisTheSameAsString={usePublicPath:true,addPublicPath:(path)=>'myValue'+path}
When thetags
option is used the type of the specified tag(s) is inferred either from the file extension or an optionaltype
option that may be one of:'js' \| 'css'
|
The inferred type is used to split thetags
option intotagLinks
andtagScripts
that are injectedbefore any specifiedlinks
orscripts
options.
The following are functionally equivalent:
newHtmlWebpackTagsPlugin({tags:['style-1.css',{path:'script-2.js'},{path:'script-3-not-js.css',type:'js'},'style-4.css']});newHtmlWebpackTagsPlugin({links:['style-1.css','style-4.css'],scripts:[{path:'script-2.js'},{path:'script-3-not-js.css'}]});
Thevalue
of thetags
,links
orscripts
options can be specified in several ways:
- as aString:
newHtmlWebpackTagsPlugin({tags:'style.css'});
- as anObject:
newHtmlWebpackTagsPlugin({links:{path:'style.css'}});
- as anArray ofStrings orObjects:
newHtmlWebpackTagsPlugin({scripts:['aScript.js',{path:'bScript.js'},'cScript.js']});
When tags are specified asObjects, the followingtag object
options are available:
Name | Type | Default | Description |
---|---|---|---|
path | {String} | required* | The tag file path (used for<link href /> or<script src /> or<meta content /> )(* not required for meta tags) |
append | {Boolean} | undefined | This can be used to override the plugin levelappend option at a tag level |
type | {'js'|'css'} | undefined | Fortags assets this may be used to specify whether the tag is alink or ascript |
glob ,globPath | {String, String} | undefined | Together these two options specify aglob to run, inserting a tag with path for each match result |
globFlatten | {Boolean} | false | When used withglob andglobPath this flag controls whether glob-matched files are output with with full path (false ) or just the filename (true ) |
attributes | {Object} | undefined | The attributes to be injected into the html tags. Some attributes are filtered out byhtml-webpack-plugin .(Recommended: sethtml-webpack-plugin option:{ inject: true } ) |
sourcePath | {String} | undefined | Specify a source path to be added as an entry tohtml-webpack-plugin . Useful to trigger webpack recompilation after the asset has changed |
hash | {Boolean|String|Function} | undefined | Whether & how to inject the the webpackcompilation.hash into the tag's path |
publicPath | {Boolean|String|Function} | undefined | Whether & how to inject the (webpack)publicPath into the tag's path |
external | {Object({ packageName: String, variableName: String})} | undefined | When specified forscript tags causes{ packageName: variableName } to be added to thewebpack config's externals |
Thetag object
hash
option may be used to override the mainhash
option:
constpluginOptions={hash:true,tags:[{path:'will-have-hash-injected'},{path:'will-NOT-have-hash-injected',hash:false},{path:'will-be-sandwhiched-by-hash',hash:(path,hash)=>hash+path+hash}]}// orconstpluginOptionsDisabled={hash:false,tags:[{path:'will-NOT-have-hash-injected'},{path:'will-have-hash-injected',hash:true},]}
Thetag object
publicPath
option may be used to override the mainpublicPath
option:
constpluginOptions={publicPath:true,tags:[{path:'will-have-public-path-injected'},{path:'will-NOT-have-public-path-injected',publicPath:false},{path:'will-be-sandwhiched-by-public-path',publicPath:(path,publicPath)=>publicPath+path+publicPath}]}// orconstpluginOptionsDisabled={publicPath:false,tags:[{path:'will-NOT-have-public-path-injected'},{path:'will-have-public-path-injected',publicPath:true},]}
UsingHtmlWebpackTagsPlugin
andCopyWebpackPlugin
to inject copied assets from anode_modules
package:
plugins:[newCopyWebpackPlugin([{from:'node_modules/bootstrap/dist/css',to:'css/'},{from:'node_modules/bootstrap/dist/fonts',to:'fonts/'}]),newHtmlWebpackPlugin(),newHtmlWebpackTagsPlugin({links:['css/bootstrap.min.css','css/bootstrap-theme.min.css']})]
Using theappend
option set totrue andfalse at the same time:
Whenappend
is set tofalse and there are multiple instances of this plugins, the second plugin's tags will be inserted before the first plugin's tags.
plugins:[newCopyWebpackPlugin([{from:'node_modules/bootstrap/dist/css',to:'css/'},{from:'node_modules/bootstrap/dist/fonts',to:'fonts/'}]),newHtmlWebpackPlugin(),newHtmlWebpackTagsPlugin({links:['css/bootstrap.min.css','css/bootstrap-theme.min.css'],append:false}),newHtmlWebpackTagsPlugin({links:['css/custom.css'],append:true})]
Using customjsExtensions
:
plugins:[newHtmlWebpackPlugin(),newHtmlWebpackTagsPlugin({tags:['dist/output.js','lib/content.jsx'],jsExtensions:['.js','.jsx']})]
Using custompublicPath
:
plugins:[newCopyWebpackPlugin([{from:'node_modules/bootstrap/dist/css',to:'css/'},{from:'node_modules/bootstrap/dist/fonts',to:'fonts/'}]),newHtmlWebpackPlugin(),newHtmlWebpackTagsPlugin({tags:['css/bootstrap.min.css','css/bootstrap-theme.min.css'],publicPath:'myPublicPath/'})]
This will overridewebpack
'spublicPath
setting for the purposes of path prefixing.
Or to injecttag objects
without prepending thepublicPath
:
plugins:[newHtmlWebpackPlugin(),newHtmlWebpackTagsPlugin({tags:['css/no-public-path.min.css','http://some.domain.com.js'],publicPath:false})]
Manually specifying a tagtag object
type
:
plugins:[newCopyWebpackPlugin([{from:'node_modules/bootstrap/dist/js',to:'js/'},{from:'node_modules/bootstrap/dist/css',to:'css/'},{from:'node_modules/bootstrap/dist/fonts',to:'fonts/'}]),newHtmlWebpackPlugin(),newHtmlWebpackTagsPlugin({tags:['/js/bootstrap.min.js','/css/bootstrap.min.css','/css/bootstrap-theme.min.css',{path:'https://fonts.googleapis.com/css?family=Material+Icons',type:'css'}]})]
Adding customattributes
totag objects
:
The bootstrap-theme<link>
tag will be given anid="bootstrapTheme"
attribute.
plugins:[newCopyWebpackPlugin([{from:'node_modules/bootstrap/dist/css',to:'css/'},{from:'node_modules/bootstrap/dist/fonts',to:'fonts/'}]),newHtmlWebpackPlugin(),newHtmlWebpackTagsPlugin({tags:['/css/bootstrap.min.css',{path:'/css/bootstrap-theme.min.css',attributes:{id:'bootstrapTheme'}}],append:false,publicPath:''})]
Using thehash
option to inject the webpack compilation hash:
When thehash
option is set totrue
, tag paths will be injected with a hash value.
TheaddHash
option can be used to control how the hash is injected.
plugins:[newCopyWebpackPlugin([{from:'node_modules/bootstrap/dist/css',to:'css/'},{from:'node_modules/bootstrap/dist/fonts',to:'fonts/'}]),newHtmlWebpackPlugin(),newHtmlWebpackTagsPlugin({tags:['css/bootstrap.min.css','css/bootstrap-theme.min.css'],append:false,hash:true})]
Using thehash
option to customize the injection of the webpack compilation hash:
When thehash
option is set to afunction
, tag paths will be replaced with the result of executing that function.
plugins:[newCopyWebpackPlugin([{from:'somepath/somejsfile.js',to:'js/somejsfile.[hash].js'},{from:'somepath/somecssfile.css',to:'css/somecssfile.[hash].css'}]),newHtmlWebpackPlugin(),newHtmlWebpackTagsPlugin({tags:[{path:'js',glob:'*.js',globPath:'somepath'}],tags:[{path:'css',glob:'*.css',globPath:'somepath'}],append:false,hash:function(assetName,hash){assetName=assetName.replace(/\.js$/,'.'+hash+'.js');assetName=assetName.replace(/\.css$/,'.'+hash+'.css');returnassetName;}})]
Specifying specifichtml-webpack-plugin
instances to inject to with thefiles
option:
plugins:[newCopyWebpackPlugin([{from:'node_modules/bootstrap/dist/css',to:'css/'},{from:'node_modules/bootstrap/dist/fonts',to:'fonts/'}]),newHtmlWebpackPlugin({filename:'a/index.html'}),newHtmlWebpackPlugin({filename:'b/index.html'}),newHtmlWebpackTagsPlugin({files:['a/**/*.html'],tags:['css/a.css'],append:true}),newHtmlWebpackTagsPlugin({files:['b/**/*.html'],tags:['css/b.css'],append:true})]
Specifyingtag object
path searches usings aglob
:
Note that sincecopy-webpack-plugin
does not actually copy the files to webpack's output directory untilafterhtml-webpack-plugin
has completed, it is necessary to use theglobPath
to retrieve filename matches relative to the original location of any such files.
plugins:[newCopyWebpackPlugin([{from:'node_modules/bootstrap/dist/css',to:'css/'},{from:'node_modules/bootstrap/dist/fonts',to:'fonts/'}]),newHtmlWebpackPlugin(),newHtmlWebpackTagsPlugin({tags:[{path:'css',glob:'*.css',globPath:'node_modules/bootstrap/dist/css/'}],append:true})]
Using thelinks
option to injectlink
tags:
output:{publicPath:'/my-public-path/'},plugins:[newCopyWebpackPlugin([{from:'node_modules/bootstrap/dist/css',to:'css/'},{from:'node_modules/bootstrap/dist/fonts',to:'fonts/'}]),newHtmlWebpackPlugin(),newHtmlWebpackTagsPlugin({tags:[],links:[{path:'asset/path',attributes:{rel:'icon'}},{path:'/absolute/asset/path',publicPath:false,attributes:{rel:'manifest'}}]})]
Will append the following<link>
elements into the index template html
<head><!-- previous header content --><linkrel="icon"href="/my-public-path/asset/path"><linkrel="manifest"href="/absolute/asset/path"></head>
Note that the second link's href was not prefixed with the webpackpublicPath
because the second link asset'spublicPath
was set tofalse
.
Using thescripts
option to injectscript
tags:
output:{publicPath:'/my-public-path/'},plugins:[newCopyWebpackPlugin([{from:'node_modules/bootstrap/dist/js',to:'js/'}]),newHtmlWebpackPlugin(),newHtmlWebpackTagsPlugin({tags:[],scripts:[{path:'asset/path',attributes:{type:'text/javascript'}}]})]
Will append the following<script>
element into the index template html
<body><!-- previous body content --><scriptsrc="/my-public-path/asset/path"type="text/javascript"></script></body>
Specifyingscripts
withexternal
options:
output:{publicPath:'/my-public-path/'},plugins:[newCopyWebpackPlugin([{from:'node_modules/bootstrap/dist/js',to:'js/'}]),newHtmlWebpackPlugin(),newHtmlWebpackTagsPlugin({tags:[],scripts:[{path:'asset/path',external:{packageName:'react',variableName:'React'},attributes:{type:'text/javascript'}}]})]
Will add the followingproperties
to thewebpack.compilation.options.externals
:
constcompilationConfig={ ...otherProperties,externals:{"react":"React"}};
This can be useful to control which packages webpack is bundling versus ones you can serve from a CDN.
Note thatscript
tags withexternal
specified need to be placedbefore the webpack bundle tags.
This means that you should always setappend
tofalse when using thescript
external
option.
TheprependExternals
option was added in2.0.10
to handle this case automatically.
Using themetas
option to injectmeta
tags:
output:{publicPath:'/my-public-path/'},plugins:[newCopyWebpackPlugin([{from:'node_modules/bootstrap/dist/js',to:'js/'}]),newHtmlWebpackPlugin(),newHtmlWebpackTagsPlugin({metas:[{path:'asset/path',attributes:{name:'the-meta-name'}}]})]
Will inject the following<meta>
element into the index template html
<head><!-- previous header content --><metacontent="/my-public-path/asset/path"name="the-meta-name"></head>
Note that theappend
settings has no effect on how the<meta>
elements are injected.
Some users have encountered issues with plugin ordering.
It is advisable to always place any
HtmlWebpackPlugin
pluginsbefore anyHtmlWebpackTagsPlugin
plugins in your webpack config.When
append
isfalse tags are injected before any other tags. This means that if you have two instances of this plugin both with append set to false, then thesecond
plugin's tags will be injectedbefore thefirst
plugin's tags.
Setting theexternal
option for ascript
tag object
requires caution to ensure that the scripts are in the correct order.
It is advisable to always set
append
tofalse so thatexternal
<script> tags are always insertedbefore thewebpack
bundle <script> tags.The order that you use when you specify a list of external links matters. For example,
<script src="react.js"/>
should come before<script src="react-router.s"/>
ifreact-router
has a peer dependency onreact
.
Changing HtmlWebpackPlugininject
option from itsdefault value
oftrue may cause issues.
- This pluginrecommends that the HtmlWebpackPlugin
inject
option to betrue for attribute injection to work.
Disabling injection means that you are agreeing to template how the tags should be generated in yourtemplates/index.html
file like this:
<html><head><!-- other head content --><% for (var cssIndex = 0; cssIndex<htmlWebpackPlugin.files.css.length;cssIndex++){%><linkrel="stylesheet"href="<%= htmlWebpackPlugin.files.css[cssIndex] %>"><% } %></head><body><!-- other body content --><% for (var jsIndex = 0; jsIndex<htmlWebpackPlugin.files.js.length;jsIndex++){%><scriptsrc="<%= htmlWebpackPlugin.files.js[jsIndex] %>"></script><% } %></body></html>
The default templating engine forhtml-webpack-plugin
seems to be based onlodash
.
With the above template we might use the followingwebpack
config whichdisablesinject
:
output:{publicPath:'/the-public-path/'},plugins:[newHtmlWebpackPlugin({<b>inject: false</b>}),newHtmlWebpackTagsPlugin({tags:[{path:'css/bootstrap-theme.min.css',attributes:{id:'bootstrapTheme'}}],links:[{href:'the-ref',attributes:{rel:'icon'}}],append:true})]
The problem is that thetemplate syntax
does not seem to allow injection of more thanone attribute value
, namely thepath
(href
orsrc
)
This means it willgenerate anindex.html
that ismissing all of the scriptattributes
like this:
<head><linkhref="/the-public-path/css/bootstrap-theme.min.css"><linkhref="/the-public-path/the-ref"></head>
If the templating engine supports injection ofentire tags instead of just thehref
/src
attribute value then working withinject
set tofalse may be possible.
About
lets you define html tags to inject with html-webpack-plugin
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors11
Uh oh!
There was an error while loading.Please reload this page.