Как свести к минимуму размер пакета веб-пакетов?
Я пишу веб-приложение, использующее react
и webpack
в качестве моего модуля.
Мой jsx
код действительно светлый, размер всей папки составляет 25 кб.
Мой bundle.js
, созданный из webpack
, равен 2,2 мб. После выполнения оптимизации с помощью флага -p
он уменьшает пакет до 700 кбайт, что по-прежнему чрезвычайно велико.
Я просмотрел файл react.min.js
и его размер составляет 130kb.
Возможно ли, что веб-пакет создает такие большие файлы, или я делаю что-то неправильно?
webpack.config.js
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: './public/components/main.jsx',
output: {
path: __dirname + "/public",
filename: 'bundle.js'
},
module: {
loaders: [{
test: /.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
}, {
test: /\.css$/,
loader: "style!css"
}]
}
};
ИЗМЕНИТЬ
package.json:
{
"name": "XChange",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"main": "./bin/www",
"devDependencies": {
"body-parser": "~1.13.2",
"cookie-parser": "~1.3.5",
"debug": "~2.2.0",
"express": "~4.13.1",
"jade": "~1.11.0",
"morgan": "~1.6.1",
"serve-favicon": "~2.3.0",
"react-dom": "~0.14.3",
"react": "~0.14.3",
"webpack": "~1.12.9",
"babel-loader": "~6.2.0",
"babel-core": "~6.2.1",
"babel-preset-react": "~6.1.18",
"babel-preset-es2015": "~6.1.18",
"react-bootstrap": "~0.28.1",
"material-ui": "~0.14.0-rc1",
"history": "~1.13.1",
"react-router": "~1.0.2",
"style-loader": "~0.13.0",
"css-loader": "~0.18.0"
},
"dependencies": {
"express-validator": "~2.18.0",
"mongoose": "~4.2.9",
"kerberos": "~0.0.17",
"bcrypt": "~0.8.5"
}
}
Ответы
Ответ 1
В соответствии с вашими комментариями вы используете material-ui
и react-bootstrap
. Эти зависимости связаны с веб-пакетом вместе с вашими пакетами react
и react-dom
. Каждый раз, когда вы require
или import
пакет, он входит в состав вашего пакета.
И здесь я догадываюсь. Вероятно, вы импортируете компоненты react-bootstrap
и material-ui
, используя путь библиотеки:
import { Button } from 'react-bootstrap';
import { FlatButton } from 'material-ui';
Это удобно и удобно, но это не только пакеты Button
и FlatButton
(и их зависимости), но библиотеки в целом.
Один из способов облегчить это - попробовать только import
или require
, что нужно, скажем, компонентный способ. Используя тот же пример:
import Button from 'react-bootstrap/lib/Button';
import FlatButton from 'material-ui/lib/flat-button';
Это будет только связывать Button
, FlatButton
и их соответствующие зависимости. Но не вся библиотека. Поэтому я попытался бы избавиться от всех ваших импортных библиотек и использовать компонентный способ.
Если вы не используете много компонентов, это должно значительно уменьшить размер вашего связанного файла.
В качестве дополнительного объяснения:
Когда вы используете библиотечный способ, вы импортируете все эти реакционные бутстрапы и все эти материалы-ui, независимо от того, какие из них вы фактически используете.
Ответ 2
01/2017 EDIT. С тех пор я узнал немного больше о разных плагинах Webpack и хотел обновить его. Оказывается, что UglifyJS имеет небольшую конфигурацию опций, которые, похоже, не очень популярны, но могут иметь драматическое влияние на ваш размер пакета. Это моя текущая конфигурация с некоторыми аннотациями (документы на сайте велики):
new webpack.optimize.UglifyJsPlugin({
comments: false, // remove comments
compress: {
unused: true,
dead_code: true, // big one--strip code that will never execute
warnings: false, // good for prod apps so users can't peek behind curtain
drop_debugger: true,
conditionals: true,
evaluate: true,
drop_console: true, // strips console statements
sequences: true,
booleans: true,
}
})
Однажды я столкнулся с неясной проблемой с uglify
-элементом экранов unicode unicode, поэтому будьте внимательны, если вы используете эти преобразования, чтобы такие кросс-подобные вещи были возможны.
Подробнее о конкретных опциях webpack
можно узнать в webpack docs с некоторыми последующими ссылками для дальнейшего чтения.
(sidenote: Я думаю, что ваш пакет .json запутан... по крайней мере некоторые из этих зависимостей dev зависят от каждого пакета. json, который я видел (например, react-starter-kit)
Если вы готовитесь к производству, вы должны предпринять еще несколько шагов, чтобы уменьшить размер вашего файла. Здесь снимок моего webpack.config.js:
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new webpack.optimize.DedupePlugin(),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
})
],
1) минимизирует/убирает ваш код
2) заменяет дублирующий код, чтобы свести к минимуму размер файла
3) сообщает webpack о том, что он использует для сборки node вещи, которые он использует
Наконец, если вы используете исходную карту (что вам, вероятно, и нужно), вы захотите добавить соответствующую строку. Sentry написал хорошее сообщение в блоге об этом.
В моей сборке я использую devtool: 'source-map'
для производства
Ответ 3
ОБНОВЛЕНО 05/18: обновить настройку UglifyJsPlugin для лучшей минимизации
Я использую ниже конфигурацию для минимизации в производственном коде.
plugins: [
new webpack.DefinePlugin({
'process.env': {
// This has effect on the react lib size
'NODE_ENV': JSON.stringify('production'),
}
}),
new ExtractTextPlugin("bundle.css", {allChunks: false}),
new webpack.optimize.AggressiveMergingPlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin({
mangle: true,
compress: {
warnings: false, // Suppress uglification warnings
pure_getters: true,
unsafe: true,
unsafe_comps: true,
screw_ie8: true,
conditionals: true,
unused: true,
comparisons: true,
sequences: true,
dead_code: true,
evaluate: true,
if_return: true,
join_vars: true
},
output: {
comments: false,
},
exclude: [/\.min\.js$/gi] // skip pre-minified libs
}),
new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]),
new CompressionPlugin({
asset: "[path].gz[query]",
algorithm: "gzip",
test: /\.js$|\.css$|\.html$/,
threshold: 10240,
minRatio: 0
})
],
Ответ 4
Вы посмотрели, как вы отправляете скрипты по проводам... У меня были очень простые компоненты реакции, которые составляли около 300 кбайт каждый, и это было после оптимизации веб-пакета.
После того, как они были gzipped, они спустились до 38kb. Все еще значительна - но это то, что мы получаем для использования функций tomorrows сегодня.
Если вы используете node/express для обслуживания статических ресурсов, включая ваш javascript, посмотрите на сжатие (https://github.com/expressjs/compression).
Я также предлагаю посмотреть руководство по лучшей практике node для производства https://expressjs.com/en/advanced/best-practice-performance.html
Если вы не используете файлы через node, тогда у apache (или другого веб-сервера) будут опции для сжатия текстовых файлов.