使用React和Webpack添加Favicon

我正在尝试添加一个favicon到我使用webpack的React-based网站。 添加一个favicon是一个完全的噩梦,我已经尝试了许多解决scheme无济于事。 推荐给我的最新解决scheme叫做“favicons-webpack-plugin”,可以在这里find: https : //github.com/jantimon/favicons-webpack-plugin 。

如果有人能告诉我我做错了什么,你的帮助将不胜感激。

运行“npm run start”时出现以下错误

在这里输入图像描述

这是我的目录结构:

在这里输入图像描述

这是我的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 (eg `200`) or `null` console.log(error.name); // Error name eg "API Error" console.log(error.message); // Error description eg "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 } }) ] }); } 

这是我的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()}`)); 

浏览器在/favicon.ico查找您的favicon,所以这就是它的需求。 您可以通过导航到[address:port]/favicon.ico来查看是否已将其放置在正确的位置,并查看您的图标是否显示。

在开发模式下,您使用的是historyApiFallback,因此需要configurationwebpack以显式返回该路线的图标:

 historyApiFallback: { index: '[path/to/index]', rewrites: [ // shows favicon { from: /favicon.ico/, to: '[path/to/favicon]' } ] } 

在你的server.js文件中,尝试显式地重写url:

 app.configure(function() { app.use('/favicon.ico', express.static(__dirname + '[route/to/favicon]')); }); 

(或者你的设置更喜欢重写URL)

我build议生成一个真正的.ico文件,而不是使用.png ,因为我发现在浏览器中更可靠。

将你的favicon简单地添加到公共文件夹应该做的。 确保favicon被命名为“favicon.ico”。

对于未来的谷歌浏览器:您也可以使用copy-webpack-plugin并将其添加到webpack的生产configuration中:

 plugins: [ new CopyWebpackPlugin([ // relative path is from src { from: '../static/favicon.ico' }, // <- your path to favicon ]) ] 

既然你有一个服务器,我不知道我得到为什么需要一个插件? 你能不能创build一个目录,公开,并把它放在里面?

一旦你有一个public目录,你只需要添加下面一行到服务器代码:

 app.use('/', express.static(path.join(__dirname, 'public')))