Есть небольшое SPA на React.js. Ничего сверх, все как у людей - router, flux, material-ui, больше десятка компонентов. Собирается это все, конечно же, с помощью Webpack. На выходе получается минифицированный файл bundle.js размером 603kb. O_o
Так должно быть? Как оптимизировать/уменьшить файл сборки? Куда обращать внимание?
Конфигурации проекта ниже.
package.json...
"dependencies": {
"events": "^1.1.1",
"flux": "^2.1.1",
"keymirror": "^0.1.1",
"less": "^2.7.1",
"material-ui": "^0.15.2",
"react": "^15.2.1",
"react-dom": "^15.2.1",
"react-router": "^2.6.0",
"react-tap-event-plugin": "^1.0.0"
},
"devDependencies": {
"autoprefixer-loader": "*",
"babel-core": "^6.9.1",
"babel-loader": "^6.2.4",
"babel-preset-es2015": "^6.9.0",
"babel-preset-react": "^6.5.0",
"babel-preset-stage-0": "^6.5.0",
"css-loader": "^0.22.0",
"extract-text-webpack-plugin": "^1.0.1",
"file-loader": "^0.8.5",
"image-webpack-loader": "^1.8.0",
"json-loader": "^0.5.4",
"less-loader": "^2.2.2",
"react-hot-loader": "3.0.0-beta.2",
"style-loader": "^0.13.0",
"url-loader": "^0.5.6",
"webpack": "^1.13.1",
"webpack-dev-server": "1.14.0"
}
...
webpack.config,jsvar webpack = require('webpack');
const NODE_ENV = process.env.NODE_ENV || 'development';
const NODE_HOST = process.env.NODE_HOST || '0.0.0.0';
const NODE_PORT = process.env.NODE_PORT || 8090;
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: getEntrySources(['./src/main.js']),
output: {
path: __dirname + '/public/build',
publicPath: "/build/",
filename: "bundle.js"
},
module: {
loaders: [
{
test: /\.css$/,
loader: (process.env.NODE_ENV === "production")
? ExtractTextPlugin.extract('style', 'css!autoprefixer')
: "style-loader!css-loader!autoprefixer-loader",
exclude: [/node_modules/, /public/]
},
{
test: /\.less$/,
loader: (process.env.NODE_ENV === "production")
? ExtractTextPlugin.extract('style', 'css!less!autoprefixer')
: "style-loader!css-loader!autoprefixer-loader!less",
exclude: [/node_modules/, /public/]
},
{
test: /\.(jpe?g|png|gif|svg|ico)$/i,
loaders: [
'file?name=[sha512:hash:base64:7].[ext]',
'image-webpack?progressive=true&optimizationLevel=7&interlaced=true'
],
exclude: [/node_modules/, /public/, /src\/fonts/]
},
{
test : /\.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
loader : 'file?name=[name].[ext]',
exclude: [/node_modules/, /public/, /src\/img/]
},
{
test: /\.json$/,
loader: "json-loader"
},
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ["es2015", "stage-0", "react"],
plugins: (process.env.NODE_ENV === "production")
? []
: ["react-hot-loader/babel"]
}
}
]
},
devServer: {
colors: true,
historyApiFallback: true,
inline: false,
contentBase: __dirname + '/public',
port: NODE_PORT,
hot: true
},
plugins: [
new ExtractTextPlugin('bundle.css', {
allChunks: true,
disable: process.env.NODE_ENV == 'development'
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
]
};
if (NODE_ENV == 'production') {
module.exports.plugins.push(
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
drop_console: true,
unsafe: true
}
})
);
}
function getEntrySources(sources) {
if (process.env.NODE_ENV !== 'production') {
sources.unshift('react-hot-loader/patch');
sources.unshift(`webpack-dev-server/client?http://${NODE_HOST}:${NODE_PORT}`);
sources.unshift('webpack/hot/only-dev-server');
}
return sources;
}
Результат после запуска аналайзера
webpack --json | webpack-bundle-size-analyzerreact: 658.9 KB (35.3%)
material-ui: 404.68 KB (21.7%)
lodash: 133.82 KB (7.18%)
react-router: 101.96 KB (5.47%)
sockjs-client: 98.54 KB (5.29%)
inline-style-prefixer: 54.42 KB (2.92%)
history: 49.02 KB (2.63%)
warning: 1.76 KB (3.60%)
<self>: 47.26 KB (96.4%)
json3: 42.28 KB (2.27%)
url: 36.04 KB (1.93%)
punycode: 14.31 KB (39.7%)
<self>: 21.74 KB (60.3%)
fbjs: 33.59 KB (1.80%)
react-proxy: 21.75 KB (1.17%)
bowser: 15.71 KB (0.843%)
react-tap-event-plugin: 9.95 KB (0.534%)
fbjs: 2.56 KB (25.7%)
<self>: 7.4 KB (74.3%)
url-parse: 9.44 KB (0.506%)
flux: 8.93 KB (0.479%)
fbjs: 1.47 KB (16.5%)
<self>: 7.46 KB (83.5%)
recompose: 8.59 KB (0.461%)
events: 8.13 KB (0.436%)
debug: 7.67 KB (0.412%)
style-loader: 6.99 KB (0.375%)
react-hot-loader: 5.69 KB (0.305%)
react-event-listener: 5.17 KB (0.278%)
querystring: 4.51 KB (0.242%)
node-libs-browser: 4.4 KB (0.236%)
process: 4.4 KB (100%)
<self>: 0 B (0.00%)
deep-equal: 3.8 KB (0.204%)
webpack: 3.36 KB (0.180%)
keycode: 2.7 KB (0.145%)
webpack-dev-server: 2.42 KB (0.130%)
ms: 2.28 KB (0.122%)
object-assign: 1.95 KB (0.104%)
warning: 1.76 KB (0.0947%)
invariant: 1.48 KB (0.0794%)
css-loader: 1.47 KB (0.0789%)
query-string: 1.45 KB (0.0776%)
keymirror: 1.38 KB (0.0740%)
hoist-non-react-statics: 1.35 KB (0.0727%)
querystringify: 1.27 KB (0.0682%)
requires-port: 753 B (0.0394%)
inherits: 672 B (0.0352%)
simple-assign: 281 B (0.0147%)
hyphenate-style-name: 271 B (0.0142%)
global: 243 B (0.0127%)
strict-uri-encode: 182 B (0.00953%)
strip-ansi: 161 B (0.00843%)
ansi-regex: 135 B (0.00707%)
react-dom: 63 B (0.00330%)
react-addons-create-fragment: 59 B (0.00309%)
react-addons-transition-group: 59 B (0.00309%)
<self>: 104.54 KB (5.61%)