Problem
We have a source image file, e.g., 1024x1024px, and we want to generate favicons of different sizes for various platforms, matching web application manifest. The webmanifest file with favicons should be generated automatically too.
Solution
For Webpack we can use the powerful html-bundler-webpack-plugin.
This bundler plugin renders a HTML template and can generate favicons automatically. Under the hood is used the Favicons Node.js module.
This module generates favicons and their associated files for many platforms such as android
, apple
, windows
.
Install
Install modules:
npm i -D html-bundler-webpack-plugin favicons
Optional, you can install CSS and SASS loaders if you use them:
npm i -D css-loader sass-loader
Usage
For example, we have a simple HTML file, where we can specify source files of styles, scripts and images:
<!DOCTYPE html>
<html>
<head>
<!-- source favicon file relative to this HTML file -->
<link href="./myFavicon.png" rel="icon" />
<!-- SCSS file relative to this HTML file -->
<link href="./styles.scss" rel="stylesheet" />
<!-- source script file relative to this HTML file -->
<script src="./main.js" defer="defer"></script>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
Create minimalistic Webpack config:
const path = require('path');
// bundler plugin to render html
const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');
// favicon plugin to generate icons
const { FaviconsBundlerPlugin } = require('html-bundler-webpack-plugin/plugins');
module.exports = {
mode: 'production',
output: {
path: path.join(__dirname, 'dist/'),
},
plugins: [
new HtmlBundlerPlugin({
entry: {
// define templates here
index: './src/views/home.html', // => dist/index.html
},
js: {
// output filename of JS
filename: '[name].[contenthash:8].js',
},
css: {
// output filename of CSS
filename: '[name].[contenthash:8].css',
},
}),
new FaviconsBundlerPlugin({
enabled: 'auto', // true, false, auto - generate favicons in production mode only
faviconOptions: {
path: '/img/favicons', // output path
appName: 'My App',
icons: {
android: true, // Create Android homescreen icon.
appleIcon: true, // Create Apple touch icons.
appleStartup: false, // Create Apple startup images.
favicons: true, // Create regular favicons.
windows: false, // Create Windows 8 tile icons.
yandex: false, // Create Yandex browser icon.
},
},
}),
],
module: {
rules: [
{
test: /\.(s?css)$/,
use: ['css-loader', 'sass-loader'],
},
{
test: /\.(png|jpe?g|ico|svg)$/,
type: 'asset/resource',
},
],
},
};
See complete favicons options here.
The generated HTML contains output filenames of CSS and JS, but the original tag <link href="./myFavicon.png" rel="icon" />
is replaced with the generated favicon and meta tags.
The generated dist/index.html:
<!DOCTYPE html>
<html>
<head>
<!-- original tag is replaced with tags generated by favicons module -->
<link rel="apple-touch-icon" sizes="1024x1024" href="/img/favicons/apple-touch-icon-1024x1024.png">
<link rel="apple-touch-icon" sizes="114x114" href="/img/favicons/apple-touch-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/img/favicons/apple-touch-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/img/favicons/apple-touch-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/img/favicons/apple-touch-icon-152x152.png">
<link rel="apple-touch-icon" sizes="167x167" href="/img/favicons/apple-touch-icon-167x167.png">
<link rel="apple-touch-icon" sizes="180x180" href="/img/favicons/apple-touch-icon-180x180.png">
<link rel="apple-touch-icon" sizes="57x57" href="/img/favicons/apple-touch-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/img/favicons/apple-touch-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/img/favicons/apple-touch-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/img/favicons/apple-touch-icon-76x76.png">
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicons/favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="48x48" href="/img/favicons/favicon-48x48.png">
<link rel="icon" type="image/x-icon" href="/img/favicons/favicon.ico">
<link rel="manifest" href="/img/favicons/manifest.webmanifest">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="My App">
<meta name="application-name" content="My App">
<meta name="mobile-web-app-capable" content="yes">
<meta name="theme-color" content="#fff">
<link href="css/styles.05e4dd86.css" rel="stylesheet" />
<script src="js/main.f4b855d8.js" defer="defer"></script>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
The generated dist/img/favicons/manifest.webmanifest will be looks like:
{
"name": "My App",
"short_name": "My App",
"description": null,
"dir": "auto",
"lang": "en-US",
"display": "standalone",
"orientation": "any",
"start_url": "/?homescreen=1",
"background_color": "#fff",
"theme_color": "#fff",
"icons": [
{
"src": "/img/favicons/android-chrome-36x36.png",
"sizes": "36x36",
"type": "image/png",
"purpose": "any"
},
{
"src": "/img/favicons/android-chrome-48x48.png",
"sizes": "48x48",
"type": "image/png",
"purpose": "any"
},
{
"src": "/img/favicons/android-chrome-72x72.png",
"sizes": "72x72",
"type": "image/png",
"purpose": "any"
},
{
"src": "/img/favicons/android-chrome-96x96.png",
"sizes": "96x96",
"type": "image/png",
"purpose": "any"
},
{
"src": "/img/favicons/android-chrome-144x144.png",
"sizes": "144x144",
"type": "image/png",
"purpose": "any"
},
{
"src": "/img/favicons/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "/img/favicons/android-chrome-256x256.png",
"sizes": "256x256",
"type": "image/png",
"purpose": "any"
},
{
"src": "/img/favicons/android-chrome-384x384.png",
"sizes": "384x384",
"type": "image/png",
"purpose": "any"
},
{
"src": "/img/favicons/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
}
]
}
This is a game-changer for web developers, making the process of generating favicons for different platforms a breeze!
Top comments (0)