使用Webpack优化你的第三方库
在webpack项目中使用了第三方库?使用这些方法可以缩小bundle!
async
async
是一组用于处理异步函数的实用程序. npm package
通常,您应该使用async-es
。它随ES模块一起提供,并且更适合webpack打包。
尽管如此,即使更喜欢使用async
,对于优化列表,请参阅async-es
部分。
async-es
async-es
是一组用于处理异步函数的实用程序。它与async
相同,但它更适合webpack打包。npm package
使用babel-plugin-lodash
删除未使用的方法
如果你使用async-es
作为单个导入,你将整个库打包到应用程序中 —— 即使你只使用它的几个方法:
// 您只使用`async.map`,但整个库被打包
import async from 'async-es';
async.map(['file1', 'file2', 'file3'], fs.stat, function(err, results) {
console.log(results);
});
使用babel-plugin-lodash
只选择你需要的async-es
方法:
// 应用Babel之前
import async from 'async-es';
async.map(['file1', 'file2', 'file3'], fs.stat, function(err, results) {
console.log(results);
});
↓
// 应用Babel之后
import _map from 'async-es/map';
_map(['file1', 'file2', 'file3'], fs.stat, function(err, results) {
console.log(results);
});
启用此插件,如下所示:
// .babelrc
{
"plugins": [["lodash", { "id": ["async-es"] }]],
}
babel-polyfill
babel-polyfill
是一个Babel的包,它加载了core-js
和一个自定义的再生器运行时。 Babel docs · npm package
有关优化列表,请参阅core-js
部分。
core-js
core-js
是一套用于ES5和ES2015+的polyfill。npm package
使用babel-preset-env
删除不必要的polyfill
如果使用Babel和babel-preset-env
编译代码,请添加useBuiltIns: true
选项。此选项将Babel配置为仅包含目标浏览器所必需的polyfill。例如,如果您将应用程序定位为支持Internet Explorer 11:
// .babelrc
{
"presets": [
[
"env",
{
"targets": {
"browsers": ["last 2 versions", "ie >= 11"]
}
}
]
]
}
启用useBuiltIns: true
将删除Internet Explorer 11已支持的所有功能(例如Object.create
,Object.keys
等)的polyfill。
将非转换代码发送到现代浏览器
所有支持<script type ="module">
的浏览器也支持现代JS功能,如async
/await
,箭头函数和类。使用此功能构建bundle包的两个版本,并使现代浏览器仅加载现代代码。有关指南,请参阅Philip Walton的文章。
date-fns
date-fns
是一个日期实用程序库。 npm package
启用babel-plugin-date-fns
babel-plugin-date-fns
使用特定日期函数函数的导入替换date-fns的完整导入:
import { format } from 'date-fns';
format(new Date(2014, 1, 11), 'MM/DD/YYYY');
↓
import _format from 'date-fns/format';
_format(new Date(2014, 1, 11), 'MM/DD/YYYY');
lodash
Lodash是一个实用程序库。 npm package
启用babel-plugin-lodash
babel-plugin-lodash
通过导入特定的Lodash功能取代了完整的Lodash导入:
import _map from 'lodash/map';
_map([1, 2, 3], i => i + 1);
↓
import _map from 'lodash/map';
_map([1, 2, 3], i => i + 1);
注意:该插件不适用于方法链 – 比如这样的代码不会被优化。
_([1, 2, 3]).map(i => i + 1).value();
为lodash-es
别名为lodash
一些依赖项可能使用lodash-es
而不是lodash
。如果是这样的话,Lodash将打包两次。
为避免这种情况,请将lodash-es
包别名为lodash
:
// webpack.config.js
module.exports = {
resolve: {
alias: {
'lodash-es': 'lodash',
},
},
};
启用lodash-webpack-plugin
lodash-webpack-plugin
剥离了你不需要的Lodash功能部分。例如,如果您使用_.get()
但不需要深层路径支持,则此插件可以删除它。将其添加到您的webpack配置中以使打包更小。
请谨慎使用该插件。 默认设置会删除许多功能,您的应用可能会使用其中一些功能。
lodash-es
lodash-es
是Lodash的ES模块。 npm package
有关优化列表,请参阅lodash
部分。
moment
Moment.js是一个处理日期的库。 npm package
使用moment-locales-webpack-plugin
删除未使用的语言
默认情况下,Moment.js附带160多KB压缩后的本地化文件。如果您的应用程序仅提供几种语言,则不需要所有这些文件。使用moment-locales-webpack-plugin
删除未使用的语言。
请谨慎使用该插件。 默认设置删除所有区域设置;如果您使用其中一些,这可能会破坏您的应用。
react
React是一个用于构建用户界面的库。 npm package
删除生产中的propTypes
声明
React不会在生产中执行propTypes
检查,但propTypes
声明仍然占用了bundle的一部分。 使用babel-plugin-transform-react-remove-prop-types
从构建过程中删除它们。
迁移到另一个类似React的库
React的替代品具有类似的API,具有更小的尺寸或更高的性能,但缺少一些功能(例如,Fragments, Portals或合成事件)。
- Preact | 最小的React替代方案(
preact@8.3.1
+preact-compat@3.18.3
7.6 kB gzipped;react@16.4.0
+react-dom@16.4.0
31.4 kB gzipped)| 没有合成事件| IE8支持polyfill - Nerv | 比React小,比Preact大(
nervjs@1.3.3
9.8 kB gzipped,不需要compat;react@16.4.0
+react-dom@16.4.0
31.4 kB gzipped)| Nerv的目标是100%使用相同的API(没有Fiber和Suspense),详见NervJS/nerv#10 | IE8支持 - Inferno | 比React小,大于Preact和Nerv(
inferno@5.4.2
+inferno-compat@5.4.2
11.3 kB gzipped;react@16.4.0
+react-dom@16.4.0
31.4 kB gzipped)| 比React更高的运行时性能,是所有React替代品中性能最高的,提供了手动优化的可能性 部分合成事件| IE8原生不受支持
谨慎迁移到替代品。 一些替代品没有合成事件或缺少一些React 16功能(Preact issue, Inferno issue, Nerv issue)。 但是,许多项目仍然可以在没有任何代码库更改的情况下进行迁移。 请参阅迁移指南:Preact, Inferno, Nerv。
reactstrap
Reactstrap是基于Bootstrap 4的React库。 npm package
使用babel-plugin-transform-imports
删除未使用的模块
从Reactstrap导入模块时:
import { Alert } from 'reactstrap';
其他Reactstrap模块也会打包到应用程序中并使其更大。
使用babel-plugin-transform-imports
去除未使用的模块:
// .babelrc
{
"plugins": [
["transform-imports", {
"reactstrap": {
"transform": "reactstrap/lib/${member}",
"preventFullImport": true
}
}]
]
}
要了解它是如何工作的,请查看babel-plugin-transform-imports
部分。
react-bootstrap
react-bootstrap
是基于React的Bootstrap 3库。 npm package
使用babel-plugin-transform-imports
删除未使用的模块
从react-bootstrap
导入模块时:
import { Alert } from 'reactstrap';
其他react-bootstrap
模块也会打包到应用程序中并使其更大。
使用babel-plugin-transform-imports
去除未使用的模块:
// .babelrc
{
"plugins": [
["transform-imports", {
"react-bootstrap": {
"transform": "react-bootstrap/es/${member}",
"preventFullImport": true
}
}]
]
}
要了解它是如何工作的,请查看babel-plugin-transform-imports
部分
react-router
React Router是React的流行路由器解决方案。 npm package
使用babel-plugin-transform-imports
删除未使用的模块
从React Router导入模块时:
import { withRouter } from 'react-router';
其他React Router模块也会打包到应用程序中并使其更大。
使用babel-plugin-transform-imports
去除未使用的模块:
// .babelrc
{
"plugins": [
["transform-imports", {
"react-router": {
"transform": "react-router/${member}",
"preventFullImport": true
}
}]
]
}
(这是使用React Router v4测试的。)
要了解它是如何工作的,请查看babel-plugin-transform-imports
部分。
styled-components
styled-components
是一个CSS-in-JS库。 npm
package
使用babel-plugin-styled-components
压缩代码
babel-plugin-styled-components
插件可以压缩用styled-components
编写的CSS代码。请参阅相关文档。
whatwg-fetch
whatwg-fetch
是一个完整的window.fetch()
polyfill。 npm package
替换为unfetch
unfetch
是window.fetch()
的500字节polyfill。与whatwg-fetch
不同,它不支持完整的window.fetch()
API,而是专注于polyfill最常用的部分。
谨慎迁移到unfetch
。 虽然它支持最流行的API部分,但如果它依赖于不太常见的东西,您的应用可能会无法正常运行。
适用于多个库的解决方案
当然,也有其他库的优化技巧。你可以将它们与常识一起使用,以获得更小或更高性能的bundle包。
babel-plugin-transform-imports
这个方便的babel插件会将您的导入转换为仅导入特定组件,这可确保不会包含整个库。
// Before
import { Grid, Row, Col } from 'react-bootstrap';
// After
import Grid from 'react-bootstrap/lib/Grid';
import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col';