如何优化 webpack/es6 开销?
Posted
技术标签:
【中文标题】如何优化 webpack/es6 开销?【英文标题】:How to optimize webpack/es6 overhead? 【发布时间】:2016-10-21 13:18:43 【问题描述】:我一直在优化我的应用程序的加载时间,在优化我的代码取得了一些快速的胜利后,我注意到似乎有一个 500 毫秒长的初始化阶段,所有的 require 语句似乎都得到了解决,或者其他什么。
这可以优化吗?如何优化?
我正在使用 webpack、react 和耦合几十个 npm 包。 结果文件是 2.8M 解压缩和大约 900k 压缩。应用本身的代码量并不大,主要是 npm 包。
我想知道我是否可以通过不同的方式编译它来避免所有需要以及什么不是实时的。
更新:我目前正在使用带有重复数据删除插件的生产版本。
【问题讨论】:
你试过npm dedupe
吗?有进展吗?
太好了,小费!我已经看到加载时间总体上有所减少,但我仍然看到 500 毫秒的 webpack_require 块。
如果你不做太多分块(看起来你没有),你可能应该go chunks 并通过延迟加载其中一些来改善开始时间。我不认为在不了解您的构建的情况下可以提出一些建议。您可以浏览配置文件并分析成本高昂的__webpack_require__
s 属于哪些模块。还要检查this。
感谢您的建议。我很可能会进行一些拆分,因为这似乎是解决这个问题的唯一方法。
查看分析器时,请确保区分自己/自己的时间和总时间。在__webpack_require__
中花费的总时间很高,因为运行模块计入 total 时间指标,但自用时间应该少得多(在函数中花费的时间,而不是子项花费的时间)。
【参考方案1】:
您可以做的一件事是使用devTool config 并更改生成源地图的方式。这应该会以牺牲调试的便利性为代价来加快速度。
Webpack 实际上在 http://webpack.github.io/docs/build-performance.html 上有一个关于如何优化性能的很棒的小指南。
基本上,它归结为您认为需要多少调试信息。
通过设置
devtool: "#source-map"
您保留原始代码,这显然是最容易调试的,但这是以文件大小/构建时间为代价的。
更新: 根据下面克里斯的评论,这里是another guide
【讨论】:
很好的答案!这个guide 可能会很好地补充它。 克里斯!== 克里斯。我的印象是这个问题涉及运行时性能而不是构建时间,所以这都是关于分块和延迟加载的。 @estus 我可能是非常错误的,但运行时性能确实涉及在保存/内容更改时重建/编译应用程序。它挂在require
语句上的位置可能是由于 webpack 试图对模块进行源映射?
我相信 OP 在页面加载时显示性能图,所以这是关于 app 运行时性能,而不是 builder 运行时性能。
克里斯 2.0 在这里。与开发版本相比,我确实在生产版本中获得了(稍微)更好的性能。【参考方案2】:
我不相信您的时间线来自缩小代码(比较映射文件中的 __webpack_require__
和缩小代码中的 f
)。
我将展示 minify 和一些插件可以将这个脚本的运行时间减少两倍。在 webpack 配置中,我将只展示配置之间的主要区别。
开发模式
webpack.config.js
devtool: 'cheap-module-eval-source-map',
cache: true,
debug: true,
时间线 - 473 毫秒
生产模式
webpack.config.js
plugins: [
'transform-react-remove-prop-types',
'transform-react-constant-elements',
'transform-react-inline-elements'
],
cache: false,
debug: false,
plugins: [
// Search for equal or similar files and deduplicate them in the output
// https://webpack.github.io/docs/list-of-plugins.html#dedupeplugin
new webpack.optimize.DedupePlugin(),
// Minimize all javascript output of chunks
// https://github.com/mishoo/UglifyJS2#compressor-options
new webpack.optimize.UglifyJsPlugin(
compress:
screw_ie8: true,
warnings: false,
,
),
// A plugin for a more aggressive chunk merging strategy
// https://webpack.github.io/docs/list-of- plugins.html#aggressivemergingplugin
new webpack.optimize.AggressiveMergingPlugin(),
]
时间线 - 228 毫秒
如果您想从这个解释中深入分析webpack.config.js
,您可以查看react-starter-kit 的源代码。
【讨论】:
嗨,真的 - 我也注意到了。感谢您展示在缩小时节省了多少时间!我会检查你的配置,看看我还能应用什么。【参考方案3】:正如一些 cmets 已经指出的,我们必须区分构建时和运行时。 webpack 文档中的referenced guide 是关于构建性能。
虽然不使用源映射和缩小代码等开发工具会影响执行速度,但我认为最重要的是分块/延迟加载(正如estus 已经指出的那样)。
您应该决定初始渲染不需要应用程序的哪些部分。这些部分应该被移动到另一个块中并通过require.ensure()
延迟加载。
通常你的路由器是一个典型的异步加载东西的地方:
<Router>
<Route
path="/dashboard"
getComponent=loadPage("Dashboard")
/>
</Router>
function loadPage(page)
return (location, cb) => pages[page](cb);
const pages =
Dashboard(cb)
require.ensure(
["./Dashboard.js"],
require => cb(null, require("./Dashboard.js").default)
// .default is required in case you are using ES2015 modules
);
;
现在,所有仅在 Dashboard
上需要的模块都将被移动到一个单独的块中。
冗长的require.ensure
部分甚至可以通过将所有***组件(我在这里称它们为pages
)移动到像pages
这样的专用文件夹来进行优化。然后你可以配置 webpack 使用bundle-loader 来异步加载这些东西:
// webpack.config.js
...
test: /\.jsx$/,
include: [
path.resolve("path", "to", "pages"),
],
loaders: [
"bundle-loader?" + JSON.stringify(
lazy: true
)
]
,
那么你的路由器看起来像:
// This does not actually import the Dashboard,
// but a function which loads the dashboard.
import Dashboard from "path/to/pages/Dashboard";
function loadPage(page)
return (location, cb) => pages[page](module =>
cb(null, module.default);
);
const pages =
Dashboard
;
如果你超级懒,只想引用相同的文件名而不手动创建pages
-Object,你也可以使用require contexts:
function loadPage(page)
return (location, cb) =>
require("./path/to/pages/" + page + ".jsx")(
module => cb(null, module.default)
);
【讨论】:
以上是关于如何优化 webpack/es6 开销?的主要内容,如果未能解决你的问题,请参考以下文章
react + webpack +es6 hello world