{"id":22746146,"url":"https://github.com/rspack-contrib/html-rspack-tags-plugin","last_synced_at":"2025-04-14T10:13:29.787Z","repository":{"id":258078898,"uuid":"874095692","full_name":"rspack-contrib/html-rspack-tags-plugin","owner":"rspack-contrib","description":"Enhances `rspack.HtmlRspackPlugin` by letting you specify script or link tags to inject.","archived":false,"fork":false,"pushed_at":"2024-10-17T10:21:08.000Z","size":137,"stargazers_count":1,"open_issues_count":1,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-14T10:13:25.637Z","etag":null,"topics":["rspack","rspack-plugin","webpack"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rspack-contrib.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-10-17T08:44:45.000Z","updated_at":"2024-10-20T02:41:32.000Z","dependencies_parsed_at":"2024-10-17T15:25:35.104Z","dependency_job_id":null,"html_url":"https://github.com/rspack-contrib/html-rspack-tags-plugin","commit_stats":null,"previous_names":["rspack-contrib/html-rspack-tags-plugin"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rspack-contrib%2Fhtml-rspack-tags-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rspack-contrib%2Fhtml-rspack-tags-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rspack-contrib%2Fhtml-rspack-tags-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rspack-contrib%2Fhtml-rspack-tags-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rspack-contrib","download_url":"https://codeload.github.com/rspack-contrib/html-rspack-tags-plugin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248860167,"owners_count":21173342,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["rspack","rspack-plugin","webpack"],"created_at":"2024-12-11T02:11:40.218Z","updated_at":"2025-04-14T10:13:29.756Z","avatar_url":"https://github.com/rspack-contrib.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"html-rspack-tags-plugin\n========================================\n\n[![npm version](https://badge.fury.io/js/html-rspack-tags-plugin.svg)](https://badge.fury.io/js/html-rspack-tags-plugin) [![Build Status](https://travis-ci.org/jharris4/html-rspack-tags-plugin.svg?branch=master)](https://travis-ci.org/jharris4/html-rspack-tags-plugin) [![js-semistandard-style](https://img.shields.io/badge/code%20style-semistandard-brightgreen.svg?style=flat-square)](https://github.com/Flet/semistandard)\n\nEnhances [rspack.HtmlRspackPlugin](https://rspack.dev/plugins/rspack/html-rspack-plugin)\nby letting you specify script or link tags to inject.\n\nNotice\n------------\n\nThis plugin is forked from [jharris4/html-webpack-tags-plugin](https://github.com/jharris4/html-webpack-tags-plugin).\n\nChange list:\n\n- Rename package to `html-rspack-tags-plugin`\n- Rename plugin to `HtmlRspackTagsPlugin`\n- Remove `webpack` dependency and use `@rspack/core` instead\n- Remove `HtmlRspackPlugin` dependency and use `rspack.HtmlRspackPlugin` instead\n- Remove `copy-webpack-plugin` dev dependency and use `rspack.CopyRspackPlugin` instead\n- Remove `mini-css-extract-plugin` dev dependency and use `rspack.CssExtractRspackPlugin` instead\n\n\nMotivation\n------------\n\nWhen using a plugin such as [CopyRspackPlugin](https://rspack.dev/plugins/rspack/copy-rspack-plugin) you may have assets output to your build directory that are not detected/output by the HtmlRspackPlugin.\n\nThis plugin lets you manually resolve such issues, and also lets you inject the rspack `publicPath` or compilation `hash` into your tag paths if you so choose.\n\nInstallation\n------------\nYou must be running rspack on node 16.x or higher\n\nInstall the plugin with npm:\n```shell\n$ npm install --save-dev html-rspack-tags-plugin\n```\n\nBasic Usage\n-----------\nRequire the plugin in your rspack config:\n\n```javascript\nvar HtmlRspackTagsPlugin = require('html-rspack-tags-plugin');\nvar rspack = require('@rspack/core');\n```\n\nAdd the plugin to your rspack config:\n\n```javascript\noutput: {\n  publicPath: '/abc/'\n},\nplugins: [\n  new rspack.HtmlRspackPlugin(),\n  new HtmlRspackTagsPlugin({ tags: ['a.js', 'b.css'], append: true })\n]\n```\n\nWhich will generate html like this:\n\n```html\n\u003chead\u003e\n  \u003c!-- other head content --\u003e\n  \u003clink rel=\"stylesheet\" href=\"/abc/b.css\"/\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n  \u003c!-- other body content --\u003e\n  \u003cscript type=\"text/javascript\" src=\"/abc/a.js\"\u003e\u003c/script\u003e\n\u003c/body\u003e\n```\n\nConfiguration\n-------\n\n### Default Options\n\nThis plugin will run and do nothing if no options are provided.\n\nThe default options for this plugin are shown below:\n\n```js\nconst url = require('url');\n\nconst DEFAULT_OPTIONS = {\n  append: true,\n  prependExternals: true,\n  jsExtensions: ['.js'],\n  cssExtensions: ['.css'],\n  useHash: false,\n  addHash: (assetPath, hash) =\u003e assetPath + '?' + hash,\n  hash: undefined,\n  usePublicPath: true,\n  addPublicPath: (assetPath, publicPath) =\u003e url.resolve(publicPath, assetPath),\n  publicPath: undefined,\n  tags: [],\n  links: [],\n  scripts: [],\n  metas: undefined\n};\n```\n\n---\n### Options\n\nAll options for this plugin are validated as soon as the plugin is instantiated.\n\nThe available options are:\n\n|Name|Type|Default|Description|\n|:--:|:--:|:-----:|:----------|\n|**`append`**|`{Boolean}`|`true`|Whether to prepend or append the injected tags relative to any existing or rspack bundle tags (should be set to **false** when using any `script` tag **`external`**) |\n|**`prependExternals`**|`{Boolean}`|`true`|Whether to default **`append`** to **false** for any `\u003cscript\u003e` `tag` that has an **`external`** option specified|\n|**`files`**|`{Array\u003cString\u003e}`|`[]`|If specified this plugin will only inject tags into the HtmlRspackPlugin instances that are injecting into these files  (uses [minimatch](https://github.com/isaacs/minimatch))|\n|**`jsExtensions`**|`{String\\|Array\u003cString\u003e}`|`['.js']`|The file extensions to use when determining if a `tag` in the `tags` option is a `script`|\n|**`cssExtensions`**|`{String\\|Array\u003cString\u003e}`|`['.css']`|The file extensions to use when determining if a `tag` in the `tags` option is a `link`|\n|**`useHash`**|`{Boolean}`|`false`|Whether to inject the rspack `compilation.hash` into the tag paths|\n|**`addHash`**|`{Function(assetPath:String, hash:String):String}`|`see above`|The function to call when injecting the `hash` into the tag paths|\n|**`hash`**|`{Boolean\\|String\\|Function}`|`undefined`|Shortcut to specifying `useHash` and `addHash`|\n|**`usePublicPath`**|`{Boolean}`|`true`|Whether to inject the (rspack) `publicPath` into the tag paths|\n|**`addPublicPath`**|`{Function(assetPath:String, publicPath:String):String}`|`see above`|Whether to inject the `publicPath` into the tag paths|\n|**`publicPath`**|`{Boolean\\|String\\|Function}`|`undefined`|Shortcut to specifying `usePublicPath` and `addPublicPath`|\n|**`links`**|`{String\\|Object\\|Array\u003cString\\|Object\u003e}`|`[]`|The tags to inject as `\u003clink\u003e` html tags|\n|**`scripts`**|`{String\\|Object\\|Array\u003cString\\|Object\u003e}`|`[]`|The tags to inject as `\u003cscript\u003e` html tags|\n|**`tags`**|`{String\\|Object\\|Array\u003cString\\|Object\u003e}`|`[]`|The tags to inject as `\u003clink\u003e` or `\u003cscript\u003e` html tags depending on the tag `type`|\n|**`metas`**|`{Object\\|Array\u003cObject\u003e}`|`undefined`|The tags to inject as `\u003cmeta\u003e` html tags|\n\n---\n\nThe **`append`** option controls whether tags are injected before or after `rspack` or `template` tags.\n\nIf multiple plugins are used with **`append`** set to **false** then the **tags will be injected in reverse order**.\n\nThis option has no effect on **`meta`** tags.\n\nThis sample `index.html` template:\n\n```html\n\u003chtml\u003e\n  \u003chead\u003e\u003clink href=\"template-link\"\u003e\u003c/head\u003e\n  \u003cbody\u003e\u003cscript src=\"template-script\"\u003e\u003c/script\u003e\u003c/body\u003e\n\u003c/html\u003e\n```\n\nAnd this sample `rspack` config:\n```js\n{\n  entry: {\n    'app': 'app.js',\n    'style': 'style.css' // also generates style.js\n  },\n  plugins: [\n    new HtmlRspackTagsPlugin({\n      append: false, links: 'plugin-a-link', scripts: 'plugin-a-script'\n    }),\n    new HtmlRspackTagsPlugin({\n      append: false, links: 'plugin-b-link', scripts: 'plugin-b-script'\n    }),\n    new HtmlRspackTagsPlugin({\n      append: true, links: 'plugin-c-link', scripts: 'plugin-c-script'\n    }),\n    new HtmlRspackTagsPlugin({\n      append: true, links: 'plugin-d-link', scripts: 'plugin-d-script'\n    })\n  ]\n}\n```\n\nWill generate approximately this html:\n```html\n\u003chead\u003e\n  \u003clink href=\"plugin-b-link\"\u003e\n  \u003clink href=\"plugin-a-link\"\u003e\n  \u003clink href=\"template-link\"\u003e\n  \u003clink href=\"style.css\"\u003e\n  \u003clink href=\"plugin-c-link\"\u003e\n  \u003clink href=\"plugin-d-link\"\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n  \u003cscript src=\"plugin-b-script\"\u003e\u003c/script\u003e\n  \u003cscript src=\"plugin-a-script\"\u003e\u003c/script\u003e\n  \u003cscript src=\"template-script\"\u003e\u003c/script\u003e\n  \u003cscript src=\"app.js\"\u003e\u003c/script\u003e\n  \u003cscript src=\"style.js\"\u003e\u003c/script\u003e\n  \u003cscript src=\"plugin-c-link\"\u003e\u003c/script\u003e\n  \u003cscript src=\"plugin-d-link\"\u003e\u003c/script\u003e\n\u003c/body\u003e\n```\n\n---\n\nThe **`hash`** option is a shortcut that overrides the **`useHash`** and **`addHash`** options:\n\n```js\nconst shortcutFunction = {\n  hash: (path, hash) =\u003e path + '?' + hash\n}\nconst isTheSameAsFunction = {\n  useHash: true,\n  addHash: (path, hash) =\u003e path + '?' + hash\n}\n\nconst shortcutDisabled = {\n  hash: false\n}\nconst isTheSameAsDisabled = {\n  useHash: false,\n}\n```\n\n---\n\nThe **`publicPath`** option is a shortcut that overrides the **`usePublicPath`** and **`addPublicPath`** options:\n\n```js\nconst shortcutFunction = {\n  publicPath: (path, publicPath) =\u003e publicPath + path\n}\nconst isTheSameAsFunction = {\n  usePublicPath: true,\n  addPublicPath: (path, publicPath) =\u003e publicPath + path\n}\n\nconst shortcutDisabled = {\n  publicPath: false\n}\nconst isTheSameAsDisabled = {\n  usePublicPath: false,\n}\n\nconst shortcutString = {\n  publicPath: 'myValue'\n}\nconst isTheSameAsString = {\n  usePublicPath: true,\n  addPublicPath: (path) =\u003e 'myValue' + path\n}\n\n```\n\n---\n\nWhen the **`tags`** option is used the type of the specified tag(s) is inferred either from the file extension or an optional **`type`** option that may be one of: `'js' \\| 'css'`|\n\nThe inferred type is used to split the **`tags`** option into `tagLinks` and `tagScripts` that are injected **before** any specified **`links`** or **`scripts`** options.\n\nThe following are functionally equivalent:\n\n```js\nnew HtmlRspackTagsPlugin({\n  tags: [\n    'style-1.css',\n    { path: 'script-2.js' },\n    { path: 'script-3-not-js.css', type: 'js' },\n    'style-4.css'\n  ]\n});\n\nnew HtmlRspackTagsPlugin({\n  links: [\n    'style-1.css',\n    'style-4.css'\n  ],\n  scripts: [\n    { path: 'script-2.js' },\n    { path: 'script-3-not-js.css' }\n  ]\n});\n```\n---\n\nThe `value` of the **`tags`**, **`links`** or **`scripts`** options can be specified in several ways:\n\n- as a **String**:\n\n```js\nnew HtmlRspackTagsPlugin({ tags: 'style.css' });\n```\n\n- as an **Object**:\n\n```js\nnew HtmlRspackTagsPlugin({ links: { path: 'style.css' } });\n```\n\n- as an **Array** of **String**s or **Object**s:\n\n```js\nnew HtmlRspackTagsPlugin({\n  scripts: [\n    'aScript.js',\n    {\n      path: 'bScript.js'\n    },\n    'cScript.js'\n  ]\n});\n```\n\n---\n\nWhen tags are specified as **Object**s, the following `tag object` options are available:\n\n|Name|Type|Default|Description|\n|:--:|:--:|:-----:|:----------|\n|**`path`**|`{String}`|**`required*`**|The tag file path (used for `\u003clink href /\u003e` or `\u003cscript src /\u003e` or `\u003cmeta content /\u003e`) **`(* not required for meta tags)`**|\n|**`append`**|`{Boolean}`|`undefined`| This can be used to override the plugin level **`append`** option at a tag level|\n|**`type`**|`{'js'\\|'css'}`|`undefined`|For **`tags`** assets this may be used to specify whether the tag is a `link` or a `script`|\n|**`glob`**, **`globPath`**|`{String, String}`|`undefined`|Together these two options specify a [glob](https://github.com/isaacs/node-glob) to run, inserting a tag with path for each match result|\n|**`globFlatten`**|`{Boolean}`|`false`|When used with **`glob`** and **`globPath`** this flag controls whether glob-matched files are output with with full path (`false`) or just the filename (`true`)|\n|**`attributes`**|`{Object}`|`undefined`|The attributes to be injected into the html tags. Some attributes are filtered out by `HtmlRspackPlugin`. **(Recommended:** set `HtmlRspackPlugin` option: `{ inject: true }`**)**|\n|**`sourcePath`**|`{String}`|`undefined`|Specify a source path to be added as an entry to `HtmlRspackPlugin`. Useful to trigger rspack recompilation after the asset has changed|\n|**`hash`**|`{Boolean\\|String\\|Function}`|`undefined`|Whether \u0026 how to inject the the rspack `compilation.hash` into the tag's path|\n|**`publicPath`**|`{Boolean\\|String\\|Function}`|`undefined`|Whether \u0026 how to inject the (rspack) `publicPath` into the tag's path|\n|**`external`**|`{Object({ packageName: String, variableName: String})}`|`undefined`|When specified for **script** tags causes `{ packageName: variableName }` to be added to the [rspack config's externals](https://rspack.dev/config/externals)|\n\n---\n\nThe `tag object` **`hash`** option may be used to override the main **`hash`** option:\n\n```js\nconst pluginOptions = {\n  hash: true,\n  tags: [\n    {\n      path: 'will-have-hash-injected'\n    },\n    {\n      path: 'will-NOT-have-hash-injected',\n      hash: false\n    },\n    {\n      path: 'will-be-sandwhiched-by-hash',\n      hash: (path, hash) =\u003e hash + path + hash\n    }\n  ]\n}\n// or\nconst pluginOptionsDisabled = {\n  hash: false,\n  tags: [\n    {\n      path: 'will-NOT-have-hash-injected'\n    },\n    {\n      path: 'will-have-hash-injected',\n      hash: true\n    },\n  ]\n}\n```\n\n---\n\nThe `tag object` **`publicPath`** option may be used to override the main **`publicPath`** option:\n\n```js\nconst pluginOptions = {\n  publicPath: true,\n  tags: [\n    {\n      path: 'will-have-public-path-injected'\n    },\n    {\n      path: 'will-NOT-have-public-path-injected',\n      publicPath: false\n    },\n    {\n      path: 'will-be-sandwhiched-by-public-path',\n      publicPath: (path, publicPath) =\u003e publicPath + path + publicPath\n    }\n  ]\n}\n// or\nconst pluginOptionsDisabled = {\n  publicPath: false,\n  tags: [\n    {\n      path: 'will-NOT-have-public-path-injected'\n    },\n    {\n      path: 'will-have-public-path-injected',\n      publicPath: true\n    },\n  ]\n}\n```\n\n-----\n\nExamples\n-------\n\n_____\n\nUsing `HtmlRspackTagsPlugin` and `CopyRspackPlugin` to inject copied assets from a `node_modules` package:\n\n```javascript\nplugins: [\n  new rspack.CopyRspackPlugin([\n    { from: 'node_modules/bootstrap/dist/css', to: 'css/'},\n    { from: 'node_modules/bootstrap/dist/fonts', to: 'fonts/'}\n  ]),\n  new rspack.HtmlRspackPlugin(),\n  new HtmlRspackTagsPlugin({\n    links: ['css/bootstrap.min.css', 'css/bootstrap-theme.min.css']\n  })\n]\n```\n\n_____\n\nUsing the **`append`** option set to **true** and **false** at the same time:\n\n## **Note on Plugin Ordering**\n\nWhen **`append`** is set to **false** and there are multiple instances of this plugins, the second plugin's tags will be inserted before the first plugin's tags.\n\n```javascript\nplugins: [\n  new rspack.CopyRspackPlugin([\n    { from: 'node_modules/bootstrap/dist/css', to: 'css/'},\n    { from: 'node_modules/bootstrap/dist/fonts', to: 'fonts/'}\n  ]),\n  new rspack.HtmlRspackPlugin(),\n  new HtmlRspackTagsPlugin({\n    links: ['css/bootstrap.min.css', 'css/bootstrap-theme.min.css'],\n    append: false\n  }),\n  new HtmlRspackTagsPlugin({\n    links: ['css/custom.css'],\n    append: true\n  })\n]\n```\n\n_____\n\nUsing custom **`jsExtensions`**:\n\n```javascript\nplugins: [\n  new rspack.HtmlRspackPlugin(),\n  new HtmlRspackTagsPlugin({\n    tags: ['dist/output.js', 'lib/content.jsx'],\n    jsExtensions: ['.js', '.jsx']\n  })\n]\n```\n\n_____\n\nUsing custom **`publicPath`**:\n\n```javascript\nplugins: [\n  new rspack.CopyRspackPlugin([\n    { from: 'node_modules/bootstrap/dist/css', to: 'css/'},\n    { from: 'node_modules/bootstrap/dist/fonts', to: 'fonts/'}\n  ]),\n  new rspack.HtmlRspackPlugin(),\n  new HtmlRspackTagsPlugin({\n    tags: ['css/bootstrap.min.css', 'css/bootstrap-theme.min.css'],\n    publicPath: 'myPublicPath/'\n  })\n]\n```\n\nThis will override `rspack`'s `publicPath` setting for the purposes of path prefixing.\n\n_____\n\nOr to inject `tag objects` **without** prepending the **`publicPath`**:\n\n```javascript\nplugins: [\n  new rspack.HtmlRspackPlugin(),\n  new HtmlRspackTagsPlugin({\n    tags: ['css/no-public-path.min.css', 'http://some.domain.com.js'],\n    publicPath: false\n  })\n]\n```\n\n_____\n\nManually specifying a tag `tag object` **`type`**:\n\n```javascript\nplugins: [\n  new rspack.CopyRspackPlugin([\n    { from: 'node_modules/bootstrap/dist/js', to: 'js/'},\n    { from: 'node_modules/bootstrap/dist/css', to: 'css/'},\n    { from: 'node_modules/bootstrap/dist/fonts', to: 'fonts/'}\n  ]),\n  new rspack.HtmlRspackPlugin(),\n  new HtmlRspackTagsPlugin({\n    tags: [\n      '/js/bootstrap.min.js',\n      '/css/bootstrap.min.css',\n      '/css/bootstrap-theme.min.css',\n      {\n        path: 'https://fonts.googleapis.com/css?family=Material+Icons',\n        type: 'css'\n      }\n    ]\n  })\n]\n```\n\n_____\n\nAdding custom **`attributes`** to `tag objects`:\n\nThe bootstrap-theme `\u003clink\u003e` tag will be given an `id=\"bootstrapTheme\"` attribute.\n\n```javascript\nplugins: [\n  new rspack.CopyRspackPlugin([\n    { from: 'node_modules/bootstrap/dist/css', to: 'css/'},\n    { from: 'node_modules/bootstrap/dist/fonts', to: 'fonts/'}\n  ]),\n  new rspack.HtmlRspackPlugin(),\n  new HtmlRspackTagsPlugin({\n    tags: [\n      '/css/bootstrap.min.css',\n      { path: '/css/bootstrap-theme.min.css', attributes: { id: 'bootstrapTheme' } }\n    ],\n    append: false,\n    publicPath: ''\n  })\n]\n```\n\n_____\n\nUsing the **`hash`** option to inject the rspack compilation hash:\n\nWhen the **`hash`** option is set to `true`, tag paths will be injected with a hash value.\n\nThe **`addHash`** option can be used to control how the hash is injected.\n\n```javascript\n  plugins: [\n    new rspack.CopyRspackPlugin([\n      { from: 'node_modules/bootstrap/dist/css', to: 'css/'},\n      { from: 'node_modules/bootstrap/dist/fonts', to: 'fonts/'}\n    ]),\n    new rspack.HtmlRspackPlugin(),\n    new HtmlRspackTagsPlugin({\n      tags: ['css/bootstrap.min.css', 'css/bootstrap-theme.min.css'],\n      append: false,\n      hash: true\n    })\n  ]\n```\n\n_____\n\nUsing the **`hash`** option to customize the injection of the rspack compilation hash:\n\nWhen the **`hash`** option is set to a `function`, tag paths will be replaced with the result of executing that function.\n\n```javascript\nplugins: [\n  new rspack.CopyRspackPlugin([\n    { from: 'somepath/somejsfile.js', to: 'js/somejsfile.[hash].js' },\n    { from: 'somepath/somecssfile.css', to: 'css/somecssfile.[hash].css' }\n  ]),\n  new rspack.HtmlRspackPlugin(),\n  new HtmlRspackTagsPlugin({\n    tags: [{ path: 'js', glob: '*.js', globPath: 'somepath' }],\n    tags: [{ path: 'css', glob: '*.css', globPath: 'somepath' }],\n    append: false,\n    hash: function(assetName, hash) {\n      assetName = assetName.replace(/\\.js$/, '.' + hash + '.js');\n      assetName = assetName.replace(/\\.css$/, '.' + hash + '.css');\n      return assetName;\n    }\n  })\n]\n```\n\n_____\n\nSpecifying specific `HtmlRspackPlugin` instances to inject to with the **`files`** option:\n\n```javascript\nplugins: [\n  new rspack.CopyRspackPlugin([\n    { from: 'node_modules/bootstrap/dist/css', to: 'css/'},\n    { from: 'node_modules/bootstrap/dist/fonts', to: 'fonts/'}\n  ]),\n  new rspack.HtmlRspackPlugin({\n    filename: 'a/index.html'\n  }),\n  new rspack.HtmlRspackPlugin({\n    filename: 'b/index.html'\n  }),\n  new HtmlRspackTagsPlugin({\n    files: ['a/**/*.html'],\n    tags: ['css/a.css'],\n    append: true\n  }),\n  new HtmlRspackTagsPlugin({\n    files: ['b/**/*.html'],\n    tags: ['css/b.css'],\n    append: true\n  })\n]\n```\n\n_____\n\nSpecifying `tag object` path searches usings a **`glob`**:\n\nNote that since `CopyRspackPlugin` does not actually copy the files to rspack's output directory until *after* `HtmlRspackPlugin` has completed, it is necessary to use the **`globPath`** to retrieve filename matches relative to the original location of any such files.\n\n```javascript\nplugins: [\n  new rspack.CopyRspackPlugin([\n    { from: 'node_modules/bootstrap/dist/css', to: 'css/'},\n    { from: 'node_modules/bootstrap/dist/fonts', to: 'fonts/'}\n  ]),\n  new rspack.HtmlRspackPlugin(),\n  new HtmlRspackTagsPlugin({\n    tags: [{ path: 'css', glob: '*.css', globPath: 'node_modules/bootstrap/dist/css/' }],\n    append: true\n  })\n]\n```\n\n_____\n\nUsing the **`links`** option to inject `link` tags:\n\n```javascript\noutput: {\n  publicPath: '/my-public-path/'\n},\nplugins: [\n  new rspack.CopyRspackPlugin([\n    { from: 'node_modules/bootstrap/dist/css', to: 'css/'},\n    { from: 'node_modules/bootstrap/dist/fonts', to: 'fonts/'}\n  ]),\n  new rspack.HtmlRspackPlugin(),\n  new HtmlRspackTagsPlugin({\n    tags: [],\n    links: [\n      {\n        path: 'asset/path',\n        attributes: {\n          rel: 'icon'\n        }\n      },\n      {\n        path: '/absolute/asset/path',\n        publicPath: false,\n        attributes: {\n          rel: 'manifest'\n        }\n      }\n    ]\n  })\n]\n```\n\nWill append the following `\u003clink\u003e` elements into the index template html\n\n```html\n\u003chead\u003e\n  \u003c!-- previous header content --\u003e\n  \u003clink rel=\"icon\" href=\"/my-public-path/asset/path\"\u003e\n  \u003clink rel=\"manifest\" href=\"/absolute/asset/path\"\u003e\n\u003c/head\u003e\n```\n\nNote that the second link's href was not prefixed with the rspack `publicPath` because the second link asset's **`publicPath`** was set to `false`.\n\n\n_____\n\nUsing the **`scripts`** option to inject `script` tags:\n\n```javascript\noutput: {\n  publicPath: '/my-public-path/'\n},\nplugins: [\n  new rspack.CopyRspackPlugin([\n    { from: 'node_modules/bootstrap/dist/js', to: 'js/'}\n  ]),\n  new rspack.HtmlRspackPlugin(),\n  new HtmlRspackTagsPlugin({\n    tags: [],\n    scripts: [\n      {\n        path: 'asset/path',\n        attributes: {\n          type: 'text/javascript'\n        }\n      }\n    ]\n  })\n]\n```\n\nWill append the following `\u003cscript\u003e` element into the index template html\n\n```html\n\u003cbody\u003e\n  \u003c!-- previous body content --\u003e\n  \u003cscript src=\"/my-public-path/asset/path\" type=\"text/javascript\"\u003e\u003c/script\u003e\n\u003c/body\u003e\n```\n\n\n_____\n\nSpecifying **`scripts`** with **`external`** options:\n\n```javascript\noutput: {\n  publicPath: '/my-public-path/'\n},\nplugins: [\n  new rspack.CopyRspackPlugin([\n    { from: 'node_modules/bootstrap/dist/js', to: 'js/'}\n  ]),\n  new rspack.HtmlRspackPlugin(),\n  new HtmlRspackTagsPlugin({\n    tags: [],\n    scripts: [\n      {\n        path: 'asset/path',\n        external: {\n          packageName: 'react',\n          variableName: 'React'\n        },\n        attributes: {\n          type: 'text/javascript'\n        }\n      }\n    ]\n  })\n]\n```\n\nWill add the following `properties` to the `rspack.compilation.options.externals`:\n\n```js\nconst compilationConfig = {\n  ...otherProperties,\n  externals: {\n    \"react\": \"React\"\n  }\n};\n```\n\nThis can be useful to control which packages rspack is bundling versus ones you can serve from a CDN.\n\nNote that `script` tags with **`external`** specified need to be placed **before** the rspack bundle tags.\n\nThis means that you should always set **`append`** to **false** when using the `script` **`external`** option.\n\nThe **`prependExternals`** option was added in `2.0.10` to handle this case automatically.\n\n\n_____\n\nUsing the **`metas`** option to inject `meta` tags:\n\n```javascript\noutput: {\n  publicPath: '/my-public-path/'\n},\nplugins: [\n  new rspack.CopyRspackPlugin([\n    { from: 'node_modules/bootstrap/dist/js', to: 'js/'}\n  ]),\n  new rspack.HtmlRspackPlugin(),\n  new HtmlRspackTagsPlugin({\n    metas: [\n      {\n        path: 'asset/path',\n        attributes: {\n          name: 'the-meta-name'\n        }\n      }\n    ]\n  })\n]\n```\n\nWill inject the following `\u003cmeta\u003e` element into the index template html\n\n```html\n\u003chead\u003e\n  \u003c!-- previous header content --\u003e\n  \u003cmeta content=\"/my-public-path/asset/path\" name=\"the-meta-name\"\u003e\n\u003c/head\u003e\n```\n\nNote that the **`append`** settings has no effect on how the `\u003cmeta\u003e` elements are injected.\n\n\n_____\n\nCaveats\n-------\n\n___\n\n#### Plugin Ordering\n\nSome users have encountered issues with plugin ordering.\n\n- It is advisable to always place any `HtmlRspackPlugin` plugins **before** any `HtmlRspackTagsPlugin` plugins in your rspack config.\n\n- When **`append`** is **false** 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 the `second` plugin's tags will be injected **before** the `first` plugin's tags.\n\n---\n\n#### rspack `externals`\n\nSetting the **`external`** option for a `script` `tag object` requires caution to ensure that the scripts are in the correct order.\n\n- It is advisable to always set **`append`** to **false** so that `external` \\\u003cscript\\\u003e tags are always inserted **before** the `rspack` bundle \\\u003cscript\\\u003e tags.\n\n- The order that you use when you specify a list of external links matters. For example, `\u003cscript src=\"react.js\"/\u003e` should come before `\u003cscript src=\"react-router.s\"/\u003e` if `react-router` has a peer dependency on `react`.\n\n---\n\n#### HtmlRspackPlugin `inject` option\n\nChanging HtmlRspackPlugin **`inject`** option from its `default value` of **true** may cause issues.\n\n- This plugin **recommends** that the HtmlRspackPlugin **`inject`** option to be **true** for attribute injection to work.\n\n**Disabling injection** means that you are agreeing to template how the tags should be generated in your `templates/index.html` file like this:\n\n```html\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003c!-- other head content --\u003e\n    \u003c% for (var cssIndex = 0; cssIndex \u003c htmlRspackPlugin.files.css.length; cssIndex++) { %\u003e\n    \u003clink rel=\"stylesheet\" href=\"\u003c%= htmlRspackPlugin.files.css[cssIndex] %\u003e\"\u003e\n    \u003c% } %\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003c!-- other body content --\u003e\n    \u003c% for (var jsIndex = 0; jsIndex \u003c htmlRspackPlugin.files.js.length; jsIndex++) { %\u003e\n    \u003cscript src=\"\u003c%= htmlRspackPlugin.files.js[jsIndex] %\u003e\"\u003e\u003c/script\u003e\n    \u003c% } %\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\nThe default templating engine for `HtmlRspackPlugin` seems to be based on **`lodash`**.\n\nWith the above template we might use the following `rspack` config which **disables** **`inject`**:\n\n```javascript\noutput: {\n  publicPath: '/the-public-path/'\n},\nplugins: [\n  new rspack.HtmlRspackPlugin({ \u003cb\u003einject: false\u003c/b\u003e }),\n  new HtmlRspackTagsPlugin({\n    tags: [{ path: 'css/bootstrap-theme.min.css', attributes: { id: 'bootstrapTheme' } }],\n    links: [{ href: 'the-ref', attributes: { rel: 'icon' } }],\n    append: true\n  })\n]\n```\n\nThe problem is that the `template syntax` does not seem to allow injection of more than `one attribute value`, namely the `path` (**`href`** or **`src`**)\n\nThis means it will **generate** an `index.html` that is **missing** all of the script **`attributes`** like this:\n\n```html\n\u003chead\u003e\n  \u003clink href=\"/the-public-path/css/bootstrap-theme.min.css\"\u003e\n  \u003clink href=\"/the-public-path/the-ref\"\u003e\n\u003c/head\u003e\n```\n\nIf the templating engine supports injection of **entire tags** instead of just the `href`/`src` attribute value then working with **`inject`** set to **false** may be possible.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frspack-contrib%2Fhtml-rspack-tags-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frspack-contrib%2Fhtml-rspack-tags-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frspack-contrib%2Fhtml-rspack-tags-plugin/lists"}