Skip to content

Commit c068d9a

Browse files
devilmancbcsorryccPeachScript
committed
feat(preset-umi): support multiple favicon files (#705)
* feat: support favicon list * feat: optimization code * Update packages/preset-umi/src/features/favicon/favicon.ts Co-authored-by: Peach <[email protected]> * Update packages/core/src/service/service.ts * Update packages/core/src/service/service.ts * feat: fix favicons types and add docs Co-authored-by: chencheng (云谦) <[email protected]> Co-authored-by: Peach <[email protected]>
1 parent 83f246b commit c068d9a

File tree

5 files changed

+41
-32
lines changed

5 files changed

+41
-32
lines changed

docs/docs/api/config.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -315,17 +315,17 @@ export default {
315315

316316
配置额外的 postcss 插件。
317317

318-
## favicon
318+
## favicons
319319

320-
* 类型:`string`
320+
* 类型:`string[]`
321321
* 默认值:`null`
322322

323-
配置 favicon 路径。可以是绝对路径,也可以是基于项目根目录的相对路径。
323+
支持配置多个 favicon 文件。配置 favicons 路径,可以是绝对路径,也可以是基于项目根目录的相对路径。
324324

325325
比如:
326326

327327
```js
328-
favicon: '/assets/favicon.ico'
328+
favicons: ['/assets/favicon.ico']
329329
```
330330

331331
HTML 中会生成 `<link rel="shortcut icon" type="image/x-icon" href="/assets/favicon.ico" />`

packages/preset-umi/src/commands/dev/getMarkupArgs.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,16 @@ export async function getMarkupArgs(opts: { api: IApi }) {
2222
key: 'addHTMLStyles',
2323
initialValue: opts.api.config.styles || [],
2424
});
25-
const favicon = await opts.api.applyPlugins({
25+
const favicons = await opts.api.applyPlugins({
2626
key: 'modifyHTMLFavicon',
27-
initialValue: opts.api.config.favicon,
27+
initialValue: [].concat(opts.api.config.favicons || []),
2828
});
2929
return {
3030
mountElementId: opts.api.config.mountElementId,
3131
base:
3232
opts.api.config.history?.type === 'browser' ? opts.api.config.base : '/',
3333
routes: opts.api.appData.routes,
34-
favicon,
34+
favicons,
3535
headScripts,
3636
scripts,
3737
metas,

packages/preset-umi/src/features/favicon/favicon.ts

+25-19
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ const FAVICON_FILES = [
1313
'favicon.webp',
1414
];
1515

16-
function getFaviconFile(p: string): string | undefined {
17-
return FAVICON_FILES.find((f) => existsSync(join(p, f)));
16+
function getFaviconFiles(p: string): string[] | undefined {
17+
return FAVICON_FILES.filter((f) => existsSync(join(p, f)));
1818
}
1919

2020
export default (api: IApi) => {
@@ -26,39 +26,45 @@ export default (api: IApi) => {
2626

2727
api.modifyAppData(async (memo) => {
2828
if (api.config.favicon) return memo;
29-
const faviconFile = getFaviconFile(api.paths.absSrcPath);
30-
if (faviconFile) {
31-
memo.faviconFile = faviconFile;
29+
const faviconFiles = getFaviconFiles(api.paths.absSrcPath);
30+
if (faviconFiles) {
31+
memo.faviconFiles = faviconFiles;
3232
}
3333
return memo;
3434
});
3535

3636
api.addBeforeMiddlewares(() => [
3737
(req, res, next) => {
38-
if (
39-
api.appData.faviconFile &&
40-
req.path === `/${api.appData.faviconFile}`
41-
) {
42-
res.sendFile(join(api.paths.absSrcPath, api.appData.faviconFile));
43-
} else {
38+
const iconFile = (api.appData.faviconFiles || []).find(
39+
(file: any) => req.path === `/${file}`,
40+
);
41+
if (!iconFile) {
4442
next();
43+
} else {
44+
res.sendFile(join(api.paths.absSrcPath, iconFile));
4545
}
4646
},
4747
]);
4848

4949
api.onBuildComplete(({ err }) => {
5050
if (err) return;
51-
if (api.appData.faviconFile) {
52-
copyFileSync(
53-
join(api.paths.absSrcPath, api.appData.faviconFile),
54-
join(api.paths.absOutputPath, api.appData.faviconFile),
55-
);
51+
if (api.appData.faviconFiles) {
52+
api.appData.faviconFiles.forEach((e: any) => {
53+
copyFileSync(
54+
join(api.paths.absSrcPath, e),
55+
join(api.paths.absOutputPath, e),
56+
);
57+
});
5658
}
5759
});
5860

5961
api.modifyHTMLFavicon((memo) => {
60-
return api.appData.faviconFile
61-
? `${api.config.publicPath}${api.appData.faviconFile}`
62-
: memo;
62+
// respect favicon config from user, and fallback to auto-detecting files
63+
if (!memo.length && api.appData.faviconFiles) {
64+
api.appData.faviconFiles.forEach((e: any) => {
65+
memo.push(`${api.config.publicPath}${e}`);
66+
});
67+
}
68+
return memo;
6369
});
6470
};

packages/preset-umi/src/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export type IApi = PluginAPI &
103103
}): void;
104104
};
105105
modifyHTML: IModify<CheerioAPI, { path: string }>;
106-
modifyHTMLFavicon: IModify<string, {}>;
106+
modifyHTMLFavicon: IModify<string[], {}>;
107107
modifyRendererPath: IModify<string, {}>;
108108
modifyRoutes: IModify<Record<string, IRoute>, {}>;
109109
modifyViteConfig: IModify<

packages/server/src/server.ts

+8-5
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export interface IOpts {
2020
links?: Record<string, string>[];
2121
metas?: Record<string, string>[];
2222
styles?: (Record<string, string> | string)[];
23-
favicon?: string;
23+
favicons?: string[];
2424
title?: string;
2525
headScripts?: (Record<string, string> | string)[];
2626
scripts?: (Record<string, string> | string)[];
@@ -84,9 +84,12 @@ export async function getMarkup(
8484
return `<${opts.tagName} ${attrs} />`;
8585
}
8686

87-
const favicon = opts.favicon
88-
? `<link rel="shortcut icon" href="${opts.favicon}">`
89-
: '';
87+
const favicons: string[] = [];
88+
if (Array.isArray(opts.favicons)) {
89+
opts.favicons.forEach((e) => {
90+
favicons.push(`<link rel="shortcut icon" href="${e}">`);
91+
});
92+
}
9093
const title = opts.title ? `<title>${opts.title}</title>` : '';
9194
const metas = (opts.metas || []).map((meta) =>
9295
getTagContent({ attrs: meta, tagName: 'meta' }),
@@ -110,7 +113,7 @@ export async function getMarkup(
110113
/>
111114
<meta http-equiv="X-UA-Compatible" content="ie=edge" />`,
112115
metas.join('\n'),
113-
favicon,
116+
favicons.join('\n'),
114117
title,
115118
links.join('\n'),
116119
styles.join('\n'),

0 commit comments

Comments
 (0)