脚本宝典收集整理的这篇文章主要介绍了

开发工具心得:如何 10 倍提高你的 Webpack 构建效率

脚本宝典小编觉得挺不错的,现在分享给大家,也给大家做个参考,希望能帮助你少写一行代码,多一份安全和惬意。
<p><code></p> <h2 id="articleHeader0">0. 前言</h2> <p><span class="img-wrap"><img data-src="/img/remote/1460000005770045" src="/img/remote/1460000005770045" alt="babel+webpack+es6+react" title="babel+webpack+es6+react" style="cursor: pointer; display: inline;"></span></p> <blockquote> <p>图1:ES6 + Webpack + <a href="http://www.js-code.com/tag/react" title="React" target="_blank">React</a> + Babel</p> </blockquote> <p>webpack 是个好东西,和 NPM 搭配起来使用管理模块实在非常方便。而 Babel 更是神一般的存在,让我们在这个浏览器尚未全面普及 ES6 语法的时代可以先一步体验到新的语法带来的便利和效率上的提升。在 <a href="http://www.js-code.com/tag/react" title="React" target="_blank">React</a> 项目架构中这两个东西基本成为了标配,但 commonjs 的模块必须在使用前经过 webpack 的构建(后文称为 build)才能在浏览器端使用,而每次修改也都需要重新构建(后文称为 rebuild)才能生效,如何提高 webpack 的构建效率成为了提高开发效率的关键之一。</p> <h2 id="articleHeader1">1. Webpack 的构建流程</h2> <p>在开始正式的优化之前,让我们先回顾一下 Webpack 的构建流程,有哪些关键步骤,只有了解了这些,我们才能分析出哪些地方有优化的可能性。<br /><span class="img-wrap"><img data-src="/img/remote/1460000004839887" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="webpack official" title="webpack official" style="cursor: pointer;"></span></p> <blockquote> <p>图2:webpack is a module bundler.</p> </blockquote> <p>首先,我们来看看官方对于 Webpack 的理念阐释,webapck 把所有的静态资源都看做是一个 module,通过 webpack,将这些 module 组成到一个 bundle 中去,从而实现在页面上引入一个 bundle.js,来实现所有静态资源的加载。所以详细一点看,webpack 应该是这样的:</p> <p><span class="img-wrap"><img data-src="/img/remote/1460000005770047" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="" title="" style="cursor: pointer;"></span></p> <blockquote> <p>图3:Every <a href="http://www.js-code.com/tag/static" title="static" target="_blank">static</a> asset should be able to be a module --webpack</p> </blockquote> <p>通过 loader,webpack 可以把各种非原生 js 的静态资源转换成 JavaScript,所以理论上任何一种静态资源都可以成为一个 module。 <br />当然 webpack 还有很多其他好玩的特性,但不是本文的重点因此不铺开进行说明了。了解了上述的过程,我们就可以根据这些过程的前后处理进行对应的优化,接下来我们会针对 build 和 rebuild 的过程给与相应的意见。</p> <h2 id="articleHeader2">2. RESOLVE</h2> <p>我们先从解析模块路径和分析依赖讲起,有人可能觉得这无所谓,但当项目应用依赖的模块越来越多,越来越重时,项目越来越大,文件和文件夹越来越多时,这个过程就变得越来越关乎性能。</p> <h3 id="articleHeader3">2.1 减小 Webpack 覆盖的范围</h3> <blockquote> <p>build +, rebuild +</p> </blockquote> <p>webpack 默认会去寻找所有 resolve.root 下的模块,但是有些目录我们是可以明确告知 webpack 不要管这里,从而减轻 webpack 的工作量。这时会用到 <code>module.noParse</code> 参数。</p> <h3 id="articleHeader4">2.2 Resolove.root VS Resolove.moduledirectories</h3> <blockquote> <p>build +, rebuild +</p> </blockquote> <p><code>root</code> 和 <code>moduledirectories</code> 如果只从用法上来看,似乎是可以互相替代的。但因为 <code>moduledirectories</code> 从设计上是取相对路径,所以比起 <code>root</code> ,所以会多 parse 很多路径。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="resolve: { root: path.resolve('src/node_modules'), extensions: ['', '.js', '.jsx'] }, resolve: { modulesDirectories: ['node_modules', './src'], extensions: ['', '.js', '.jsx'] }," title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="js">resolve: { <span class="hljs-attr">root</span>: path.resolve(<span class="hljs-string">'src/<a href="http://www.js-code.com/tag/node" title="浏览关于“node”的文章" target="_blank" class="tag_link">node</a>_modules'</span>), <span class="hljs-attr">extensions</span>: [<span class="hljs-string">''</span>, <span class="hljs-string">'.js'</span>, <span class="hljs-string">'.jsx'</span>] }, <span class="hljs-attr">resolve</span>: { <span class="hljs-attr">modulesDirectories</span>: [<span class="hljs-string">'node_modules'</span>, <span class="hljs-string">'./src'</span>], <span class="hljs-attr">extensions</span>: [<span class="hljs-string">''</span>, <span class="hljs-string">'.js'</span>, <span class="hljs-string">'.jsx'</span>] },</code></pre> <p>上面的配置,只会解析</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="./src/node_modules/a" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs groovy"><code class="sh" style="word-break: break-word; white-space: initial;">.<span class="hljs-regexp">/src/</span>node_modules/a</code></pre> <p>==== 此处有修改 2016/09/10 感谢 <a href="/u/lili_21">@lili_21</a> ====</p> <p>而下面的配置会解析</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="/some/folder/structure/node_modules/a /some/folder/structure/src/a /some/folder/node_modules/a /some/folder/src/a /some/node_modules/a /some/src/a /node_modules/a /src/a " title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs groovy"><code class="sh"><span class="hljs-regexp">/some/</span>folder<span class="hljs-regexp">/structure/</span>node_modules/a <span class="hljs-regexp">/some/</span>folder<span class="hljs-regexp">/structure/</span>src/a <span class="hljs-regexp">/some/</span>folder<span class="hljs-regexp">/node_modules/</span>a <span class="hljs-regexp">/some/</span>folder<span class="hljs-regexp">/src/</span>a <span class="hljs-regexp">/some/</span>node_modules/a <span class="hljs-regexp">/some/</span>src/a <span class="hljs-regexp">/node_modules/</span>a <span class="hljs-regexp">/src/</span>a </code></pre> <p>大部分的情况下使用 <code>root</code> 即可,只有在有很复杂的路径下,才考虑使用 <code>moduledirectories</code>,这可以<a href="https://github.com/webpack/webpack/issues/1574#issuecomment-157520561" rel="nofollow noreferrer" target="_blank">明显提高 webpack 的构建性能</a>。这个 <a href="https://github.com/webpack/webpack/issues/472#issuecomment-55706013" rel="nofollow noreferrer" target="_blank">issue</a> 也很详细地讨论了这个问题。</p> <h2 id="articleHeader5">3. LOADERS</h2> <p>webpack 官方和社区为我们提供了各种各样 loader 来处理各种类型的文件,这些 loader 的配置也直接影响了构建的性能。</p> <h3 id="articleHeader6">3.1 Babel-loader: 能者少劳</h3> <blockquote> <p>build ++, rebuild ++</p> </blockquote> <p>以 <a href="http://www.js-code.com/tag/babel" title="babel" target="_blank">babel</a>-loader 为例,我们在开发 <a href="http://www.js-code.com/tag/react" title="浏览关于“React”的文章" target="_blank" class="tag_link">React</a> 项目时很可能会使用到了 ES6 或者 jsx 的语法,因此使用到 <a href="http://www.js-code.com/tag/babel" title="babel" target="_blank">babel</a>-loader 的情况很多,最简单的情况下我们可以这样配置,让所有的 js/jsx 通过 <a href="http://www.js-code.com/tag/babel" title="浏览关于“babel”的文章" target="_blank" class="tag_link">babel</a>-loader:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="module: { loaders: [ { test: /.js(x)*$/, loader: 'babel-loader', query: { presets: ['react', 'es2015-ie', 'stage-1'] } } ] }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs css"><code><span class="hljs-selector-tag">module</span>: { <span class="hljs-attribute">loaders</span>: [ { test: /.<span class="hljs-built_in">js</span>(x)*$/, loader: <span class="hljs-string">'babel-loader'</span>, query: { p<a href="http://www.js-code.com/tag/reset" title="浏览关于“reset”的文章" target="_blank" class="tag_link">reset</a>s: [<span class="hljs-string">'react'</span>, <span class="hljs-string">'es2015-ie'</span>, <span class="hljs-string">'stage-1'</span>] } } ] }</code></pre> <p>上面这样的做法当然是 ok 的,但是对于很多的 npm 包来说,他们完全没有经过 babel 的必要(成熟的 npm 包会在发布前将自己 <a href="http://www.js-code.com/tag/es5" title="es5" target="_blank">es5</a>,甚至 es3 化),让这些包通过 babel 会带来巨大的性能负担,毕竟 babel6 要经过几十个插件的处理,虽然 babel-loader 强大,但能者多劳的这种保守的想法却使得 babel-loader 成为了整个构建的性能瓶颈。所以我们可以使用 <code>exclude</code>,大胆地屏蔽掉 npm 里的包,从而使整包的构建效率飞速提高。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="module: { loaders: [ { test: /.js(x)*$/, loader: 'babel-loader', exclude: function(path) { // 路径中含有 node_modules 的就不去解析。 var isNpmModule = !!path.match(/node_modules/); return isNpmModule; }, query: { presets: ['react', 'es2015-ie', 'stage-1'] } } ] }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-keyword">module</span>: { loaders: [ { test: <span class="hljs-regexp">/.js(x)*$/</span>, loader: <span class="hljs-string">'babel-loader'</span>, exclude: <span class="hljs-function"><span class="hljs-keyword"><a href="http://www.js-code.com/tag/function" title="浏览关于“function”的文章" target="_blank" class="tag_link">function</a></span>(<span class="hljs-params">path</span>) </span>{ <span class="hljs-comment">// 路径中含有 node_modules 的就不去解析。</span> <span class="hljs-keyword"><a href="http://www.js-code.com/tag/var" title="浏览关于“var”的文章" target="_blank" class="tag_link">var</a></span> isNpmModule = !!path.match(<span class="hljs-regexp">/node_modules/</span>); <span class="hljs-keyword"><a href="http://www.js-code.com/tag/return" title="浏览关于“return”的文章" target="_blank" class="tag_link">return</a></span> isNpmModule; }, query: { presets: [<span class="hljs-string">'react'</span>, <span class="hljs-string">'es2015-ie'</span>, <span class="hljs-string">'stage-1'</span>] } } ] }</code></pre> <p>甚至,在我们十分确信的情况下,使用 <a href="http://www.js-code.com/tag/in" title="in" target="_blank">in</a>clude 来限定 babel 的使用范围,进一步提高效率。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="var path = require('path'); module.exports = { module: { loaders: [ { test: /.js(x)*$/, loader: 'babel-loader', include: [ // 只去解析运行目录下的 src 和 demo 文件夹 path.join(process.cwd(), './src'), path.join(process.cwd(), './demo') ], query: { presets: ['react', 'es2015-ie', 'stage-1'] } } ] } }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-keyword">var</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">'path'</span>); <span class="hljs-built_in">module</span>.<a href="http://www.js-code.com/tag/export" title="浏览关于“export”的文章" target="_blank" class="tag_link">export</a>s = { <span class="hljs-keyword">module</span>: { loaders: [ { test: <span class="hljs-regexp">/.js(x)*$/</span>, loader: <span class="hljs-string">'babel-loader'</span>, <a href="http://www.js-code.com/tag/in" title="浏览关于“in”的文章" target="_blank" class="tag_link">in</a>clude: [ <span class="hljs-comment">// 只去解析运行目录下的 src 和 demo 文件夹</span> path.join(process.cwd(), <span class="hljs-string">'./src'</span>), path.join(process.cwd(), <span class="hljs-string">'./demo'</span>) ], query: { presets: [<span class="hljs-string">'react'</span>, <span class="hljs-string">'es2015-ie'</span>, <span class="hljs-string">'stage-1'</span>] } } ] } }</code></pre> <h2 id="articleHeader7">4. PLUGINS</h2> <p>webpack 官方和社区为我们提供了很多方便的插件,有些插件为我们开发和生产带来了很多的便利,但是不合适地使用插件也会拖慢 webpack 的构建效率,而有些插件虽然不会为我们的开发上直接提供便利,但使用他们却可以帮助我们提高 webpack 的构建效率,这也是本文会提到的。</p> <h3 id="articleHeader8">4.1 Source<a href="http://www.js-code.com/tag/map" title="Map" target="_blank">Map</a>s</h3> <blockquote> <p>build +</p> </blockquote> <p>Source<a href="http://www.js-code.com/tag/map" title="Map" target="_blank">Map</a>s 是一个非常实用的功能,可以让我们在 chrome debug 时可以不用直接看已经 bundle 过的 js,而是直接在源代码上进行查看和调试,但完美的 Source<a href="http://www.js-code.com/tag/map" title="浏览关于“Map”的文章" target="_blank" class="tag_link">Map</a>s 是很慢的,webpack 官方提供了七种 sourceMap 模式共大家选择,性能对比如下:</p> <table> <thead> <tr> <th>devtool</th> <th>build speed</th> <th>rebuild speed</th> <th>production supported</th> <th>quality</th> </tr> </thead> <tbody> <tr> <td><a href="http://www.js-code.com/tag/eval" title="eval" target="_blank">eval</a></td> <td>+++</td> <td>+++</td> <td>no</td> <td>generated code</td> </tr> <tr> <td>cheap-<a href="http://www.js-code.com/tag/eval" title="eval" target="_blank">eval</a>-source-map</td> <td>+</td> <td>++</td> <td>no</td> <td>trans<a href="http://www.js-code.com/tag/for" title="for" target="_blank">for</a>med code (l<a href="http://www.js-code.com/tag/in" title="in" target="_blank">in</a>es only)</td> </tr> <tr> <td>cheap-source-map</td> <td>+</td> <td>o</td> <td>yes</td> <td>trans<a href="http://www.js-code.com/tag/form" title="form" target="_blank">form</a>ed code (lines only)</td> </tr> <tr> <td>cheap-module-<a href="http://www.js-code.com/tag/eval" title="eval" target="_blank">eval</a>-source-map</td> <td>o</td> <td>++</td> <td>no</td> <td>original source (lines only)</td> </tr> <tr> <td>cheap-module-source-map</td> <td>o</td> <td>-</td> <td>yes</td> <td>original source (lines only)</td> </tr> <tr> <td><a href="http://www.js-code.com/tag/eval" title="eval" target="_blank">eval</a>-source-map</td> <td>--</td> <td>+</td> <td>no</td> <td>original source</td> </tr> <tr> <td>source-map</td> <td>--</td> <td>--</td> <td>yes</td> <td>original source</td> </tr> </tbody> </table> <p>具体各自的区别请参考 <a href="https://github.com/webpack/docs/wiki/configuration#devtool" rel="nofollow noreferrer" target="_blank">https://github.com/webpack/do...</a> ,我们这里推荐使用 cheap-source-map,也就是去掉了column mapping 和 loader-sourceMap(例如 jsx to js) 的 sourceMap,虽然带上 <code><a href="http://www.js-code.com/tag/eval" title="浏览关于“eval”的文章" target="_blank" class="tag_link">eval</a></code> 参数的可以快更多,但是这种 sourceMap 只能看,不能调试,得不偿失。</p> <h3 id="articleHeader9">4.2 OPTIMIZATION</h3> <blockquote> <p>build ++,rebuild ++</p> </blockquote> <p>webpack 提供了一些可以优化浏览器端性能的优化插件,如Ugl<a href="http://www.js-code.com/tag/if" title="if" target="_blank">if</a>yJsPlugin,OccurrenceOrderPlugin 和 DedupePlugin,都很实用,也都在消耗构建性能(Ugl<a href="http://www.js-code.com/tag/if" title="if" target="_blank">if</a>yJsPlugin 非常耗性能),如果你是在开发环境下,这些插件最好都不要使用,毕竟脚本大一些,跑的慢一些这些比起每次构建要耗费更多时间来说,显然还是后者更会消磨开发者的耐心,因此,只在正产环境中使用 OPTIMIZATION。</p> <h3 id="articleHeader10">4.3 CommonsChunk</h3> <blockquote> <p>rebuild +</p> </blockquote> <p>当你的 webpack 构建任务中有多个入口文件,而这些文件都 require 了相同的模块,如果你不做任何事情,webpack 会为每个入口文件引入一份相同的模块,显然这样做,会使得相同模块变化时,所有引入的 en<a href="http://www.js-code.com/tag/try" title="try" target="_blank">try</a> 都需要一次 rebuild,造成了性能的浪费,CommonsChunkPlugin 可以将相同的模块提取出来单独打包,进而减小 rebuild 时的性能消耗。这里有一篇很通俗易懂的使用方法:<a href="http://webpack.toobug.net/zh-cn/chapter3/common-chunks-plugin.html" rel="nofollow noreferrer" target="_blank">http://webpack.toobug.net/zh-...</a> ,感兴趣的朋友不妨一试。</p> <h3 id="articleHeader11">4.4 DLL &amp; DllReference</h3> <blockquote> <p>build +++, rebuild +++</p> </blockquote> <p>除了正在开发的源代码之外,通常还会引入很多第三方 NPM 包,这些包我们不会进行修改,但是仍然需要在每次 build 的过程中消耗构建性能,那有没有什么办法可以减少这些消耗呢?DLLPlugin 就是一个解决方案,他通过前置这些依赖包的构建,来提高真正的 build 和 rebuild 的构建效率。<br />鉴于现有的资料对于这两个插件的解释都不是很清楚,笔者这里翻译了一篇<a href="http://qiita.com/pirosikick/items/c77db84dbed4c447a6fe#dll%E3%83%90%E3%83%B3%E3%83%89%E3%83%AB%E3%81%A8%E3%81%AF" rel="nofollow noreferrer" target="_blank">日本同学的文章</a>,通过一个简单的例子来说明一下这两个插件的用法。我们举例,把 react 和 react-<a href="http://www.js-code.com/tag/do" title="do" target="_blank">do</a>m 打包成为 dll bundle。<br />首先,我们来写一个 <a href="https://github.com/webpack/docs/wiki/list-of-plugins#dllplugin" rel="nofollow noreferrer" target="_blank">DLLPlugin</a> 的 config 文件。</p> <blockquote> <p>webpack.dll.config.js</p> </blockquote> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="const path = require('path'); const webpack = require('webpack'); module.exports = { entry: { vendor: ['react', 'react-dom'] }, output: { path: path.join(__dirname, 'dist'), filename: '[name].dll.js', /** * output.library * 将会定义为 window.${output.library} * 在这次的例子中,将会定义为`window.vendor_library` */ library: '[name]_library' }, plugins: [ new webpack.DllPlugin({ /** * path * 定义 manifest 文件生成的位置 * [name]的部分由entry的名字替换 */ path: path.join(__dirname, 'dist', '[name]-manifest.json'), /** * name * dll bundle 输出到那个全局变量上 * 和 output.library 一样即可。 */ name: '[name]_library' }) ] };" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="js"><span class="hljs-keyword"><a href="http://www.js-code.com/tag/const" title="浏览关于“const”的文章" target="_blank" class="tag_link">const</a></span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">'path'</span>); <span class="hljs-keyword">const</span> webpack = <span class="hljs-built_in">require</span>(<span class="hljs-string">'webpack'</span>); <span class="hljs-built_in">module</span>.exports = { <span class="hljs-attr">en<a href="http://www.js-code.com/tag/try" title="浏览关于“try”的文章" target="_blank" class="tag_link">try</a></span>: { <span class="hljs-attr">ven<a href="http://www.js-code.com/tag/do" title="浏览关于“do”的文章" target="_blank" class="tag_link">do</a>r</span>: [<span class="hljs-string">'react'</span>, <span class="hljs-string">'react-dom'</span>] }, <span class="hljs-attr">output</span>: { <span class="hljs-attr">path</span>: path.join(__dir<a href="http://www.js-code.com/tag/name" title="浏览关于“name”的文章" target="_blank" class="tag_link">name</a>, <span class="hljs-string">'dist'</span>), <span class="hljs-attr">filename</span>: <span class="hljs-string">'[name].dll.js'</span>, <span class="hljs-comment">/** * output.library * 将会定义为 <a href="http://www.js-code.com/tag/window" title="浏览关于“window”的文章" target="_blank" class="tag_link">window</a>.${output.library} * 在这次的例子中,将会定义为`window.vendor_library` */</span> library: <span class="hljs-string">'[name]_library'</span> }, <span class="hljs-attr"><a href="http://www.js-code.com/tag/plugin" title="浏览关于“plugin”的文章" target="_blank" class="tag_link">plugin</a>s</span>: [ <span class="hljs-keyword"><a href="http://www.js-code.com/tag/new" title="浏览关于“new”的文章" target="_blank" class="tag_link">new</a></span> webpack.DllPlugin({ <span class="hljs-comment">/** * path * 定义 man<a href="http://www.js-code.com/tag/if" title="浏览关于“if”的文章" target="_blank" class="tag_link">if</a>est 文件生成的位置 * [name]的部分由entry的名字替换 */</span> path: path.join(__dirname, <span class="hljs-string">'dist'</span>, <span class="hljs-string">'[name]-manifest.json'</span>), <span class="hljs-comment">/** * name * dll bundle 输出到那个全局变量上 * 和 output.library 一样即可。 */</span> name: <span class="hljs-string">'[name]_library'</span> }) ] };</code></pre> <p>执行 webpack 后,就会在 dist 目录下生成 dll bundle 和对应的 manifest 文件</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="$ ./node_modules/.bin/webpack --config webpack.dll.config.js Hash: 36187493b1d9a06b228d Version: webpack 1.13.1 Time: 860ms Asset Size Chunks Chunk Names vendor.dll.js 699 kB 0 [emitted] vendor [0] dll vendor 12 bytes {0} [built] + 167 hidden modules $ ls dist ./ vendor-manifest.json ../ vendor.dll.js" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs groovy"><code class="sh">$ .<span class="hljs-regexp">/node_modules/</span>.bin/webpack --config webpack.dll.config.js <span class="hljs-string">Hash:</span> <span class="hljs-number">36187493</span>b1d9a06b228d <span class="hljs-string">Version:</span> webpack <span class="hljs-number">1.13</span><span class="hljs-number">.1</span> <span class="hljs-string">Time:</span> <span class="hljs-number">860</span>ms Asset Size Chunks Chunk Names vendor.dll.js <span class="hljs-number">699</span> kB <span class="hljs-number">0</span> [emitted] vendor [<span class="hljs-number">0</span>] dll vendor <span class="hljs-number">12</span> <a href="http://www.js-code.com/tag/byte" title="浏览关于“byte”的文章" target="_blank" class="tag_link">byte</a>s {<span class="hljs-number">0</span>} [built] + <span class="hljs-number">167</span> <a href="http://www.js-code.com/tag/hidden" title="浏览关于“hidden”的文章" target="_blank" class="tag_link">hidden</a> modules $ ls dist ./ vendor-manifest.json ../ vendor.dll.js</code></pre> <p>manifest 文件的格式大致如下,由包含的 module 和对应的 id 的键值对构成。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="cat dist/vendor-manifest.json { &quot;name&quot;: &quot;vendor_library&quot;, &quot;content&quot;: { &quot;./node_modules/react/react.js&quot;: 1, &quot;./node_modules/react/lib/React.js&quot;: 2, &quot;./node_modules/process/browser.js&quot;: 3, &quot;./node_modules/object-assign/index.js&quot;: 4, &quot;./node_modules/react/lib/ReactChildren.js&quot;: 5, &quot;./node_modules/react/lib/PooledClass.js&quot;: 6, &quot;./node_modules/fbjs/lib/invariant.js&quot;: 7, ..." title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs r"><code class="sh">cat dist/vendor-manifest.json { <span class="hljs-string">"name"</span>: <span class="hljs-string">"vendor_library"</span>, <span class="hljs-string">"content"</span>: { <span class="hljs-string">"./node_modules/react/react.js"</span>: <span class="hljs-number">1</span>, <span class="hljs-string">"./node_modules/react/lib/React.js"</span>: <span class="hljs-number">2</span>, <span class="hljs-string">"./node_modules/process/browser.js"</span>: <span class="hljs-number">3</span>, <span class="hljs-string">"./node_modules/object-<a href="http://www.js-code.com/tag/assign" title="浏览关于“assign”的文章" target="_blank" class="tag_link">assign</a>/index.js"</span>: <span class="hljs-number">4</span>, <span class="hljs-string">"./node_modules/react/lib/ReactChildren.js"</span>: <span class="hljs-number">5</span>, <span class="hljs-string">"./node_modules/react/lib/Pooled<a href="http://www.js-code.com/tag/class" title="浏览关于“Class”的文章" target="_blank" class="tag_link">Class</a>.js"</span>: <span class="hljs-number">6</span>, <span class="hljs-string">"./node_modules/fbjs/lib/invariant.js"</span>: <span class="hljs-number">7</span>, <span class="hljs-keyword">...</span></code></pre> <p>好,接下来我们通过 <a href="https://github.com/webpack/docs/wiki/list-of-plugins#dllreferenceplugin" rel="nofollow noreferrer" target="_blank">DLLReferencePlugin</a> 来使用刚才生成的 DLL Bundle。</p> <p>首先我们写一个只去 <code>require</code> react,并通过 <code>console.log</code> 吐出的 <code>index.js</code>。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="var React = require('react'); var ReactDOM = require('react-dom'); console.log(&quot;dll's React:&quot;, React); console.log(&quot;dll's ReactDOM:&quot;, ReactDOM);" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="js"><span class="hljs-keyword">var</span> React = <span class="hljs-built_in">require</span>(<span class="hljs-string">'react'</span>); <span class="hljs-keyword">var</span> React<a href="http://www.js-code.com/tag/dom" title="浏览关于“DOM”的文章" target="_blank" class="tag_link">DOM</a> = <span class="hljs-built_in">require</span>(<span class="hljs-string">'react-dom'</span>); <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"dll's React:"</span>, React); <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"dll's ReactDOM:"</span>, ReactDOM);</code></pre> <p>再写一个不参考 Dll Bundle 的普通 webpack config 文件。</p> <blockquote> <p>webpack.conf.js</p> </blockquote> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="const path = require('path'); const webpack = require('webpack'); module.exports = { entry: { 'dll-user': ['./index.js'] }, output: { path: path.join(__dirname, 'dist'), filename: '[name].bundle.js' } };" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="js"><span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">'path'</span>); <span class="hljs-keyword">const</span> webpack = <span class="hljs-built_in">require</span>(<span class="hljs-string">'webpack'</span>); <span class="hljs-built_in">module</span>.exports = { <span class="hljs-attr">entry</span>: { <span class="hljs-string">'dll-user'</span>: [<span class="hljs-string">'./index.js'</span>] }, <span class="hljs-attr">output</span>: { <span class="hljs-attr">path</span>: path.join(__dirname, <span class="hljs-string">'dist'</span>), <span class="hljs-attr">filename</span>: <span class="hljs-string">'[name].bundle.js'</span> } };</code></pre> <p>执行 webpack,会在 dist 下生成 dll-user.bundle.js,约 700K,耗时 801ms。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="$ ./node_modules/.bin/webpack Hash: d8cab39e58c13b9713a6 Version: webpack 1.13.1 Time: 801ms Asset Size Chunks Chunk Names dll-user.bundle.js 700 kB 0 [emitted] dll-user [0] multi dll-user 28 bytes {0} [built] [1] ./index.js 145 bytes {0} [built] + 167 hidden modules" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs groovy"><code class="sh">$ .<span class="hljs-regexp">/node_modules/</span>.bin/webpack <span class="hljs-string">Hash:</span> d8cab39e58c13b9713a6 <span class="hljs-string">Version:</span> webpack <span class="hljs-number">1.13</span><span class="hljs-number">.1</span> <span class="hljs-string">Time:</span> <span class="hljs-number">801</span>ms Asset Size Chunks Chunk Names dll-user.bundle.js <span class="hljs-number">700</span> kB <span class="hljs-number">0</span> [emitted] dll-user [<span class="hljs-number">0</span>] multi dll-user <span class="hljs-number">28</span> bytes {<span class="hljs-number">0</span>} [built] [<span class="hljs-number">1</span>] ./index.js <span class="hljs-number">145</span> bytes {<span class="hljs-number">0</span>} [built] + <span class="hljs-number">167</span> hidden modules</code></pre> <p>接下来,我们加入 <a href="https://github.com/webpack/docs/wiki/list-of-plugins#dllreferenceplugin" rel="nofollow noreferrer" target="_blank">DLLReferencePlugin</a></p> <blockquote> <p>webpack.conf.js</p> </blockquote> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="const path = require('path'); const webpack = require('webpack'); module.exports = { entry: { 'dll-user': ['./index.js'] }, output: { path: path.join(__dirname, 'dist'), filename: '[name].bundle.js' }, // ----在这里追加---- plugins: [ new webpack.DllReferencePlugin({ context: __dirname, /** * 在这里引入 manifest 文件 */ manifest: require('./dist/vendor-manifest.json') }) ] // ----在这里追加---- };" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="js"><span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">'path'</span>); <span class="hljs-keyword">const</span> webpack = <span class="hljs-built_in">require</span>(<span class="hljs-string">'webpack'</span>); <span class="hljs-built_in">module</span>.exports = { <span class="hljs-attr">entry</span>: { <span class="hljs-string">'dll-user'</span>: [<span class="hljs-string">'./index.js'</span>] }, <span class="hljs-attr">output</span>: { <span class="hljs-attr">path</span>: path.join(__dirname, <span class="hljs-string">'dist'</span>), <span class="hljs-attr">filename</span>: <span class="hljs-string">'[name].bundle.js'</span> }, <span class="hljs-comment">// ----在这里追加----</span> plugins: [ <span class="hljs-keyword">new</span> webpack.DllReferencePlugin({ <span class="hljs-attr">con<a href="http://www.js-code.com/tag/text" title="浏览关于“text”的文章" target="_blank" class="tag_link">text</a></span>: __dirname, <span class="hljs-comment">/** * 在这里引入 manifest 文件 */</span> manifest: <span class="hljs-built_in">require</span>(<span class="hljs-string">'./dist/vendor-manifest.json'</span>) }) ] <span class="hljs-comment">// ----在这里追加----</span> };</code></pre> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="./node_modules/.bin/webpack Hash: 3bc7bf760779b4ca8523 Version: webpack 1.13.1 Time: 70ms Asset Size Chunks Chunk Names dll-user.bundle.js 2.01 kB 0 [emitted] dll-user [0] multi dll-user 28 bytes {0} [built] [1] ./index.js 145 bytes {0} [built] + 3 hidden modules" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs groovy"><code class="sh">.<span class="hljs-regexp">/node_modules/</span>.bin/webpack <span class="hljs-string">Hash:</span> <span class="hljs-number">3</span>bc7bf760779b4ca8523 <span class="hljs-string">Version:</span> webpack <span class="hljs-number">1.13</span><span class="hljs-number">.1</span> <span class="hljs-string">Time:</span> <span class="hljs-number">70</span>ms Asset Size Chunks Chunk Names dll-user.bundle.js <span class="hljs-number">2.01</span> kB <span class="hljs-number">0</span> [emitted] dll-user [<span class="hljs-number">0</span>] multi dll-user <span class="hljs-number">28</span> bytes {<span class="hljs-number">0</span>} [built] [<span class="hljs-number">1</span>] ./index.js <span class="hljs-number">145</span> bytes {<span class="hljs-number">0</span>} [built] + <span class="hljs-number">3</span> hidden modules</code></pre> <p>结果是非常惊人的,只有2.01K,耗时 70 ms,无疑大大提高了 build 和 rebuild 的效率。实际放到页面上看下是否可行。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="<a href="http://www.js-code.com/tag/button" title="button" target="_blank">button</a>" <a href="http://www.js-code.com/tag/class" title="class" target="_blank">class</a>="copyCode code-tool" data-toggle="tooltip" data-placement="<a href="http://www.js-code.com/tag/top" title="top" target="_blank">top</a>" data-clipboard-<a href="http://www.js-code.com/tag/text" title="text" target="_blank">text</a>="<body><br /> <script src=&quot;dist/vendor.dll.js&quot;></script><br /> <script src=&quot;dist/dll-user.bundle.js&quot;></script><br /> </body>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="xml hljs"><code class="html"><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"dist/vendor.dll.js"</span>&gt;</span><span class="undefined"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"dist/dll-user.bundle.js"</span>&gt;</span><span class="undefined"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span></code></pre> <p><span class="img-wrap"><img data-src="/img/remote/1460000005770049" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="" title="" style="cursor: pointer;"></span></p> <p>因为 Dll bundle 在依赖安装完毕后就可以进行了,我们可以在第一次执行 dev server 前执行一次 dll bundle 的 webapck 任务。</p> <h4>4.4.1 和 external 的比较</h4> <p>有人会说,这个和 用 <code>webpack</code> 的 <code>externals</code> 配置把 require 的 module 指向全局变量有点像啊。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="const path = require('path'); const webpack = require('webpack'); module.exports = { entry: { 'ex': ['./index.js'] }, output: { path: path.join(__dirname, 'dist'), filename: '[name].bundle.js' }, externals: { // require('react')はwindow.Reactを使う 'react': 'React', // require('react-dom')はwindow.ReactDOMを使う 'react-dom': 'ReactDOM' } };" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="js"><span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">'path'</span>); <span class="hljs-keyword">const</span> webpack = <span class="hljs-built_in">require</span>(<span class="hljs-string">'webpack'</span>); <span class="hljs-built_in">module</span>.exports = { <span class="hljs-attr">entry</span>: { <span class="hljs-string">'ex'</span>: [<span class="hljs-string">'./index.js'</span>] }, <span class="hljs-attr">output</span>: { <span class="hljs-attr">path</span>: path.join(__dirname, <span class="hljs-string">'dist'</span>), <span class="hljs-attr">filename</span>: <span class="hljs-string">'[name].bundle.js'</span> }, <span class="hljs-attr">externals</span>: { <span class="hljs-comment">// require('react')はwindow.Reactを使う</span> <span class="hljs-string">'react'</span>: <span class="hljs-string">'React'</span>, <span class="hljs-comment">// require('react-dom')はwindow.ReactDOMを使う</span> <span class="hljs-string">'react-dom'</span>: <span class="hljs-string">'ReactDOM'</span> } };</code></pre> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="<a href="http://www.js-code.com/tag/button" title="button" target="_blank">button</a>" <a href="http://www.js-code.com/tag/class" title="class" target="_blank">class</a>="copyCode code-tool" data-toggle="tooltip" data-placement="<a href="http://www.js-code.com/tag/top" title="top" target="_blank">top</a>" data-clipboard-<a href="http://www.js-code.com/tag/text" title="text" target="_blank">text</a>="<body><br /> <script src=&quot;dist/react.min.js&quot;></script><br /> <script src=&quot;dist/react-dom.min.js&quot;></script><br /> <script src=&quot;dist/ex.bundle.js&quot;></script><br /> </body>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="xml hljs"><code class="html"><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"dist/react.min.js"</span>&gt;</span><span class="undefined"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"dist/react-dom.min.js"</span>&gt;</span><span class="undefined"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"dist/ex.bundle.js"</span>&gt;</span><span class="undefined"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span></code></pre> <p>这里有两个主要的区别:</p> <ol> <li> <p>像是 <code>react</code> 这种已经打好了生产包的使用 <code>externals</code> 很方便,但是也有很多 npm 包是没有提供的,这种情况下 <code>DLLBundle</code> 仍可以使用。</p> </li> <li> <p>如果只是引入 npm 包一部分的功能,比如 <code>require('react/lib/React')</code> 或者 <code>require('lodash/fp/extend')</code> ,这种情况下 <code>DLLBundle</code> 仍可以使用。</p> </li> <li> <p>当然如果只是引用了 <code>react</code> 这类的话,<code>externals</code> 因为配置简单所以也推荐使用。</p> </li> </ol> <h3 id="articleHeader12">4.5 <a href="https://github.com/amireh/happypack" rel="nofollow noreferrer" target="_blank">HappyPack</a><br /> </h3> <blockquote> <p>build +, rebuild +</p> </blockquote> <p>webpack 的长时间构建搞的大家都很 unhappy。于是 @amireh 想到了一个点子,既然 loader 默认都是一个进程在跑,那是否可以让 loader 多进程去处理文件呢?</p> <p><span class="img-wrap"><img data-src="/img/remote/1460000005770054" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="" title="" style="cursor: pointer;"></span></p> <p>happyPack 的文档写的很易懂,这里就不再赘述,happyPack 不仅利用了多进程,同时还利用缓存来使得 rebuild 更快。下面是插件作者给出的性能数据:</p> <blockquote> <p>For the main repository I tested on, which had around 3067 modules, the build time went <a href="http://www.js-code.com/tag/do" title="do" target="_blank">do</a>wn from 39 seconds to a whopping ~10 seconds when there was yet no</p> </blockquote> <ol> <li> <p>Successive builds now take between 6 and 7 seconds.</p> </li> </ol> <blockquote> <p>Here's a rundown of the <a href="http://www.js-code.com/tag/var" title="var" target="_blank">var</a>ious states the build was per<a href="http://www.js-code.com/tag/for" title="for" target="_blank">for</a>med in:</p> </blockquote> <table> <thead> <tr> <th>Elapsed (ms)</th> <th>Happy?</th> <th>Cache enabled?</th> <th>Cache present?</th> <th colspan="2">Using DLLs?</th> </tr> </thead> <tbody> <tr> <td>39851</td> <td>NO</td> <td>N/A</td> <td>N/A</td> <td colspan="2">NO</td> </tr> <tr> <td>37393</td> <td>NO</td> <td>N/A</td> <td>N/A</td> <td colspan="2">YES</td> </tr> <tr> <td>14605</td> <td>YES</td> <td>NO</td> <td>N/A</td> <td colspan="2">NO</td> </tr> <tr> <td>13925</td> <td>YES</td> <td>YES</td> <td>NO</td> <td colspan="2">NO</td> </tr> <tr> <td>11877</td> <td>YES</td> <td>YES</td> <td>YES</td> <td colspan="2">NO</td> </tr> <tr> <td>9228</td> <td>YES</td> <td>NO</td> <td>N/A</td> <td colspan="2">YES</td> </tr> <tr> <td>9597</td> <td>YES</td> <td>YES</td> <td>NO</td> <td colspan="2">YES</td> </tr> <tr> <td>6975</td> <td>YES</td> <td>YES</td> <td>YES</td> <td colspan="2">YES</td> </tr> </tbody> </table> <blockquote> <p>The builds above were run on Linux over a machine with 12 cores.</p> </blockquote> <h2 id="articleHeader13">5. 其他</h2> <p>上面我们针对 webpack 的 resolve、loader 和 <a href="http://www.js-code.com/tag/plugin" title="plugin" target="_blank">plugin</a> 的过程给出了相应的优化意见,除了这些哪些优化点呢?其实有些优化贯穿在这个流程中,比如缓存和文件 IO。</p> <h3 id="articleHeader14">5.1 Cache</h3> <p>无论在何种性能优化中,缓存总是必不可少的一部分,毕竟每次变动都只影响很小的一部分,如果能够缓存住那些没有变动的部分,直接拿来使用,自然会事半功倍,在 webpack 的整个构建过程中,有多个地方提供了缓存的机会,如果我们打开了这些缓存,会大大加速我们的构建,尤其是 rebuild 的效率。</p> <h4>5.1.1 <a href="http://webpack.github.io/docs/configuration.html#cache" rel="nofollow noreferrer" target="_blank">webpack.cache</a><br /> </h4> <blockquote> <p>rebuild +</p> </blockquote> <p>webpack 自身就有 cache 的配置,并且在 watch 模式下自动开启,虽然效果不是最明显的,但却对所有的 module 都有效。</p> <h4>5.1.2 <a href="https://github.com/babel/babel-loader#options" rel="nofollow noreferrer" target="_blank">babel-loader.cacheDirectory</a><br /> </h4> <blockquote> <p>rebuild ++</p> </blockquote> <p>babel-loader 可以利用系统的临时文件夹缓存经过 babel 处理好的模块,对于 rebuild js 有着非常大的性能提升。</p> <h4>5.1.3 <a href="https://github.com/amireh/happypack#cache-boolean" rel="nofollow noreferrer" target="_blank">HappyPack.cache</a><br /> </h4> <blockquote> <p>build +, rebuild +</p> </blockquote> <p>上面提到的 happyPack 插件也同样提供了 cache 功能,默认是以 <code>.happypack/cache--[id].json</code> 的路径进行缓存。因为是缓存在当前目录下,所以他也可以辅助下次 build 时的效率。</p> <h3 id="articleHeader15">5.2 FileSystem</h3> <p>默认的情况下,构建好的目录一定要输出到某个目录下面才能使用,但 webpack 提供了一种很棒的读写机制,使得我们可以直接在内存中进行读写,从而极大地提高 IO 的效率,开启的方法也很简单。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="var MemoryFS = require(&quot;memory-fs&quot;); var webpack = require(&quot;webpack&quot;); var fs = new MemoryFS(); var compiler = webpack({ ... }); compiler.outputFileSystem = fs; compiler.run(function(err, stats) { // ... var fileContent = fs.readFileSync(&quot;...&quot;); });" title="" data-original-title="复制"></span> </div> </p></div> <pre class="javascript hljs"><code class="js"><span class="hljs-keyword">var</span> MemoryFS = <span class="hljs-built_in">require</span>(<span class="hljs-string">"memory-fs"</span>); <span class="hljs-keyword">var</span> webpack = <span class="hljs-built_in">require</span>(<span class="hljs-string">"webpack"</span>); <span class="hljs-keyword">var</span> fs = <span class="hljs-keyword">new</span> MemoryFS(); <span class="hljs-keyword">var</span> compiler = webpack({ ... }); compiler.outputFileSystem = fs; compiler.run(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err, stats</span>) </span>{ <span class="hljs-comment">// ...</span> <span class="hljs-keyword">var</span> fileContent = fs.readFileSync(<span class="hljs-string">"..."</span>); });</code></pre> <p>当然,我们还可以通过 webpackDevMiddleware 更加无缝地就接入到 dev server 中,例如我们以 express 作为静态 server 的例子。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="var compiler = webpack(webpackCfg); var webpackDevMiddlewareInstance = webpackDevMiddleware(compiler, { // webpackDevMiddleware 默认使用了 memory-fs publicPath: '/dist', aggregateTimeout: 300, // wait so long for more changes poll: true, // use polling instead of native watchers stats: { chunks: false } }); var app = express(); app.use(webpackDevMiddlewareInstance); app.listen(xxxx, function(err) { console.log(colors.info(&quot;dev server start: listening at &quot; + xxxx)); if (err) { console.error(err); } }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs javascript"><code><span class="hljs-keyword">var</span> compiler = webpack(webpackCfg); <span class="hljs-keyword">var</span> webpackDevMiddlewareInstance = webpackDevMiddleware(compiler, { <span class="hljs-comment">// webpackDevMiddleware 默认使用了 memory-fs</span> <a href="http://www.js-code.com/tag/public" title="浏览关于“public”的文章" target="_blank" class="tag_link">public</a>Path: <span class="hljs-string">'/dist'</span>, <span class="hljs-attr">aggregateTimeout</span>: <span class="hljs-number">300</span>, <span class="hljs-comment">// wait so <a href="http://www.js-code.com/tag/long" title="浏览关于“long”的文章" target="_blank" class="tag_link">long</a> <a href="http://www.js-code.com/tag/for" title="浏览关于“for”的文章" target="_blank" class="tag_link">for</a> more changes</span> poll: <span class="hljs-literal"><a href="http://www.js-code.com/tag/true" title="浏览关于“true”的文章" target="_blank" class="tag_link">true</a></span>, <span class="hljs-comment">// use polling instead of native watchers</span> stats: { <span class="hljs-attr">chunks</span>: <span class="hljs-literal"><a href="http://www.js-code.com/tag/false" title="浏览关于“false”的文章" target="_blank" class="tag_link">false</a></span> } }); <span class="hljs-keyword">var</span> app = express(); app.use(webpackDevMiddlewareInstance); app.listen(xxxx, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err</span>) </span>{ <span class="hljs-built_in">console</span>.log(colors.info(<span class="hljs-string">"dev server start: listening at "</span> + xxxx)); <span class="hljs-keyword">if</span> (err) { <span class="hljs-built_in">console</span>.error(err); } }</code></pre> <h2 id="articleHeader16">6. 总结</h2> <p>上面我们从 webpack 构建的各个部分,给出了相应的优化策略,如果你的项目中能够将其完全贯彻起来,10 倍提速不是梦想。这些优化也同样应用到了我们团队的 react 项目中,<a href="https://github.com/uxcore/uxcore" rel="nofollow noreferrer" target="_blank">https://github.com/uxcore/uxcore</a> ,欢迎一起来讨论 webpack 的效率优化方案。</p> <h2 id="articleHeader17">7. 参考文章</h2> <ul> <li> <p>webpack build per<a href="http://www.js-code.com/tag/form" title="form" target="_blank">form</a>ance:<a href="http://webpack.github.io/docs/build-performance.html" rel="nofollow noreferrer" target="_blank">http://webpack.github.io/docs...</a></p> </li> <li> <p>webpackのDLLバンドルを使ってビルドを速くする:<a href="http://qiita.com/pirosikick/items/c77db84dbed4c447a6fe#%E3%81%8A%E3%81%BE%E3%81%91cachedirectory" rel="nofollow noreferrer" target="_blank">http://qiita.com/pirosikick/i...</a></p> </li> <li> <p>How to make your Webpack builds 10x faster:<a href="http://www.slideshare.net/trueter/how-to-make-your-webpack-builds-10x-faster" rel="nofollow noreferrer" target="_blank">http://www.slideshare.net/tru...</a></p> </li> </ul> <blockquote> <p>本文作者 <a href="https://github.com/eternalsky" rel="nofollow noreferrer" target="_blank">eternalsky</a>,始发于团队微信公众号 <strong>猿猿相抱</strong> 和个人博客 <a href="http://eternalsky.me/" rel="nofollow noreferrer" target="_blank"><strong>空の屋敷</strong></a>,转载请保留作者信息。</p> </blockquote> <p></code></p>

总结

以上是脚本宝典为你收集整理的

开发工具心得:如何 10 倍提高你的 Webpack 构建效率

全部内容,希望文章能够帮你解决

开发工具心得:如何 10 倍提高你的 Webpack 构建效率

所遇到的程序开发问题,欢迎加入QQ群277859234一起讨论学习。如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典网站推荐给程序员好友。 本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。

80%的人都看过