Commit 60178ac7 authored by Andrey Popp's avatar Andrey Popp Committed by Dan Abramov
Browse files

Load favicon through html-loader. (#428)

* Load favicon through html-loader.

Fixes #291.

* Add test for *.ico in e2e test suite

* Configure html-loader to process <link href="...">

* Address feedback on html-loader inclusion.

* Place favicon.ico at the root of the build dir

* Make comment style consistent between prod and dev webpack configs

* Fix html-loader config in dev mode
parent 25a0b66f
Showing with 49 additions and 11 deletions
+49 -11
...@@ -36,7 +36,6 @@ if (isInCreateReactAppSource) { ...@@ -36,7 +36,6 @@ if (isInCreateReactAppSource) {
module.exports = { module.exports = {
appBuild: resolveOwn('../build'), appBuild: resolveOwn('../build'),
appHtml: resolveOwn('../template/index.html'), appHtml: resolveOwn('../template/index.html'),
appFavicon: resolveOwn('../template/favicon.ico'),
appPackageJson: resolveOwn('../package.json'), appPackageJson: resolveOwn('../package.json'),
appSrc: resolveOwn('../template/src'), appSrc: resolveOwn('../template/src'),
appNodeModules: resolveOwn('../node_modules'), appNodeModules: resolveOwn('../node_modules'),
...@@ -47,7 +46,6 @@ if (isInCreateReactAppSource) { ...@@ -47,7 +46,6 @@ if (isInCreateReactAppSource) {
module.exports = { module.exports = {
appBuild: resolveApp('build'), appBuild: resolveApp('build'),
appHtml: resolveApp('index.html'), appHtml: resolveApp('index.html'),
appFavicon: resolveApp('favicon.ico'),
appPackageJson: resolveApp('package.json'), appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'), appSrc: resolveApp('src'),
appNodeModules: resolveApp('node_modules'), appNodeModules: resolveApp('node_modules'),
...@@ -59,7 +57,6 @@ if (isInCreateReactAppSource) { ...@@ -59,7 +57,6 @@ if (isInCreateReactAppSource) {
module.exports = { module.exports = {
appBuild: resolveApp('build'), appBuild: resolveApp('build'),
appHtml: resolveApp('index.html'), appHtml: resolveApp('index.html'),
appFavicon: resolveApp('favicon.ico'),
appPackageJson: resolveApp('package.json'), appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'), appSrc: resolveApp('src'),
appNodeModules: resolveApp('node_modules'), appNodeModules: resolveApp('node_modules'),
......
...@@ -126,13 +126,23 @@ module.exports = { ...@@ -126,13 +126,23 @@ module.exports = {
// When you `import` an asset, you get its (virtual) filename. // When you `import` an asset, you get its (virtual) filename.
// In production, they would get copied to the `build` folder. // 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], include: [paths.appSrc, paths.appNodeModules],
exclude: /\/favicon.ico$/,
loader: 'file', loader: 'file',
query: { query: {
name: 'static/media/[name].[ext]' 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 // "url" loader works just like "file" loader but it also embeds
// assets smaller than specified size as data URLs to avoid requests. // assets smaller than specified size as data URLs to avoid requests.
{ {
...@@ -143,6 +153,15 @@ module.exports = { ...@@ -143,6 +153,15 @@ module.exports = {
limit: 10000, limit: 10000,
name: 'static/media/[name].[ext]' name: 'static/media/[name].[ext]'
} }
},
// "html" loader is used to process template page (index.html) to resolve
// resources linked with <link href="./relative/path"> HTML tags.
{
test: /\.html$/,
loader: 'html',
query: {
attrs: ['link:href'],
}
} }
] ]
}, },
...@@ -169,7 +188,6 @@ module.exports = { ...@@ -169,7 +188,6 @@ module.exports = {
new HtmlWebpackPlugin({ new HtmlWebpackPlugin({
inject: true, inject: true,
template: paths.appHtml, template: paths.appHtml,
favicon: paths.appFavicon,
}), }),
// Makes some environment variables available to the JS code, for example: // Makes some environment variables available to the JS code, for example:
// if (process.env.NODE_ENV === 'development') { ... }. See `env.js`. // if (process.env.NODE_ENV === 'development') { ... }. See `env.js`.
......
...@@ -126,23 +126,33 @@ module.exports = { ...@@ -126,23 +126,33 @@ module.exports = {
loader: ExtractTextPlugin.extract('style', 'css?-autoprefixer!postcss') loader: ExtractTextPlugin.extract('style', 'css?-autoprefixer!postcss')
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`. // 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$/, test: /\.json$/,
include: [paths.appSrc, paths.appNodeModules], include: [paths.appSrc, paths.appNodeModules],
loader: 'json' 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. test: /\.(ico|jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/,
// When you `import` an asset, you get its filename. exclude: /\/favicon.ico$/,
test: /\.(jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/,
include: [paths.appSrc, paths.appNodeModules], include: [paths.appSrc, paths.appNodeModules],
loader: 'file', loader: 'file',
query: { query: {
name: 'static/media/[name].[hash:8].[ext]' 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 // "url" loader works just like "file" loader but it also embeds
// assets smaller than specified size as data URLs to avoid requests. // assets smaller than specified size as data URLs to avoid requests.
{ {
...@@ -153,6 +163,15 @@ module.exports = { ...@@ -153,6 +163,15 @@ module.exports = {
limit: 10000, limit: 10000,
name: 'static/media/[name].[hash:8].[ext]' name: 'static/media/[name].[hash:8].[ext]'
} }
},
// "html" loader is used to process template page (index.html) to resolve
// resources linked with <link href="./relative/path"> HTML tags.
{
test: /\.html$/,
loader: 'html',
query: {
attrs: ['link:href'],
}
} }
] ]
}, },
...@@ -181,7 +200,6 @@ module.exports = { ...@@ -181,7 +200,6 @@ module.exports = {
new HtmlWebpackPlugin({ new HtmlWebpackPlugin({
inject: true, inject: true,
template: paths.appHtml, template: paths.appHtml,
favicon: paths.appFavicon,
minify: { minify: {
removeComments: true, removeComments: true,
collapseWhitespace: true, collapseWhitespace: true,
......
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
"filesize": "3.3.0", "filesize": "3.3.0",
"fs-extra": "0.30.0", "fs-extra": "0.30.0",
"gzip-size": "3.0.0", "gzip-size": "3.0.0",
"html-loader": "0.4.3",
"html-webpack-plugin": "2.22.0", "html-webpack-plugin": "2.22.0",
"http-proxy-middleware": "0.17.0", "http-proxy-middleware": "0.17.0",
"jest": "14.1.0", "jest": "14.1.0",
......
...@@ -67,6 +67,7 @@ test -e build/*.html ...@@ -67,6 +67,7 @@ test -e build/*.html
test -e build/static/js/*.js test -e build/static/js/*.js
test -e build/static/css/*.css test -e build/static/css/*.css
test -e build/static/media/*.svg test -e build/static/media/*.svg
test -e build/favicon.ico
# Run tests # Run tests
npm run test npm run test
...@@ -96,6 +97,7 @@ test -e build/*.html ...@@ -96,6 +97,7 @@ test -e build/*.html
test -e build/static/js/*.js test -e build/static/js/*.js
test -e build/static/css/*.css test -e build/static/css/*.css
test -e build/static/media/*.svg test -e build/static/media/*.svg
test -e build/favicon.ico
# Run tests # Run tests
npm run test npm run test
...@@ -113,6 +115,7 @@ test -e build/*.html ...@@ -113,6 +115,7 @@ test -e build/*.html
test -e build/static/js/*.js test -e build/static/js/*.js
test -e build/static/css/*.css test -e build/static/css/*.css
test -e build/static/media/*.svg test -e build/static/media/*.svg
test -e build/favicon.ico
# Run tests # Run tests
npm run test npm run test
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="./src/favicon.ico">
<title>React App</title> <title>React App</title>
</head> </head>
<body> <body>
......
File moved
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment