Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/core/src/defaultConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ const getDefaultHtmlConfig = (): NormalizedHtmlConfig => ({
crossorigin: false,
outputStructure: 'flat',
scriptLoading: 'defer',
implementation: 'js',
});

const getDefaultSecurityConfig = (): NormalizedSecurityConfig => ({
Expand Down
10 changes: 8 additions & 2 deletions packages/core/src/pluginHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import { requireCompiledPackage } from './helpers/vendors';
import { rspack } from './rspack';
import type { HtmlRspackPlugin } from './types';
import type { HtmlRspackPlugin, NormalizedEnvironmentConfig } from './types';

let htmlPlugin: typeof HtmlRspackPlugin;

Expand All @@ -17,7 +17,13 @@ export const setHTMLPlugin = (plugin: typeof HtmlRspackPlugin): void => {
}
};

export const getHTMLPlugin = (): typeof HtmlRspackPlugin => {
export const getHTMLPlugin = (
config: NormalizedEnvironmentConfig,
): typeof HtmlRspackPlugin => {
if (config.html.implementation === 'native') {
// TODO: remove type assertion
return rspack.HtmlRspackPlugin as unknown as typeof HtmlRspackPlugin;
Comment thread
chenjiahan marked this conversation as resolved.
Comment thread
chenjiahan marked this conversation as resolved.
}
if (!htmlPlugin) {
htmlPlugin = requireCompiledPackage('html-rspack-plugin');
}
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/plugins/html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,10 +355,11 @@ export const pluginHtml = (context: InternalContext): RsbuildPlugin => ({
});

const getExtraData = (entryName: string) => extraDataMap.get(entryName);
const getHTMLPlugin = () => HtmlPlugin;

chain
.plugin('rsbuild-html-plugin')
.use(RsbuildHtmlPlugin, [getExtraData]);
.use(RsbuildHtmlPlugin, [getExtraData, getHTMLPlugin]);

if (config.html) {
const { crossorigin } = config.html;
Expand Down
10 changes: 9 additions & 1 deletion packages/core/src/plugins/resourceHints.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { isRegExp } from 'node:util/types';
import { castArray } from '../helpers';
import { getHTMLPlugin } from '../pluginHelper';
import { HtmlResourceHintsPlugin } from '../rspack-plugins/resource-hints/HtmlResourceHintsPlugin';
import type {
HtmlBasicTag,
Expand Down Expand Up @@ -90,6 +91,7 @@ export const pluginResourceHints = (): RsbuildPlugin => ({
'prefetch',
HTMLCount,
isDev,
() => getHTMLPlugin(config),
]);
}

Expand All @@ -104,7 +106,13 @@ export const pluginResourceHints = (): RsbuildPlugin => ({

chain
.plugin(CHAIN_ID.PLUGIN.HTML_PRELOAD)
.use(HtmlResourceHintsPlugin, [options, 'preload', HTMLCount, isDev]);
.use(HtmlResourceHintsPlugin, [
options,
'preload',
HTMLCount,
isDev,
() => getHTMLPlugin(config),
]);
}
});
},
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/provider/rspackConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export function getChainUtils(
isServer: target === 'node',
isWebWorker: target === 'web-worker',
CHAIN_ID,
HtmlPlugin: getHTMLPlugin(),
HtmlPlugin: getHTMLPlugin(environment.config),
};
}

Expand Down
11 changes: 8 additions & 3 deletions packages/core/src/rspack-plugins/RsbuildHtmlPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { color, isFunction, partition } from '../helpers';
import { addCompilationError } from '../helpers/compiler';
import { ensureAssetPrefix, isURL } from '../helpers/url';
import { logger } from '../logger';
import { getHTMLPlugin } from '../pluginHelper';
import type {
EnvironmentContext,
HtmlBasicTag,
Expand Down Expand Up @@ -245,9 +244,15 @@ export class RsbuildHtmlPlugin {

readonly getExtraData: (entryName: string) => HtmlExtraData | undefined;

constructor(getExtraData: (entryName: string) => HtmlExtraData | undefined) {
readonly getHTMLPlugin: () => typeof HtmlRspackPlugin;

constructor(
getExtraData: (entryName: string) => HtmlExtraData | undefined,
getHTMLPlugin: () => typeof HtmlRspackPlugin,
) {
this.name = 'RsbuildHtmlPlugin';
this.getExtraData = getExtraData;
this.getHTMLPlugin = getHTMLPlugin;
}

apply(compiler: Compiler): void {
Expand Down Expand Up @@ -370,7 +375,7 @@ export class RsbuildHtmlPlugin {
};

compiler.hooks.compilation.tap(this.name, (compilation: Compilation) => {
const hooks = getHTMLPlugin().getCompilationHooks(compilation);
const hooks = this.getHTMLPlugin().getCompilationHooks(compilation);

hooks.alterAssetTagGroups.tapPromise(this.name, async (data) => {
const extraData = getExtraDataByPlugin(data.plugin);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import type {
} from '@rspack/core';
import { castArray, isFunction, upperFirst } from '../../helpers';
import { ensureAssetPrefix } from '../../helpers/url';
import { getHTMLPlugin } from '../../pluginHelper';
import type {
HtmlRspackPlugin,
ResourceHintsFilter,
Expand Down Expand Up @@ -242,21 +241,25 @@ export class HtmlResourceHintsPlugin implements RspackPluginInstance {

isDev: boolean;

getHTMLPlugin: () => typeof HtmlRspackPlugin;

constructor(
options: ResourceHintsOptions,
type: LinkType,
HTMLCount: number,
isDev: boolean,
getHTMLPlugin: () => typeof HtmlRspackPlugin,
) {
this.options = { ...defaultOptions, ...options };
this.type = type;
this.HTMLCount = HTMLCount;
this.isDev = isDev;
this.getHTMLPlugin = getHTMLPlugin;
}

apply(compiler: Compiler): void {
compiler.hooks.compilation.tap(this.name, (compilation) => {
const pluginHooks = getHTMLPlugin().getCompilationHooks(compilation);
const pluginHooks = this.getHTMLPlugin().getCompilationHooks(compilation);
const pluginName = `HTML${upperFirst(this.type)}Plugin`;

pluginHooks.beforeAssetTagGeneration.tap(pluginName, (data) => {
Expand Down
16 changes: 16 additions & 0 deletions packages/core/src/types/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1505,6 +1505,8 @@ export type AppIcon = {
filename?: string;
};

type HtmlImplementation = 'js' | 'native';

export interface HtmlConfig {
/**
* Configure the `<meta>` tag of the HTML.
Expand Down Expand Up @@ -1591,6 +1593,19 @@ export interface HtmlConfig {
* @default 'defer'. If `output.module` is enabled, the value is always `'module'`.
*/
scriptLoading?: ScriptLoading;
/**
* Specifies which implementation to use for generating HTML files.
*
* - `'js'` (default) - Use the JavaScript-based `html-rspack-plugin`.
* - `'native'` - Use Rspack's built-in `HtmlRspackPlugin` implemented in Rust.
*
* This option is experimental and may affect the available options in `tools.htmlPlugin`,
* since the two implementations are not fully compatible.
*
* @default 'js'
* @experimental
*/
implementation?: HtmlImplementation;
}

export type NormalizedHtmlConfig = HtmlConfig & {
Expand All @@ -1601,6 +1616,7 @@ export type NormalizedHtmlConfig = HtmlConfig & {
crossorigin: boolean | CrossOrigin;
outputStructure: OutputStructure;
scriptLoading: ScriptLoading;
implementation: HtmlImplementation;
};

export type ProgressBarConfig = {
Expand Down
Loading