I have this really interesting webpack problem that I cannot figure out for the life of me.
I have the standard font-face declarations like so:
// MarkOT-ExtraLight
@font-face {
font-family: 'MarkOT-ExtraLight';
src: require('MarkOT-ExtraLight.eot?#iefix') format('embedded-opentype'),
require('MarkOT-ExtraLight.otf') format('opentype'),
require('MarkOT-ExtraLight.woff') format('woff'),
require('MarkOT-ExtraLight.ttf') format('truetype'),
require('MarkOT-ExtraLight.svg#MarkOT-ExtraLight') format('svg');
font-weight: normal;
font-style: normal;
}
```
Now I noticed that using require
worked fine except that none of my fonts were loading on my phone. So I switched from require
to url
and lo and behold, it all worked.
I deployed my app to heroku and it wasn't until I visited my site that I noticed that my css file had grown to 57.3 MB
from 2.8 MB
. Yes you heard that right, 57.3 MB
. I tested it three times by switching from using require
in my font-face declarations to using url
to confirm that's what was actually happening.
Has anyone ever experienced something similar? I've included my webpack config below.
var webpack = require('webpack');
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var BrowserSyncPlugin = require('browser-sync-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
//Environment constants
const DEVELOPMENT = "development";
const PRODUCTION = "production";
// Functions for resolving all the aliases
var path_base = path.resolve(__dirname, '../');
const resolve = path.resolve;
const base = function() {
var args = [path_base];
args.push.apply(args, arguments);
return resolve.apply(resolve,args);
};
const resolve_alias = base.bind(null, 'src/client');
const aliases = [
'actions',
'components',
'constants',
'containers',
'middleware',
'reducers',
'routes',
'store',
'styles',
'utils'
];
const resolved_aliases = aliases.reduce(function(accumulator, directory){
accumulator[directory] = resolve_alias(directory);
return accumulator;
}, {});
const productionVendors = [
'react',
'react-dom',
'react-router',
'redux',
'react-redux',
'redux-simple-router',
'classnames',
'underscore',
'history',
'immutable',
'object-assign',
'rx',
'slick-carousel',
'redux-actions'
];
const developmentVendors = [
'react',
'react-dom',
'react-router',
'redux',
'react-redux',
'redux-simple-router',
'classnames',
'underscore',
'history',
'immutable',
'redbox-react',
'object-assign',
'rx',
'slick-carousel',
'redux-actions'
];
const devPlugins = [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new HtmlWebpackPlugin({
templateContent: function(templateParams, webpackCompiler) {
return "<!DOCTYPE html><html><head lang='en'><meta charset='UTF-8'><meta name='viewport' content='width=device-width, initial-scale=1'><title>Busy - Better marketing for all.</title></head><body><div id='app'></div><script src='vendors.js'></script><script src='main.js'></script></body></html>"
}
}),
new BrowserSyncPlugin(
{
host: 'localhost',
port: 7000,
proxy: 'http://localhost:8080/webpack-dev-server/'
},
{
reload: false
}
)
]
const productionPlugins = [
new ExtractTextPlugin('[name].css'),
new webpack.IgnorePlugin(/\/config$/),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(PRODUCTION)
}
}),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
]
const environment = process.env.NODE_ENV || DEVELOPMENT;
var config = {
context: path.resolve(__dirname, '..'),
entry: {
main:
[
'font-awesome-webpack!./src/client/theme/font-awesome.config.js',
path.resolve(__dirname, '..', 'src/client/index.js')
]
},
output: {
path: path.resolve(__dirname, '..', 'dist'),
pathInfo: true,
filename: '[name].js'
},
module: {
preLoaders: [
{
test: /\.js$/,
loader: "eslint-loader",
exclude: /node_modules/
}
],
loaders: [
{
test: /src\/.+.js$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['react', 'es2015', 'stage-0']
}
},
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&mimetype=application/font-woff" },
{ test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/octet-stream" },
{ test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file" },
{ test: /\.otf(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/font-sfnt" },
{ test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: "url?mimetype=image/svg+xml" },
{
test: /\.(jpe?g|gif|png)$/,
loader: 'url?25000'
},
{
test: /\.mp4$/,
loader: 'file',
exclude: /node_modules/
}
]
},
resolve: {
alias: resolved_aliases,
modulesDirectories: [
'node_modules',
'src'
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js')
]
};
// Vendor splitting
config.entry.vendors = environment === DEVELOPMENT ? developmentVendors : productionVendors
if (environment === DEVELOPMENT) {
config.plugins = config.plugins.concat(devPlugins);
} else if (environment === PRODUCTION) {
config.plugins = config.plugins.concat(productionPlugins);
}
// Add development server entry points
if (environment === DEVELOPMENT) {
config.entry.main.unshift('webpack-dev-server/client?http://localhost:8080', 'webpack/hot/dev-server');
}
// Add dev tool configurations
if (environment === DEVELOPMENT) {
config.devServer = {
hot: true,
host: 'localhost',
port: 8080,
proxy: {"/*": "http://localhost:3000"}
}
}
// Configure CSS and Sass loaders
if (environment === DEVELOPMENT) {
config.module.loaders.push({ test: /.(scss|css)$/, loader: 'style!css?modules&importLoaders=3&localIdentName=[local]___[hash:base64:5]&sourceMap!autoprefixer?browsers=last 2 version!resolve-url!sass?sourceMapContents&outputStyle=expanded&sourceMap&includePaths[]=' + encodeURIComponent(require('node-bourbon').includePaths) +
'&includePaths[]=' + encodeURIComponent(require('node-neat').includePaths[1]) + '&includePaths[]=' + path.resolve(__dirname, '..', 'src/client/') });
} else if (environment === PRODUCTION) {
config.module.loaders.push({ test: /.(scss|css)$/, loader: ExtractTextPlugin.extract('style','css?modules&importLoaders=3&localIdentName=[local]___[hash:base64:5]&sourceMap!autoprefixer?browsers=last 2 version!resolve-url!sass?sourceMap&includePaths[]=' + encodeURIComponent(require('node-bourbon').includePaths) +
'&includePaths[]=' + encodeURIComponent(require('node-neat').includePaths[1]) + '&includePaths[]=' + path.resolve(__dirname, '..', 'src/client/') ) });
}
// Configure devtool
if (environment === DEVELOPMENT) {
config.devtool = 'inline-source-map';
} else if (environment === PRODUCTION) {
config.devtool = 'source-map';
}
module.exports = config;