J'essaie d'ajouter un favicon à un site Web basé sur React que j'ai créé à l'aide de webpack. Ajouter un favicon a été un véritable cauchemar et j'ai essayé de nombreuses solutions en vain. La dernière solution qui m'a été recommandée s'appelle 'favicons-webpack-plugin', que l'on peut trouver ici: https://github.com/jantimon/favicons-webpack-plugin .
Si quelqu'un pouvait me dire ce que je faisais mal, votre aide serait grandement appréciée.
Je reçois le message d'erreur suivant lorsque je lance npm run start
Ceci est ma structure de répertoire:
Ceci est mon fichier webpack.config.js:
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
}
})
]
});
}
Ceci est mon fichier server.js:
/* 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()}`));
Pour les futurs utilisateurs: Vous pouvez également utiliser copy-webpack-plugin et l'ajouter à la configuration de la production de webpack:
plugins: [
new CopyWebpackPlugin([
// relative path is from src
{ from: './static/favicon.ico' }, // <- your path to favicon
])
]
Les navigateurs recherchent votre favicon dans /favicon.ico
, c'est donc ce qu'il faut. Vous pouvez vérifier si vous l'avez placé au bon endroit en naviguant dans [address:port]/favicon.ico
et en vérifiant si votre icône apparaît.
En mode dev, vous utilisez historyApiFallback, vous devrez donc configurer Webpack pour qu'il retourne explicitement votre icône pour cette route:
historyApiFallback: {
index: '[path/to/index]',
rewrites: [
// shows favicon
{ from: /favicon.ico/, to: '[path/to/favicon]' }
]
}
Dans votre fichier server.js
, essayez de réécrire explicitement l'URL:
app.configure(function() {
app.use('/favicon.ico', express.static(__dirname + '[route/to/favicon]'));
});
(ou si votre configuration préfère réécrire les URL)
Je suggère de générer un vrai fichier .ico
plutôt que d'utiliser un .png
, car je trouve que cela est plus fiable pour tous les navigateurs.
Ajouter votre favicon simplement dans le dossier public devrait faire l'affaire. Assurez-vous que le favicon est nommé "favicon.ico".
Voici tout ce dont vous avez besoin:
new HtmlWebpackPlugin({
favicon: "./src/favicon.gif"
})
C'est certainement après avoir ajouté "favicon.gif" au dossier "src".
Cela transférera l'icône dans votre dossier de construction et l'inclura dans votre balise comme ceci <link rel="shortcut icon" href="favicon.gif">
. C’est plus sûr que de simplement importer avec copyWebpackPLugin
Une autre alternative est
npm install react-favicon
Et dans votre application, vous feriez simplement:
import Favicon from 'react-favicon';
//other codes
ReactDOM.render(
<div>
<Favicon url="/path/to/favicon.ico"/>
// do other stuff here
</div>
, document.querySelector('.react'));
Cela revient à ajouter tout autre script ou feuille de style externe. Tout ce que vous avez à faire est de vous concentrer sur le type chemin correct et rel et type .
Remarque: lorsque mon image de favicon était dans le dossier des actifs, il s’agissait de ne affichant pas le favicon. Donc, je ai copié l'image dans le même dossier que mon index.html et cela a parfaitement fonctionné comme il se doit.
<head>
<link rel="shortcut icon" type="image/png/ico" href="/favicon.png" />
<title>SITE NAME</title>
</head>
Cela a fonctionné pour moi. J'espère que ça marchera pour toi aussi.
Voici comment je l'ai fait.
en public/index.html
Ajoute des liens de favicon générés
dans src/App.js
import '/path/to/favicon.ico';
dans webpack.js
nouveau HTMLWebpackPlugin ({ favicon: '/path/to/favicon.ico' ,}),
Remarque. J'utilise historyApiFallback en mode dev, mais je n'avais besoin d'aucune configuration supplémentaire pour que le favicon fonctionne, ni du côté serveur.
Je vais donner des étapes simples pour ajouter un favicon :-)
logo.png
Remplacez logo.png
par favicon.ico
Remarque: lorsque vous sauvegardez, il s'agit de
favicon.ico
, assurez-vous que ce n'est pasfavicon.ico.png
Il faudra peut-être un peu de temps pour mettre à jour
changez la taille de l'icône dans manifest.json si vous ne pouvez pas attendre
Utilisez le file-loader pour cela:
{
test: /\.(svg|png|gif|jpg|ico)$/,
include: path.resolve(__dirname, path),
use: {
loader: 'file-loader',
options: {
context: 'src/assets',
name: 'root[path][name].[ext]'
}
}
}