Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions e2e/cases/assets/asset-prefix/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ test('should inject assetPrefix to env var and template correctly', async ({
},
});

await expect(page.locator('#prefix1')).toHaveText('http://example.com');
await expect(page.locator('#prefix2')).toHaveText('http://example.com');
await expect(page.locator('#prefix')).toHaveText('http://example.com');
});

test('should use output.assetPrefix in none mode', async ({ build }) => {
Expand Down
3 changes: 1 addition & 2 deletions e2e/cases/assets/asset-prefix/src/template.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
<html>
<head></head>
<body>
<div id="prefix1"><%= assetPrefix %></div>
<div id="prefix2"><%= process.env.ASSET_PREFIX %></div>
<div id="prefix"><%= assetPrefix %></div>
<div id="root"></div>
</body>
</html>
32 changes: 16 additions & 16 deletions e2e/cases/html/app-icon/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ test('should emit apple-touch-icon to dist path', async ({ build }) => {
const html = getFileContent(files, 'index.html');

expect(html).toContain(
'<link rel="apple-touch-icon" sizes="180x180" href="/static/image/icon.png">',
'<link href="/static/image/icon.png" rel="apple-touch-icon" sizes="180x180">',
);
});

Expand Down Expand Up @@ -47,13 +47,13 @@ test('should emit manifest.webmanifest to dist path', async ({ build }) => {
const html = getFileContent(files, 'index.html');

expect(html).toContain(
'<link rel="apple-touch-icon" sizes="180x180" href="/static/image/icon.png">',
'<link href="/static/image/icon.png" rel="apple-touch-icon" sizes="180x180">',
);
// do not generate apple-touch-icon for large images
expect(html).not.toContain(
'<link rel="apple-touch-icon" sizes="512x512" href="/static/image/image.png">',
'<link href="/static/image/image.png" rel="apple-touch-icon" sizes="512x512">',
);
expect(html).toContain('<link rel="manifest" href="/manifest.webmanifest">');
expect(html).toContain('<link href="/manifest.webmanifest" rel="manifest">');

expect(JSON.parse(files[manifestPath])).toEqual({
name: 'My Website',
Expand Down Expand Up @@ -84,9 +84,9 @@ test('should allow to specify URL as icon', async ({ build }) => {
const html = getFileContent(files, 'index.html');

expect(html).toContain(
'<link rel="apple-touch-icon" sizes="192x192" href="https://example.com/icon-192.png">',
'<link href="https://example.com/icon-192.png" rel="apple-touch-icon" sizes="192x192">',
);
expect(html).toContain('<link rel="manifest" href="/manifest.webmanifest">');
expect(html).toContain('<link href="/manifest.webmanifest" rel="manifest">');

expect(JSON.parse(files[manifestPath])).toEqual({
name: 'My Website',
Expand Down Expand Up @@ -145,16 +145,16 @@ test('should allow to specify target for each icon', async ({ build }) => {
const html = getFileContent(files, 'index.html');

expect(html).toContain(
'<link rel="apple-touch-icon" sizes="180x180" href="/static/image/icon.png">',
'<link href="/static/image/icon.png" rel="apple-touch-icon" sizes="180x180">',
);
// do not generate apple-touch-icon for large images
expect(html).not.toContain(
'<link rel="apple-touch-icon" sizes="512x512" href="/static/image/image.png">',
'<link href="/static/image/image.png" rel="apple-touch-icon" sizes="512x512">',
);
expect(html).not.toContain(
'<link rel="apple-touch-icon" sizes="192x192" href="/static/image/circle.svg">',
'<link href="/static/image/circle.svg" rel="apple-touch-icon" sizes="192x192">',
);
expect(html).toContain('<link rel="manifest" href="/manifest.webmanifest">');
expect(html).toContain('<link href="/manifest.webmanifest" rel="manifest">');

expect(JSON.parse(files[manifestPath])).toEqual({
name: 'My Website',
Expand Down Expand Up @@ -235,7 +235,7 @@ test('should allow to customize manifest filename', async ({ build }) => {
const manifestPath = findFile(files, 'manifest.json');
const html = getFileContent(files, 'index.html');

expect(html).toContain('<link rel="manifest" href="/manifest.json">');
expect(html).toContain('<link href="/manifest.json" rel="manifest">');

expect(JSON.parse(files[manifestPath])).toEqual({
name: 'My Website',
Expand Down Expand Up @@ -275,10 +275,10 @@ test('should append dev.assetPrefix to icon URL', async ({ dev }) => {
const html = getFileContent(files, 'index.html');

expect(html).toContain(
'<link rel="apple-touch-icon" sizes="180x180" href="http://localhost:3000/static/image/icon.png">',
'<link href="http://localhost:3000/static/image/icon.png" rel="apple-touch-icon" sizes="180x180">',
);
expect(html).toContain(
'<link rel="manifest" href="http://localhost:3000/manifest.webmanifest">',
'<link href="http://localhost:3000/manifest.webmanifest" rel="manifest">',
);

expect(JSON.parse(files[manifestPath])).toEqual({
Expand Down Expand Up @@ -326,10 +326,10 @@ test('should append output.assetPrefix to icon URL', async ({ build }) => {
const html = getFileContent(files, 'index.html');

expect(html).toContain(
'<link rel="apple-touch-icon" sizes="180x180" href="https://example.com/static/image/icon.png">',
'<link href="https://example.com/static/image/icon.png" rel="apple-touch-icon" sizes="180x180">',
);
expect(html).toContain(
'<link rel="manifest" href="https://example.com/manifest.webmanifest">',
'<link href="https://example.com/manifest.webmanifest" rel="manifest">',
);

expect(JSON.parse(files[manifestPath])).toEqual({
Expand Down Expand Up @@ -373,6 +373,6 @@ test('should apply asset prefix to apple-touch-icon URL', async ({ build }) => {
const html = getFileContent(files, 'index.html');

expect(html).toContain(
'<link rel="apple-touch-icon" sizes="180x180" href="https://www.example.com/static/image/icon.png">',
'<link href="https://www.example.com/static/image/icon.png" rel="apple-touch-icon" sizes="180x180">',
);
});
20 changes: 10 additions & 10 deletions e2e/cases/html/favicon/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ test('should emit local favicon to dist path', async ({ build }) => {
expect(icon.endsWith('/icon.png')).toBeTruthy();

const html = getFileContent(files, 'index.html');
expect(html).toContain('<link rel="icon" href="/icon.png">');
expect(html).toContain('<link href="/icon.png" rel="icon">');
});

test('should allow `html.favicon` to be an absolute path', async ({
Expand All @@ -35,7 +35,7 @@ test('should allow `html.favicon` to be an absolute path', async ({
expect(icon.endsWith('/icon.png')).toBeTruthy();

const html = getFileContent(files, 'index.html');
expect(html).toContain('<link rel="icon" href="/icon.png">');
expect(html).toContain('<link href="/icon.png" rel="icon">');
});

test('should add type attribute for SVG favicon', async ({ build }) => {
Expand All @@ -53,7 +53,7 @@ test('should add type attribute for SVG favicon', async ({ build }) => {

const html = getFileContent(files, 'index.html');
expect(html).toContain(
'<link rel="icon" href="/mobile.svg" type="image/svg+xml">',
'<link href="/mobile.svg" rel="icon" type="image/svg+xml">',
);
});

Expand All @@ -73,7 +73,7 @@ test('should apply asset prefix to favicon URL', async ({ build }) => {
const html = getFileContent(files, 'index.html');

expect(html).toContain(
'<link rel="icon" href="https://www.example.com/icon.png">',
'<link href="https://www.example.com/icon.png" rel="icon">',
);
});

Expand All @@ -88,7 +88,7 @@ test('should allow favicon to be a CDN URL', async ({ build }) => {

const files = rsbuild.getDistFiles();
const html = getFileContent(files, 'index.html');
expect(html).toContain('<link rel="icon" href="https://foo.com/icon.png">');
expect(html).toContain('<link href="https://foo.com/icon.png" rel="icon">');
});

test('should generate favicon via function correctly', async ({ build }) => {
Expand Down Expand Up @@ -116,12 +116,12 @@ test('should generate favicon via function correctly', async ({ build }) => {

const fooHtml = getFileContent(files, 'foo.html');
expect(fooHtml).toContain(
'<link rel="icon" href="https://example.com/foo.ico">',
'<link href="https://example.com/foo.ico" rel="icon">',
);

const barHtml = getFileContent(files, 'bar.html');
expect(barHtml).toContain(
'<link rel="icon" href="https://example.com/bar.ico">',
'<link href="https://example.com/bar.ico" rel="icon">',
);
});

Expand All @@ -146,7 +146,7 @@ test('should allow to custom favicon dist path with a relative path', async ({
expect(faviconFile.endsWith('/static/favicon/icon.png')).toBeTruthy();

const html = getFileContent(files, 'index.html');
expect(html).toContain('<link rel="icon" href="/static/favicon/icon.png">');
expect(html).toContain('<link href="/static/favicon/icon.png" rel="icon">');
});

test('should allow to custom favicon dist path with a relative path starting with ./', async ({
Expand All @@ -170,7 +170,7 @@ test('should allow to custom favicon dist path with a relative path starting wit
expect(faviconFile.endsWith('/custom/icon.png')).toBeTruthy();

const html = getFileContent(files, 'index.html');
expect(html).toContain('<link rel="icon" href="/custom/icon.png">');
expect(html).toContain('<link href="/custom/icon.png" rel="icon">');
});

for (const filename of ['favicon.ico', 'favicon.png', 'favicon.svg']) {
Expand All @@ -195,6 +195,6 @@ for (const filename of ['favicon.ico', 'favicon.png', 'favicon.svg']) {
expect(faviconFile.endsWith(`/${filename}`)).toBeTruthy();

const html = getFileContent(files, 'index.html');
expect(html).toContain(`<link rel="icon" href="/${filename}"`);
expect(html).toContain(`<link href="/${filename}" rel="icon"`);
});
}
2 changes: 1 addition & 1 deletion packages/core/src/defaultConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ const getDefaultHtmlConfig = (): NormalizedHtmlConfig => ({
crossorigin: false,
outputStructure: 'flat',
scriptLoading: 'defer',
implementation: 'js',
implementation: 'native',
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing the default from 'js' to 'native' is a significant breaking change that affects HTML output format. The documentation at line 1605 in types/config.ts states '@default 'js'' which should be updated to reflect this new default value of 'native'.

Copilot uses AI. Check for mistakes.
});

const getDefaultSecurityConfig = (): NormalizedSecurityConfig => ({
Expand Down
Loading