如何最小化 webpack 包的大小?
How to minimize the size of webpack's bundle?
我正在编写一个网络应用程序,使用 react
和 webpack
作为我的模块打包器。
到目前为止,我的 jsx
代码真的很轻,整个文件夹的大小是 25 kb。
我从 webpack
创建的 bundle.js
是 2.2 MB。 运行 带有 -p
标志的优化后,它将包减少到 700kb,这仍然非常大。
我查看了 react.min.js
文件,它的大小是 130kb。
是不是webpack生成了这么大的文件还是我做错了什么?
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"
}
}
根据您的评论,您正在使用 material-ui
和 react-bootstrap
。这些依赖项由 webpack 与您的 react
和 react-dom
包捆绑在一起。任何时候你 require
或 import
一个包,它都会被打包为你的包文件的一部分。
这就是我的猜测。您可能正在使用 library 方式导入 react-bootstrap
和 material-ui
组件:
import { Button } from 'react-bootstrap';
import { FlatButton } from 'material-ui';
这很好用,但它不仅捆绑了 Button
和 FlatButton
(及其依赖项),还捆绑了 整个 库。
缓解它的一种方法是尝试仅 import
或 require
需要的东西,比方说 component 方式。使用相同的例子:
import Button from 'react-bootstrap/lib/Button';
import FlatButton from 'material-ui/lib/flat-button';
这只会捆绑 Button
、FlatButton
及其各自的依赖项。但不是整个图书馆。所以我会尝试摆脱你所有的 library 导入并改用 component 方式。
如果您没有使用很多组件,那么它应该会大大减少捆绑文件的大小。
进一步说明:
当您使用 库 方式导入 all these react-bootstrap and all these material-ui 组件时,无论您实际使用的是哪个。
01/2017 编辑 - 从那以后我对不同的 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,
}
})
我曾经遇到过一个关于转义 unicode 字符的 uglify
化的晦涩问题,所以如果您使用这些转换,那么请注意这样的边缘情况是可能的。
您可以在 webpack docs 中阅读有关 webpack
支持的特定选项的更多信息,以及一些后续链接以进一步阅读。
(旁注:我认为您的 package.json 是混淆的...至少其中一些开发依赖项是我所见过的每个 package.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) minifies/uglifies 你的代码
2) 替换重复代码以最小化文件大小
3) 告诉 webpack 省略它用于节点环境构建的一些东西
最后,如果您使用源映射(您可能应该使用),您需要添加适当的行。哨兵写道 a nice blog post about this。
在我的构建中,我使用开发工具:'source-map'
用于生产
你有没有看过你的脚本是如何通过网络发送的...我有一些非常简单的反应组件,每个组件大约 300kb,那是在 webpack 优化之后。
在它们被 gzip 压缩后,它们下降到 38kb。仍然相当大 - 但这就是我们今天使用明天的功能所得到的。
如果您使用 node/express 来提供静态资源,包括您的 javascript - 请查看压缩 (https://github.com/expressjs/compression)。
我还建议查看生产节点最佳实践指南 https://expressjs.com/en/advanced/best-practice-performance.html
如果您不通过节点提供文件,那么 apache(或其他网络服务器)将有用于压缩基于文本的文件的选项。
更新 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
})
],
我发现提及 source-map-explorer 实用程序很有用,它有助于了解 bundle.js 文件中的确切内容。它可以帮助您识别 bundle js 中是否有任何不必要的东西。
你可以从 npm 安装 source-map-explorer 并像
一样使用它
source-map-explorer yourBundle.js
除此之外,如@kimmiju 所述,请检查您的服务器是否正在使用一些压缩。
你也可以尝试asynchronously load routes(webpack中的延迟加载),这样你的整个bundlejs文件就不会一次性发送,而是分块发送用户导航到这些路线。
我正在编写一个网络应用程序,使用 react
和 webpack
作为我的模块打包器。
到目前为止,我的 jsx
代码真的很轻,整个文件夹的大小是 25 kb。
我从 webpack
创建的 bundle.js
是 2.2 MB。 运行 带有 -p
标志的优化后,它将包减少到 700kb,这仍然非常大。
我查看了 react.min.js
文件,它的大小是 130kb。
是不是webpack生成了这么大的文件还是我做错了什么?
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"
}
}
根据您的评论,您正在使用 material-ui
和 react-bootstrap
。这些依赖项由 webpack 与您的 react
和 react-dom
包捆绑在一起。任何时候你 require
或 import
一个包,它都会被打包为你的包文件的一部分。
这就是我的猜测。您可能正在使用 library 方式导入 react-bootstrap
和 material-ui
组件:
import { Button } from 'react-bootstrap';
import { FlatButton } from 'material-ui';
这很好用,但它不仅捆绑了 Button
和 FlatButton
(及其依赖项),还捆绑了 整个 库。
缓解它的一种方法是尝试仅 import
或 require
需要的东西,比方说 component 方式。使用相同的例子:
import Button from 'react-bootstrap/lib/Button';
import FlatButton from 'material-ui/lib/flat-button';
这只会捆绑 Button
、FlatButton
及其各自的依赖项。但不是整个图书馆。所以我会尝试摆脱你所有的 library 导入并改用 component 方式。
如果您没有使用很多组件,那么它应该会大大减少捆绑文件的大小。
进一步说明:
当您使用 库 方式导入 all these react-bootstrap and all these material-ui 组件时,无论您实际使用的是哪个。
01/2017 编辑 - 从那以后我对不同的 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,
}
})
我曾经遇到过一个关于转义 unicode 字符的 uglify
化的晦涩问题,所以如果您使用这些转换,那么请注意这样的边缘情况是可能的。
您可以在 webpack docs 中阅读有关 webpack
支持的特定选项的更多信息,以及一些后续链接以进一步阅读。
(旁注:我认为您的 package.json 是混淆的...至少其中一些开发依赖项是我所见过的每个 package.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) minifies/uglifies 你的代码
2) 替换重复代码以最小化文件大小
3) 告诉 webpack 省略它用于节点环境构建的一些东西
最后,如果您使用源映射(您可能应该使用),您需要添加适当的行。哨兵写道 a nice blog post about this。
在我的构建中,我使用开发工具:'source-map'
用于生产
你有没有看过你的脚本是如何通过网络发送的...我有一些非常简单的反应组件,每个组件大约 300kb,那是在 webpack 优化之后。 在它们被 gzip 压缩后,它们下降到 38kb。仍然相当大 - 但这就是我们今天使用明天的功能所得到的。 如果您使用 node/express 来提供静态资源,包括您的 javascript - 请查看压缩 (https://github.com/expressjs/compression)。 我还建议查看生产节点最佳实践指南 https://expressjs.com/en/advanced/best-practice-performance.html 如果您不通过节点提供文件,那么 apache(或其他网络服务器)将有用于压缩基于文本的文件的选项。
更新 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
})
],
我发现提及 source-map-explorer 实用程序很有用,它有助于了解 bundle.js 文件中的确切内容。它可以帮助您识别 bundle js 中是否有任何不必要的东西。 你可以从 npm 安装 source-map-explorer 并像
一样使用它source-map-explorer yourBundle.js
除此之外,如@kimmiju 所述,请检查您的服务器是否正在使用一些压缩。
你也可以尝试asynchronously load routes(webpack中的延迟加载),这样你的整个bundlejs文件就不会一次性发送,而是分块发送用户导航到这些路线。