HtmlRspackPlugin
rspack.HtmlRspackPlugin generates HTML files for Rspack builds and injects the JavaScript and CSS files required by their entry points. It can also set the document title, add a favicon, and generate <base> and <meta> tags.
- Examples: Explore common use cases.
- Options: Review types, defaults, and examples.
- Template syntax: See supported interpolation and control statements.
- Hooks: Modify asset URLs, tags, and HTML.
For help choosing between the built-in plugin and the JavaScript html-rspack-plugin, see the HTML guide.
Examples
Default output
By default, the plugin emits index.html with the assets required by every entry point.
With the built-in template, the generated dist/index.html is equivalent to:
By default, the plugin injects scripts with defer into <head>. If an entry also produces CSS, the corresponding <link> tags are inserted into <head>. With multiple entry points, the HTML includes assets from all of them.
Generate multiple HTML files
To generate a separate HTML file for each entry point, register multiple rspack.HtmlRspackPlugin instances:
- Use
filenameto name each HTML file. - Use
chunksto select the entry-point assets included in each HTML file.
The following configuration emits foo.html and bar.html. Each file contains the assets required by its matching entry point, including runtime and shared assets.
Module scripts
When output.module is enabled and scriptLoading is not set, the plugin emits <script type="module"> instead of <script defer>:
Production minification
In production mode (mode: 'production'), the plugin minifies the generated HTML when minify is not set. In other modes, HTML is minified only when minify is enabled explicitly.
Use a template file
If src/index.ejs exists in the Rspack context, the plugin uses it as the template automatically. Otherwise, it uses the built-in template.
To customize the HTML structure, you can also use template to specify an HTML file. The plugin injects the required JavaScript, CSS, and favicon tags into it.
Use template string
You can also provide the HTML template directly through templateContent:
Use template function
For dynamically generated template content, use a function in either of these forms:
- Pass the function directly to
templateContent:
- Specify a
.jsor.cjsfile intemplate:
Template parameters
Use templateParameters to customize the values passed when rendering an HTML template. Templates receive the following serializable parameters by default:
htmlRspackPlugin: Data exposed by the pluginhtmlRspackPlugin.options: Normalized plugin optionshtmlRspackPlugin.tags: Generated tags prepared for insertionhtmlRspackPlugin.tags.headTags: List of<base>,<meta>,<title>,<link>, and<script>tags for injection in<head>htmlRspackPlugin.tags.bodyTags: List of<script>tags for injection in<body>
htmlRspackPlugin.files: Asset URLs selected for the current HTML filehtmlRspackPlugin.files.js: Selected JavaScript asset URLshtmlRspackPlugin.files.css: Selected CSS asset URLshtmlRspackPlugin.files.favicon: Generated favicon URL whenfaviconis configuredhtmlRspackPlugin.files.publicPath: Effective public path used for asset URLs
rspackConfig: Selected Rspack settingsrspackConfig.mode: Current build moderspackConfig.output.publicPath: Effective public path for the current HTML file, including apublicPathoverriderspackConfig.output.crossOriginLoading: Configured cross-origin loading value
When a JavaScript function renders the template, it can also access the Rspack compilation object. That object is not passed when templateParameters is false or a function.
In a built-in template, use EJS-style interpolation to read these parameters:
In a JavaScript template function, the parameters are passed as an ordinary JavaScript object:
In templates rendered by the built-in engine, call toHtml() to convert a tag or tag list to HTML. In JavaScript template functions, tags and tag lists provide toString() and can be interpolated directly.
If the template inserts htmlRspackPlugin.tags manually, set inject to false; otherwise, the plugin inserts those tags twice.
Compared with HtmlWebpackPlugin:
- Template paths do not support loader syntax such as
loader!./template.html - The
compilationobject is only available when using a template function, with thetemplateParametersrestrictions described above
Options
Pass the following options to new rspack.HtmlRspackPlugin(). All examples reuse the rspack import from the first example.
title
- Type:
string - Default:
undefined
Sets the <title> of the generated HTML. When automatic injection is enabled, the plugin replaces an existing <title> in the template or adds one to <head>.
When omitted, a custom template keeps its own title. The built-in template uses rspack. Setting inject to false prevents title from being applied automatically, but the value remains available as htmlRspackPlugin.options.title.
Generated HTML fragment:
filename
-
Type:
-
Default:
'index.html'
Sets the HTML asset path and filename relative to output.path. When omitted, the plugin emits index.html in the output directory.
-
String: Emits the HTML at the specified path. The value can include a subdirectory and filename placeholders such as
[name]and[contenthash]. A[name]placeholder emits one HTML file for each statically configured entry. -
Function: Calls the function once for each statically configured entry, passing its name as the argument. The return value becomes the corresponding HTML filename.
The [name] and function forms do not support a function-valued Rspack entry. They only control HTML filenames; every generated file still receives the same entry assets selected by chunks and excludeChunks. Register separate plugin instances when each page needs a different asset set.
template
- Type:
string - Default:
undefined
Sets the template file. Relative paths are resolved from the Rspack context. templateContent takes precedence when both options are set.
When omitted, the plugin looks for src/index.ejs in context and falls back to its built-in HTML document if the file does not exist.
-
HTML file: Reads the file as text, renders it with the built-in template syntax, and injects the generated tags.
index.html -
JavaScript module: A path ending in
.jsor.cjsis loaded as a CommonJS module. Its exported function receives the template parameters and returns the HTML string, either directly or through a promise.template.cjs
templateContent
-
Type:
-
Default:
undefined
Provides the template directly without reading a file. When set, it takes precedence over template and the default template lookup.
-
String: Renders the string with the built-in template syntax, then injects the generated tags.
-
Function: Calls the function with the final template parameters. The returned string becomes the HTML template result and is not processed as EJS. The function can be asynchronous.
When omitted, the plugin first uses template if it is set. Otherwise, it looks for src/index.ejs and then falls back to the built-in document.
templateParameters
-
Type:
-
Default:
undefined
Controls the parameters passed to an HTML template or template function. The built-in values are described in Template parameters.
-
Object: Merges the object's string properties into the built-in parameters. Properties with the same name replace the built-in value.
-
Boolean:
truepreserves the built-in parameters and is equivalent to omitting the option.falsepasses an empty object to the template. -
Function: Calls the function with the serializable built-in parameters and uses its returned object as the complete final parameter object. Return the original properties when the template still needs them. The function can be asynchronous.
The compilation parameter is available only to a JavaScript template function when templateParameters is omitted, true, or an object. It is not passed to string templates, a templateParameters function, or a template function when templateParameters is false.
inject
- Type:
boolean | 'head' | 'body' - Default:
true
Controls automatic insertion of the tags generated by the plugin. When injection is enabled, stylesheets, the title, <base>, <meta>, and favicon tags are inserted into <head>. The 'head' and 'body' values change only the placement of <script> tags.
-
true: Inserts scripts into<body>whenscriptLoadingis'blocking'; otherwise, inserts them into<head>. This is also the behavior wheninjectis omitted. -
'head'or'body': Inserts scripts into the selected element, regardless ofscriptLoading. Stylesheet and metadata tags remain in<head>. -
false: Disables automatic insertion of all generated tags, including scripts, stylesheets, title,<base>,<meta>, and favicon tags. Tags already present in the template are not removed.
With false, the generated tags remain available through htmlRspackPlugin.tags. A template rendered by the built-in engine can insert them with toHtml(); a JavaScript template function can interpolate them directly. A configured favicon is still emitted as an asset.
publicPath
- Type:
string - Default:
undefined
Sets the URL prefix for JavaScript, CSS, and favicon URLs in the generated HTML. The plugin adds a trailing slash when needed. This option takes precedence over output.publicPath.
When omitted, the plugin uses output.publicPath. An auto output public path is resolved relative to each HTML filename, so an HTML file in a subdirectory can reference assets with paths such as ../main.js.
base
-
Type:
-
Default:
undefined
Creates a <base> tag in <head>. When omitted, no base tag is generated. inject: false prevents the tag from being inserted automatically.
-
String: Uses the string as the
hrefattribute.Generated HTML fragment:
-
Object: Sets the optional
hrefandtargetattributes. An object with neither attribute produces no tag.Generated HTML fragment:
scriptLoading
- Type:
'blocking' | 'defer' | 'module' | 'systemjs-module' - Default:
'module'whenoutput.moduleis enabled, otherwise'defer'
Sets the attributes on generated <script> tags and determines their default injection position. An explicit inject: 'head' or inject: 'body' overrides that position. This option does not change the format of the emitted JavaScript.
-
'blocking': Adds no loading attribute. With the defaultinject, scripts are inserted into<body>.Generated HTML fragment:
-
'defer': Adds the booleandeferattribute. With the defaultinject, scripts are inserted into<head>.Generated HTML fragment:
-
'module': Addstype="module". Module scripts are deferred by browsers, and the defaultinjectinserts them into<head>.Generated HTML fragment:
-
'systemjs-module': Addstype="systemjs-module". The defaultinjectinserts these scripts into<head>.Generated HTML fragment:
chunks
- Type:
string[] - Default:
undefined
Selects entry points whose JavaScript and CSS files are included in the HTML. Each value is compared with an entry point name using exact string equality; it does not match an arbitrary chunk ID, asset filename, or module path. Unknown names are ignored.
When omitted, every entry point is selected before excludeChunks is applied. Selecting an entry point also includes the runtime and shared files required by that entry.
With the default chunksSortMode: 'auto', chunks first limits the entry points and excludeChunks then removes matches. With 'manual', a provided chunks array instead becomes the final ordered entry list. If chunks is omitted, excludeChunks still filters the compilation's entry point order.
excludeChunks
- Type:
string[] - Default:
undefined
Excludes entry points from the generated HTML. Each value is compared with an entry point name using exact string equality; it does not match asset filenames, module paths, or non-entry chunks. Unknown names have no effect.
In the default chunksSortMode: 'auto', exclusions are applied after chunks, so an entry present in both arrays is excluded. With 'manual', a provided chunks array is the final ordered list and excludeChunks is not applied; when chunks is omitted, exclusions still apply to the compilation's entry point order. If excludeChunks is omitted, no selected entry point is excluded.
chunksSortMode
- Type:
'auto' | 'manual' - Default:
'auto'
Controls the order in which selected entry points contribute their files to the generated tags.
-
'auto': Uses the compilation's entry point order after applyingchunksandexcludeChunks. -
'manual': Uses the order ofchunks, ignoring unknown entry names. Whenchunksis omitted, it uses the compilation's entry point order after applyingexcludeChunks. Whenchunksis present,excludeChunksis not applied.
minify
- Type:
boolean - Default:
truein production mode, otherwisefalse
Controls whether the generated HTML is minified after template rendering and tag injection. An explicit value overrides the mode-dependent default.
favicon
- Type:
string - Default:
undefined
Sets the path of a favicon file. Relative paths are resolved from the Rspack context. The plugin emits the file at the output root using its basename and generates a <link rel="icon"> tag whose URL follows publicPath.
When omitted, no favicon asset or tag is generated. With inject: false, the asset is still emitted and exposed as htmlRspackPlugin.files.favicon, but the <link> tag is not inserted automatically.
Generated HTML fragment:
meta
-
Type:
-
Default:
{}
Creates additional <meta> tags in <head>. Each top-level key becomes the default name attribute. The built-in template's <meta charset="utf-8"> is independent of this option. When the object is empty or the option is omitted, no additional meta tags are generated. inject: false prevents them from being inserted automatically.
-
String value: Uses the top-level key as
nameand the string ascontent.Generated HTML fragment:
-
Object value: Adds every property as an attribute. A
nameproperty overrides the name derived from the top-level key.Generated HTML fragment:
hash
- Type:
boolean - Default:
undefined
If true, appends the Rspack compilation hash as a query string to generated JavaScript, CSS, and favicon URLs. This changes references in the HTML, not the emitted asset filenames. When omitted or false, the plugin leaves those URLs unchanged.
Template syntax
The built-in template engine supports EJS-style interpolation and basic control flow, but it does not execute arbitrary JavaScript. The following examples show the commonly used forms.
Escaped output <%-
Escapes the content within the interpolation:
Unescaped output <%=
Does not escape the content within the interpolation:
Control statements
The following example combines for in iteration with an if condition:
Hooks
HtmlRspackPlugin exposes hooks for modifying generated tags and HTML. Call rspack.HtmlRspackPlugin.getCompilationHooks to access them:
Hook data exposes the original constructor options as data.plugin.options. Additional custom fields are preserved there for hook consumers but do not affect HTML generation by themselves.
beforeAssetTagGeneration
This hook runs after the plugin collects asset URLs from the compilation and before it creates tags.
Modify assets.js, assets.css, or assets.favicon to add or replace URLs used to create tags. Values added by the hook are used as-is: the hook does not prepend publicPath or emit the referenced files.
- Type:
AsyncSeriesWaterfallHook<[BeforeAssetTagGenerationData]> - Parameters:
Only changes to assets.js, assets.css, and assets.favicon affect the tags generated automatically by the plugin. Other fields do not affect automatic tag generation, but templates can still read them through htmlRspackPlugin.files.
The following code adds the URL extra-script.js, which produces a <script defer src="extra-script.js"></script> tag in the final HTML.
alterAssetTags
This hook runs after asset tags are created and before they are assigned to <head> or <body>.
Modify assetTags to add, remove, or update tags.
-
Type:
AsyncSeriesWaterfallHook<[AlterAssetTagsData]> -
Parameters:
Only changes to assetTags affect the generated HTML. Changes to other fields are ignored by this plugin.
Attribute names are normalized to lowercase. Attribute values are handled as follows:
true: Adds a valueless attribute, for example<script defer specialattribute src="main.js"></script>.- String: Adds an attribute with that value, for example
<script defer specialattribute="some value" src="main.js"></script>. false,undefined, ornull: Removes the attribute.
The following code adds the specialAttribute attribute to every <script> tag:
alterAssetTagGroups
This hook runs after tags are grouped for <head> and <body>, but before the template is rendered.
Modify headTags and bodyTags to move or update the grouped tags.
- Type:
AsyncSeriesWaterfallHook<[AlterAssetTagGroupsData]> - Parameters:
Only changes to headTags and bodyTags affect the generated HTML. Changes to other fields are ignored by this plugin.
The following code moves all <script> tags from <body> to <head>:
afterTemplateExecution
This hook runs after template rendering and before automatic tag injection.
Modify html, headTags, or bodyTags to change the rendered template or the tags that will be injected.
With a function-valued templateContent or a .js/.cjs template, html is the string returned by the template function. With a string or markup file template, it is the result produced by the built-in template engine.
- Type:
AsyncSeriesWaterfallHook<[AfterTemplateExecutionData]> - Parameters:
Only changes to html, headTags, and bodyTags affect the generated HTML. Changes to other fields are ignored by this plugin.
The following code adds Injected by plugin at the end of <body>. The tags are then injected after that text, producing Injected by plugin<script defer src="main.js"></script></body>:
beforeEmit
This hook runs immediately before the HTML asset is emitted and is the final chance to modify its content.
- Type:
AsyncSeriesWaterfallHook<[BeforeEmitData]> - Parameters:
Only changes to html affect the emitted asset. Changes to other fields are ignored by this plugin.
The following code adds Injected by plugin at the end of <body>. The final sequence is <script defer src="main.js"></script>Injected by plugin</body>:
afterEmit
This hook runs after the HTML asset is emitted and is intended for notification only.
- Type:
AsyncSeriesWaterfallHook<[AfterEmitData]> - Parameters:

