Serve Favicon Middleware
serve-favicon is a Node.js middleware designed for efficiently serving the `favicon.ico` file in web applications, primarily within the Express.js and Connect.js ecosystems. Currently at version 2.5.1, this package is actively maintained, receiving updates primarily for dependency management and CI improvements, rather than frequent feature additions. Its core purpose is to optimize favicon delivery by caching the icon in memory, generating robust ETags based on file content, and correctly setting the `Content-Type` header. A key differentiator is its specific focus on the default `/favicon.ico` path, ensuring that these high-frequency requests are handled quickly and bypass subsequent middleware in the stack, thereby improving overall application performance by reducing unnecessary processing for static assets.
Common errors
-
TypeError: favicon is not a function
cause Attempting to use ES module `import` syntax or destructuring when the package is CommonJS-only.fixChange `import favicon from 'serve-favicon'` to `const favicon = require('serve-favicon')`. -
Cannot GET /favicon.ico
cause The favicon file path provided to `serve-favicon` is incorrect, or the middleware is placed too late in the stack after other handlers have already consumed the request.fixDouble-check the `path.join(__dirname, 'public', 'favicon.ico')` argument to ensure it points to an existing file. Ensure `app.use(favicon(...))` is placed early in your Express/Connect middleware chain. -
favicon not showing or slow to load
cause Caching issues (e.g., `maxAge` set too low or browser cache) or the middleware being placed after a logger that's delaying the response.fixAdjust the `maxAge` option for aggressive caching (e.g., `{ maxAge: '30d' }`). Verify `serve-favicon` is positioned before any logging middleware like `morgan` to prevent unnecessary logging of favicon requests and ensure quick responses.
Warnings
- gotcha The `serve-favicon` middleware is exclusively designed to serve the default `GET /favicon.ico` request. It will not handle other vendor-specific icons (e.g., Apple Touch Icons, Web App Manifest icons) which typically require specific HTML markup and other static file serving middleware like `serve-static`.
- gotcha To ensure optimal performance and prevent unnecessary processing, `serve-favicon` should be placed very early in your middleware stack, ideally before any logger or heavy processing middleware. This allows `favicon.ico` requests to be handled and responded to quickly.
- gotcha The package currently uses CommonJS modules (`require`) and does not natively support ES Modules (`import`). Attempting to use `import` syntax will result in a runtime error.
Install
-
npm install serve-favicon -
yarn add serve-favicon -
pnpm add serve-favicon
Imports
- favicon
import favicon from 'serve-favicon'
const favicon = require('serve-favicon') - faviconMiddleware
import { faviconMiddleware } from 'serve-favicon'const favicon = require('serve-favicon') - options
favicon(path.join(__dirname, 'public', 'favicon.ico'), { maxAge: 86400000 })favicon(path.join(__dirname, 'public', 'favicon.ico'), { maxAge: '1d' })
Quickstart
const express = require('express');
const favicon = require('serve-favicon');
const path = require('path');
const fs = require('fs');
const app = express();
const publicDir = path.join(__dirname, 'public');
const faviconPath = path.join(publicDir, 'favicon.ico');
// Ensure the 'public' directory exists
if (!fs.existsSync(publicDir)) {
fs.mkdirSync(publicDir);
}
// Create a dummy favicon.ico if it doesn't exist for the example to run
if (!fs.existsSync(faviconPath)) {
// A minimal, valid ICO file (1x1 transparent pixel)
const dummyFavicon = Buffer.from('0000010001001010000001000400000028000000010000000100000001000400000000001600000000000000000000000000000000000000', 'hex');
fs.writeFileSync(faviconPath, dummyFavicon);
}
// Use serve-favicon middleware
// It should be placed early in your middleware stack
app.use(favicon(faviconPath, { maxAge: '30d' }));
app.get('/', (req, res) => {
res.send('Hello from your Express app with a favicon!');
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});