diff --git a/config/paths.js b/config/paths.js index 7645917fbc9..e6f2ff6cb3a 100644 --- a/config/paths.js +++ b/config/paths.js @@ -36,7 +36,6 @@ if (isInCreateReactAppSource) { module.exports = { appBuild: resolveOwn('../build'), appHtml: resolveOwn('../template/index.html'), - appFavicon: resolveOwn('../template/favicon.ico'), appPackageJson: resolveOwn('../package.json'), appSrc: resolveOwn('../template/src'), appNodeModules: resolveOwn('../node_modules'), @@ -47,7 +46,6 @@ if (isInCreateReactAppSource) { module.exports = { appBuild: resolveApp('build'), appHtml: resolveApp('index.html'), - appFavicon: resolveApp('favicon.ico'), appPackageJson: resolveApp('package.json'), appSrc: resolveApp('src'), appNodeModules: resolveApp('node_modules'), @@ -59,7 +57,6 @@ if (isInCreateReactAppSource) { module.exports = { appBuild: resolveApp('build'), appHtml: resolveApp('index.html'), - appFavicon: resolveApp('favicon.ico'), appPackageJson: resolveApp('package.json'), appSrc: resolveApp('src'), appNodeModules: resolveApp('node_modules'), diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js index ae95e0d92b8..5e28bb7c916 100644 --- a/config/webpack.config.dev.js +++ b/config/webpack.config.dev.js @@ -126,13 +126,23 @@ module.exports = { // When you `import` an asset, you get its (virtual) filename. // In production, they would get copied to the `build` folder. { - test: /\.(jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/, + test: /\.(ico|jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/, include: [paths.appSrc, paths.appNodeModules], + exclude: /\/favicon.ico$/, loader: 'file', query: { name: 'static/media/[name].[ext]' } }, + // A special case for favicon.ico to place it into build root directory. + { + test: /\/favicon.ico$/, + include: [paths.appSrc], + loader: 'file', + query: { + name: 'favicon.ico?[hash:8]' + } + }, // "url" loader works just like "file" loader but it also embeds // assets smaller than specified size as data URLs to avoid requests. { @@ -143,6 +153,15 @@ module.exports = { limit: 10000, name: 'static/media/[name].[ext]' } + }, + // "html" loader is used to process template page (index.html) to resolve + // resources linked with HTML tags. + { + test: /\.html$/, + loader: 'html', + query: { + attrs: ['link:href'], + } } ] }, @@ -169,7 +188,6 @@ module.exports = { new HtmlWebpackPlugin({ inject: true, template: paths.appHtml, - favicon: paths.appFavicon, }), // Makes some environment variables available to the JS code, for example: // if (process.env.NODE_ENV === 'development') { ... }. See `env.js`. diff --git a/config/webpack.config.prod.js b/config/webpack.config.prod.js index 66ca7a8cec1..ffeb75a9488 100644 --- a/config/webpack.config.prod.js +++ b/config/webpack.config.prod.js @@ -126,23 +126,33 @@ module.exports = { loader: ExtractTextPlugin.extract('style', 'css?-autoprefixer!postcss') // Note: this won't work without `new ExtractTextPlugin()` in `plugins`. }, + // JSON is not enabled by default in Webpack but both Node and Browserify + // allow it implicitly so we also enable it. { - // JSON is not enabled by default in Webpack but both Node and Browserify - // allow it implicitly so we also enable it. test: /\.json$/, include: [paths.appSrc, paths.appNodeModules], loader: 'json' }, + // "file" loader makes sure those assets end up in the `build` folder. + // When you `import` an asset, you get its filename. { - // "file" loader makes sure those assets end up in the `build` folder. - // When you `import` an asset, you get its filename. - test: /\.(jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/, + test: /\.(ico|jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/, + exclude: /\/favicon.ico$/, include: [paths.appSrc, paths.appNodeModules], loader: 'file', query: { name: 'static/media/[name].[hash:8].[ext]' } }, + // A special case for favicon.ico to place it into build root directory. + { + test: /\/favicon.ico$/, + include: [paths.appSrc], + loader: 'file', + query: { + name: 'favicon.ico?[hash:8]' + } + }, // "url" loader works just like "file" loader but it also embeds // assets smaller than specified size as data URLs to avoid requests. { @@ -153,6 +163,15 @@ module.exports = { limit: 10000, name: 'static/media/[name].[hash:8].[ext]' } + }, + // "html" loader is used to process template page (index.html) to resolve + // resources linked with HTML tags. + { + test: /\.html$/, + loader: 'html', + query: { + attrs: ['link:href'], + } } ] }, @@ -181,7 +200,6 @@ module.exports = { new HtmlWebpackPlugin({ inject: true, template: paths.appHtml, - favicon: paths.appFavicon, minify: { removeComments: true, collapseWhitespace: true, diff --git a/package.json b/package.json index 77910fcf349..1b389da8005 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "filesize": "3.3.0", "fs-extra": "0.30.0", "gzip-size": "3.0.0", + "html-loader": "0.4.3", "html-webpack-plugin": "2.22.0", "http-proxy-middleware": "0.17.0", "jest": "14.1.0", diff --git a/tasks/e2e.sh b/tasks/e2e.sh index a1566a85bdb..6e6c20c9420 100755 --- a/tasks/e2e.sh +++ b/tasks/e2e.sh @@ -67,6 +67,7 @@ test -e build/*.html test -e build/static/js/*.js test -e build/static/css/*.css test -e build/static/media/*.svg +test -e build/favicon.ico # Run tests npm run test @@ -96,6 +97,7 @@ test -e build/*.html test -e build/static/js/*.js test -e build/static/css/*.css test -e build/static/media/*.svg +test -e build/favicon.ico # Run tests npm run test @@ -113,6 +115,7 @@ test -e build/*.html test -e build/static/js/*.js test -e build/static/css/*.css test -e build/static/media/*.svg +test -e build/favicon.ico # Run tests npm run test diff --git a/template/index.html b/template/index.html index 72e10e94c6c..f89671553eb 100644 --- a/template/index.html +++ b/template/index.html @@ -3,6 +3,7 @@
+