Add Favicon with React and Webpack
Javascriptnode.jsReactjsWebpackFaviconJavascript Problem Overview
I am attempting to add a favicon to a React-based website that I made using webpack. It has been a total nightmare to add a favicon and I have tried many solutions to no avail. The latest solution that has been recommended to me is called 'favicons-webpack-plugin' which can be found here: https://github.com/jantimon/favicons-webpack-plugin.
If anyone can tell me what I am doing wrong, your assistance would be greatly appreciated.
I get the following error when I run 'npm run start'
This is my directory structure:
This is my webpack.config.js file:
const path = require('path');
const merge = require('webpack-merge');
const webpack = require('webpack');
const NpmInstallPlugin = require('npm-install-webpack-plugin');
const TARGET = process.env.npm_lifecycle_event;
const FaviconsWebpackPlugin = require('favicons-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
var favicons = require('favicons'),
source = 'my-logo.png', // Source image(s). `string`, `buffer` or array of `{ size: filepath }`
configuration = {
appName: null, // Your application's name. `string`
appDescription: null, // Your application's description. `string`
developerName: null, // Your (or your developer's) name. `string`
developerURL: null, // Your (or your developer's) URL. `string`
background: "#fff", // Background colour for flattened icons. `string`
path: "/", // Path for overriding default icons path. `string`
url: "/", // Absolute URL for OpenGraph image. `string`
display: "standalone", // Android display: "browser" or "standalone". `string`
orientation: "portrait", // Android orientation: "portrait" or "landscape". `string`
version: "1.0", // Your application's version number. `number`
logging: false, // Print logs to console? `boolean`
online: false, // Use RealFaviconGenerator to create favicons? `boolean`
icons: {
android: true, // Create Android homescreen icon. `boolean`
appleIcon: true, // Create Apple touch icons. `boolean`
appleStartup: true, // Create Apple startup images. `boolean`
coast: true, // Create Opera Coast icon. `boolean`
favicons: true, // Create regular favicons. `boolean`
firefox: true, // Create Firefox OS icons. `boolean`
opengraph: true, // Create Facebook OpenGraph image. `boolean`
twitter: true, // Create Twitter Summary Card image. `boolean`
windows: true, // Create Windows 8 tile icons. `boolean`
yandex: true // Create Yandex browser icon. `boolean`
}
},
callback = function (error, response) {
if (error) {
console.log(error.status); // HTTP error code (e.g. `200`) or `null`
console.log(error.name); // Error name e.g. "API Error"
console.log(error.message); // Error description e.g. "An unknown error has occurred"
}
console.log(response.images); // Array of { name: string, contents: <buffer> }
console.log(response.files); // Array of { name: string, contents: <string> }
console.log(response.html); // Array of strings (html elements)
};
favicons(source, configuration, callback);
const pkg = require('./package.json');
const PATHS = {
app: path.join(__dirname, 'app'),
build: path.join(__dirname, 'build')
};
process.env.BABEL_ENV = TARGET;
const common = {
entry: {
app: PATHS.app
},
// Add resolve.extensions
// '' is needed to allow imports without an extension
// note the .'s before the extension as it will fail to load without them
resolve: {
extensions: ['', '.js', '.jsx', '.json']
},
output: {
path: PATHS.build,
filename: 'bundle.js'
},
module: {
loaders: [
{
// Test expects a RegExp! Notethe slashes!
test: /\.css$/,
loaders: ['style', 'css'],
//Include accepts either a path or an array of paths
include: PATHS.app
},
//set up JSX. This accepts js too thanks to RegExp
{
test: /\.(js|jsx)$/,
//enable caching for improved performance during development
//It uses default OS directory by default. If you need something more custom,
//pass a path to it. ie: babel?cacheDirectory=<path>
loaders: [
'babel?cacheDirectory,presets[]=es2015'
],
//parse only app files Without this it will go thru the entire project.
//beside being slow this will likely result in an error
include: PATHS.app
}
]
}
};
// Default configuration. We will return this if
// Webpack is called outside of npm.
if(TARGET === 'start' || !TARGET){
module.exports = merge(common, {
devtool: 'eval-source-map',
devServer: {
contentBase: PATHS.build,
//enable history API fallback so HTML5 HISTORY API based
// routing works. This is a good default that will come in handy in more
// complicated setups.
historyApiFallback: true,
hot: true,
inline: true,
progress: true,
//display only errors to reduce output amount
stats: 'errors only',
//Parse host and port from env so this is easy to customize
host: process.env.HOST,
port: process.env.PORT
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new NpmInstallPlugin({
save: true //--save
}),
new FaviconsWebpackPlugin('my-logo.png')
]
});
}
if(TARGET === 'build' || TARGET === 'stats') {
module.exports = merge(common, {
entry: {
vendor: Object.keys(pkg.dependencies).filter(function(v) {
return v !== 'alt-utils';
}),
style: PATHS.style
},
output: {
path: PATHS.build,
// Output using entry name
filename: '[name].[chunkhash].js',
chunkFilename: '[chunkhash].js'
},
module: {
loaders: [
// Extract CSS during build
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style', 'css'),
include: PATHS.app
}
]
},
plugins: [
// Output extracted CSS to a file
new ExtractTextPlugin('[name].[chunkhash].css'),
// Extract vendor and manifest files
new webpack.optimize.CommonsChunkPlugin({
names: ['vendor', 'manifest']
}),
// Setting DefinePlugin affects React library size!
new webpack.DefinePlugin({
'process.env.NODE_ENV': '"production"'
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
]
});
}
This is my server.js file:
/* Global Requires */
const express = require('express');
const logger = require('morgan');
const bodyParser = require('body-parser');
const path = require('path');
const app = express();
const ReactDOM = require('react-dom')
var favicon = require('serve-favicon');
if(process.env.NODE_ENV === 'development') {
console.log('in development.');
require('dotenv').config();
} else {
console.log('in production.');
}
/* App Config */
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'build')));
app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
/* Server Initialization */
app.get('/', (req, res) => res.sendFile('index.html'));
var port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Server initialized on // ${new Date()}`));
Javascript Solutions
Solution 1 - Javascript
Here is all you need:
new HtmlWebpackPlugin({
favicon: "./src/favicon.gif"
})
That is definitely after adding "favicon.gif" to the folder "src".
This will transfer the icon to your build folder and include it in your tag like this <link rel="shortcut icon" href="favicon.gif">
. This is safer than just importing with copyWebpackPLugin
Solution 2 - Javascript
For future googlers: You can also use copy-webpack-plugin and add this to webpack's production config:
plugins: [
new CopyWebpackPlugin({
patterns: [
// relative path is from src
{ from: './static/favicon.ico' }, // <- your path to favicon
]
})
]
Solution 3 - Javascript
Adding your favicon simply into to the public
folder should do. Make sure the favicon is named as favicon.ico
.
Solution 4 - Javascript
Here is how I did.
public/index.html
I have added the generated favicon links.
...
<link rel="icon" type="image/png" sizes="32x32" href="%PUBLIC_URL%/path/to/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="%PUBLIC_URL%/path/to/favicon-16x16.png" />
<link rel="shortcut icon" href="%PUBLIC_URL%/path/to/favicon.ico" type="image/png/ico" />
webpack.config.js
new HTMLWebpackPlugin({
template: '/path/to/index.html',
favicon: '/path/to/favicon.ico',
})
Note
I use historyApiFallback
in dev mode, but I didn't need to have any extra setup to get the favicon work nor on the server side.
Solution 5 - Javascript
Browsers look for your favicon in /favicon.ico
, so that's where it needs to be. You can double check if you've positioned it in the correct place by navigating to [address:port]/favicon.ico
and seeing if your icon appears.
In dev mode, you are using historyApiFallback, so will need to configure webpack to explicitly return your icon for that route:
historyApiFallback: {
index: '[path/to/index]',
rewrites: [
// shows favicon
{ from: /favicon.ico/, to: '[path/to/favicon]' }
]
}
In your server.js
file, try explicitly rewriting the url:
app.configure(function() {
app.use('/favicon.ico', express.static(__dirname + '[route/to/favicon]'));
});
(or however your setup prefers to rewrite urls)
I suggest generating a true .ico
file rather than using a .png
, since I've found that to be more reliable across browsers.
Solution 6 - Javascript
Another alternative is
npm install react-favicon
And in your application you would just do:
import Favicon from 'react-favicon';
//other codes
ReactDOM.render(
<div>
<Favicon url="/path/to/favicon.ico"/>
// do other stuff here
</div>
, document.querySelector('.react'));
Solution 7 - Javascript
The correct answers:
If you are using webpack directly:
new HtmlWebpackPlugin({
favicon: "./public/fav-icon.ico"
})
If you use CRA(create-react-app) then you can modificate the manifest.json
in the public directory
Solution 8 - Javascript
It's the same as adding any other external script or stylesheet. All you have to do is focus on giving the correct path and rel and type.
Note: When my favicon image was in the assets folder, it was not displaying the favicon. So I copied the image to the same folder as of my index.html and it worked perfectly as it should.
<head>
<link rel="shortcut icon" type="image/png/ico" href="/favicon.png" />
<title>SITE NAME</title>
</head>
It worked for me. Hope it works for you too.
Solution 9 - Javascript
Replace the favicon.ico in your public folder with yours, that should get you going.
Solution 10 - Javascript
Use the file-loader for that:
{
test: /\.(svg|png|gif|jpg|ico)$/,
include: path.resolve(__dirname, path),
use: {
loader: 'file-loader',
options: {
context: 'src/assets',
name: 'root[path][name].[ext]'
}
}
}
Solution 11 - Javascript
I will give simple steps to add favicon :-)
-
Create your logo and save as
logo.png
-
Change
logo.png
tofavicon.ico
> Note : when you save it isfavicon.ico
make sure it's notfavicon.ico.png
-
It might take some time to update > change icon size in manifest.json if you can't wait
Solution 12 - Javascript
I use favicons-webpack-plugin
const FaviconsWebpackPlugin = require("favicons-webpack-plugin");
module.exports={
plugins:[
new FaviconsWebpackPlugin("./public/favicon.ico"),
//public is in the root folder in this app.
]
}
Solution 13 - Javascript
In my case -- I am running Visual Studio (Professional 2017) in debug mode with webpack 2.4.1 -- it was necessary to put the favicon.ico
into the root directory of the project, right where the folder src
is rather than in a folder public
, even though according to https://create-react-app.dev/docs/using-the-public-folder the latter should be the official location.
Solution 14 - Javascript
Ctrl+f5
clear your browser cache
Solution 15 - Javascript
This worked for me:
Add this in index.html (inside src folder along with favicon.ico)
**<link rel="icon" href="/src/favicon.ico" type="image/x-icon" />**
webpack.config.js is like:
plugins: [new HtmlWebpackPlugin({`enter code here`
template: './src/index.html'
})],
Solution 16 - Javascript
For anyone still searching... I managed to import the favicon in my index.html once I ran
npm install html-loader
And included the following in my webpack.config.js
:
// ... Other config options.
{
test: /\.html$/,
include: path.resolve(__dirname, 'public'), // Your path may be different.
use: [
{
loader: 'html-loader',
},
],
},
The file paths need to be relative to your source code, not the production code.
To check if the your build includes the favicon you can look up the production path in the url like this: localhost:xxxxx/path/to/favicon.png