Skip to content

Commit d295979

Browse files
andreypoppGeorge Czabania
authored and
George Czabania
committed
Load favicon through html-loader. (facebook#428)
* Load favicon through html-loader. Fixes facebook#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
1 parent 7e54fa2 commit d295979

File tree

7 files changed

+49
-11
lines changed

7 files changed

+49
-11
lines changed

config/paths.js

-3
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ if (isInCreateReactAppSource) {
3636
module.exports = {
3737
appBuild: resolveOwn('../build'),
3838
appHtml: resolveOwn('../template/index.html'),
39-
appFavicon: resolveOwn('../template/favicon.ico'),
4039
appPackageJson: resolveOwn('../package.json'),
4140
appStatic: resolveOwn('../template/static'),
4241
appSrc: resolveOwn('../template/src'),
@@ -48,7 +47,6 @@ if (isInCreateReactAppSource) {
4847
module.exports = {
4948
appBuild: resolveApp('build'),
5049
appHtml: resolveApp('index.html'),
51-
appFavicon: resolveApp('favicon.ico'),
5250
appPackageJson: resolveApp('package.json'),
5351
appStatic: resolveApp('static'),
5452
appSrc: resolveApp('src'),
@@ -61,7 +59,6 @@ if (isInCreateReactAppSource) {
6159
module.exports = {
6260
appBuild: resolveApp('build'),
6361
appHtml: resolveApp('index.html'),
64-
appFavicon: resolveApp('favicon.ico'),
6562
appPackageJson: resolveApp('package.json'),
6663
appStatic: resolveApp('static'),
6764
appSrc: resolveApp('src'),

config/webpack.config.dev.js

+20-2
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,23 @@ module.exports = {
127127
// When you `import` an asset, you get its (virtual) filename.
128128
// In production, they would get copied to the `build` folder.
129129
{
130-
test: /\.(jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/,
130+
test: /\.(ico|jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/,
131131
include: [paths.appSrc, paths.appNodeModules],
132+
exclude: /\/favicon.ico$/,
132133
loader: 'file',
133134
query: {
134135
name: 'static/media/[name].[ext]'
135136
}
136137
},
138+
// A special case for favicon.ico to place it into build root directory.
139+
{
140+
test: /\/favicon.ico$/,
141+
include: [paths.appSrc],
142+
loader: 'file',
143+
query: {
144+
name: 'favicon.ico?[hash:8]'
145+
}
146+
},
137147
// "url" loader works just like "file" loader but it also embeds
138148
// assets smaller than specified size as data URLs to avoid requests.
139149
{
@@ -144,6 +154,15 @@ module.exports = {
144154
limit: 10000,
145155
name: 'static/media/[name].[ext]'
146156
}
157+
},
158+
// "html" loader is used to process template page (index.html) to resolve
159+
// resources linked with <link href="./relative/path"> HTML tags.
160+
{
161+
test: /\.html$/,
162+
loader: 'html',
163+
query: {
164+
attrs: ['link:href'],
165+
}
147166
}
148167
]
149168
},
@@ -170,7 +189,6 @@ module.exports = {
170189
new HtmlWebpackPlugin({
171190
inject: true,
172191
template: paths.appHtml,
173-
favicon: paths.appFavicon,
174192
}),
175193
// Copy the static folder as-is to the build folder
176194
new CopyWebpackPlugin([

config/webpack.config.prod.js

+24-6
Original file line numberDiff line numberDiff line change
@@ -127,23 +127,33 @@ module.exports = {
127127
loader: ExtractTextPlugin.extract('style', 'css?-autoprefixer!postcss')
128128
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
129129
},
130+
// JSON is not enabled by default in Webpack but both Node and Browserify
131+
// allow it implicitly so we also enable it.
130132
{
131-
// JSON is not enabled by default in Webpack but both Node and Browserify
132-
// allow it implicitly so we also enable it.
133133
test: /\.json$/,
134134
include: [paths.appSrc, paths.appNodeModules],
135135
loader: 'json'
136136
},
137+
// "file" loader makes sure those assets end up in the `build` folder.
138+
// When you `import` an asset, you get its filename.
137139
{
138-
// "file" loader makes sure those assets end up in the `build` folder.
139-
// When you `import` an asset, you get its filename.
140-
test: /\.(jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/,
140+
test: /\.(ico|jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/,
141+
exclude: /\/favicon.ico$/,
141142
include: [paths.appSrc, paths.appNodeModules],
142143
loader: 'file',
143144
query: {
144145
name: 'static/media/[name].[hash:8].[ext]'
145146
}
146147
},
148+
// A special case for favicon.ico to place it into build root directory.
149+
{
150+
test: /\/favicon.ico$/,
151+
include: [paths.appSrc],
152+
loader: 'file',
153+
query: {
154+
name: 'favicon.ico?[hash:8]'
155+
}
156+
},
147157
// "url" loader works just like "file" loader but it also embeds
148158
// assets smaller than specified size as data URLs to avoid requests.
149159
{
@@ -154,6 +164,15 @@ module.exports = {
154164
limit: 10000,
155165
name: 'static/media/[name].[hash:8].[ext]'
156166
}
167+
},
168+
// "html" loader is used to process template page (index.html) to resolve
169+
// resources linked with <link href="./relative/path"> HTML tags.
170+
{
171+
test: /\.html$/,
172+
loader: 'html',
173+
query: {
174+
attrs: ['link:href'],
175+
}
157176
}
158177
]
159178
},
@@ -182,7 +201,6 @@ module.exports = {
182201
new HtmlWebpackPlugin({
183202
inject: true,
184203
template: paths.appHtml,
185-
favicon: paths.appFavicon,
186204
minify: {
187205
removeComments: true,
188206
collapseWhitespace: true,

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
"filesize": "3.3.0",
6363
"fs-extra": "0.30.0",
6464
"gzip-size": "3.0.0",
65+
"html-loader": "0.4.3",
6566
"html-webpack-plugin": "2.22.0",
6667
"http-proxy-middleware": "0.17.0",
6768
"jest": "14.1.0",

tasks/e2e.sh

+3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ test -e build/*.html
6767
test -e build/static/js/*.js
6868
test -e build/static/css/*.css
6969
test -e build/static/media/*.svg
70+
test -e build/favicon.ico
7071

7172
# Run tests
7273
npm run test
@@ -96,6 +97,7 @@ test -e build/*.html
9697
test -e build/static/js/*.js
9798
test -e build/static/css/*.css
9899
test -e build/static/media/*.svg
100+
test -e build/favicon.ico
99101

100102
# Run tests
101103
npm run test
@@ -113,6 +115,7 @@ test -e build/*.html
113115
test -e build/static/js/*.js
114116
test -e build/static/css/*.css
115117
test -e build/static/media/*.svg
118+
test -e build/favicon.ico
116119

117120
# Run tests
118121
npm run test

template/index.html

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<head>
44
<meta charset="utf-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<link rel="shortcut icon" href="./src/favicon.ico">
67
<title>React App</title>
78
</head>
89
<body>
File renamed without changes.

0 commit comments

Comments
 (0)