前言

Webpack 是 OneAPM 前端技术栈中非常重要的一部分。它非常好用,假设你还不了解它,建议你阅读这篇Webpack 入门指迷,在 OneAPM 我们用它完毕静态资源打包。ES6 代码的转换 ,React 组件的组织等,在接下来的日子里,我们将通过一系列文章和业界分享我们在使用 Webpack 过程中关于性能方面的经验。

作为系列文章的第一篇。我们会重点介绍 Webpack 中的 resolve.alias ,也就是请求重定向。

只是请注意 Webpack 里的请求是对模块的依赖,也就是一个 require语句,而不是一个 HTTP 请求。

必要的准备

  • 须要你有一定的 Node.js 基础
  • 电脑上装有最新版的 Webpack (npm install webpack -g)
  • 了解 Webpack 配置文件的格式

样例:本地时钟

要实现的功能非常easy。就是在页面上用中文显示当前时间,须要用到 moment 这个库,这个库封装了非常多和日期相关的函数,并且自带了国际化的支持。

新建一个 Node.js 项目

使用 npm init 初始化你的项目,然后通过npm install moment -D加上 moment 的开发人员依赖。

新建一个entry.js作为入口文件,当然你也能够用 app.js 这种名字,仅仅是大部分的 Webpack 演示样例都是用的是 entry.js

var moment = require('moment');
document.write(moment().locale('zh-cn').format('LLLL'));

新建一个页面index.html, 引用 bundle.js:

<body>
<h5>当前时间:</h5>
<script src="dist/bundle.js"></script>
</body>

此时的文件文件夹看起来是这种:

index.html
package.json
entry.js
node_modules/moment

到眼下为止 bundle.js 这个文件还不存在,只是别着急,接下来的工作就交给 Webpack 来完毕。

index.html  ------------------------+
package.json |
+--> <Clock App>
entry.js --------+ |
+-->bundle.js+--+
node_modules/moment-+

如图,Webpack 会把 entry.jsmoment模块一起打包成一个 bundle.js 文件,和 index.html 一起构成了我们的 Clock App。怎么样,是不是已经听到 Clock App 滴答作响了?

使用 webpack 打包代码

在命令行执行:

webpack --entry ./entry.js --output-path dist --output-file bundle.js

你会看到相似以下的输出结果:

Hash: bf9007fb1e0cb30e3ef7
Version: webpack 1.10.0
Time: 650ms
Asset Size Chunks Chunk Names
bundle.js 378 kB 0 [emitted] null
[0] ./entry.js 125 bytes {0} [built]
+ 86 hidden modules

能够看到,耗时 650ms,这么慢着实让人意外,一定要想办法提高“新一代神器”速度;还有一方面,最后一行的 + 86 hidden modules 非常让人怀疑:明明是一个简单的 Clock App,怎么会有这么多的依赖。

怎样高速定位 Webpack 速度慢的原因

再一次。在命令行输入:

webpack --entry ./entry.js --output-path dist --output-file bundle.js \
--colors \
--profile \
--display-modules

只是这次新添加了三个參数,这三个參数的含义各自是:

  • --colors 输出结果带彩色,比方:会用红色显示耗时较长的步骤
  • --profile输出性能数据,能够看到每一步的耗时
  • --display-modules默认情况下 node_modules 下的模块会被隐藏,加上这个參数能够显示这些被隐藏的模块

    这次命令行的结果已经非常有參考价值,能够帮助我们定位耗时比較长的步骤
Hash: bf9007fb1e0cb30e3ef7
Version: webpack 1.10.0
Time: 650ms
Asset Size Chunks Chunk Names
bundle.js 378 kB 0 [emitted] null
[0] ./entry.js 125 bytes {0} [built]
factory:11ms building:8ms = 19ms
[1] ../~/moment/moment.js 102 kB {0} [built]
[0] 19ms -> factory:7ms building:141ms = 167ms
[2] (webpack)/buildin/module.js 251 bytes {0} [built]
[0] 19ms -> [1] 148ms -> factory:132ms building:159ms = 458ms
[3] ../~/moment/locale ^\.\/.*$ 2.01 kB {0} [optional] [built]
[0] 19ms -> [1] 148ms -> factory:6ms building:10ms dependencies:113ms = 296ms
[4] ../~/moment/locale/af.js 2.57 kB {0} [optional] [built]
[0] 19ms -> [1] 148ms -> [3] 16ms -> factory:52ms building:65ms dependencies:138ms = 438ms
..... 广告切割线,Node.js project师简历请发 nodejs@oneapm.com ......
[85] ../~/moment/locale/zh-cn.js 4.31 kB {0} [optional] [built]
[0] 22ms -> [1] 162ms -> [3] 18ms -> factory:125ms building:145ms dependencies:22ms = 494ms
[86] ../~/moment/locale/zh-tw.js 3.07 kB {0} [optional] [built]
[0] 22ms -> [1] 162ms -> [3] 18ms -> factory:126ms building:146ms dependencies:21ms = 495ms

从命令行的结果里能够看到从 Request[4] 到 Request[86] 都是在解析 moment.js附带的大量本地化文件。所以我们遇到的速度慢的问题事实上是由 moment引起的。

假设你想知道为什么 Webpack 会载入这么多的模块。能够參考这篇文章 Why Enormous Locales During Webpack MomentJS

我们再来看看 entry.js代码的第一行,标准的 CommonJS写法:

var moment = require('moment');

也就是说。请求的是 moment的源代码。实际上。通过 NPM 安装moment 的时候会同一时候安装 moment 的源代码和压缩后的代码,试验证明以下这种写法也是可行的:

var moment = require('moment/min/moment-with-locales.min.js');

仅仅只是这样改,可读性会有所下降,并且每个用到moment 的地方都得这么写。另外,假设相同的问题出如今第三方模块中,改动别人代码就不那么方便了。

以下来看看用 Webpack 怎么解决问题。

在 Webpack 中使用别名

别名(resolve.alias) 是 Webpack 的一个配置项,它的作用是把用户的一个请求重定向到还有一个路径,比如通过改动 webpack.config.js配置文件,添加:

  resolve: {
alias: {
moment: "moment/min/moment-with-locales.min.js"
}
}

这样待打包的脚本中的 require('moment'); 事实上就等价于 require('moment/min/moment-with-locales.min.js'); 。通过别名的使用在本例中能够降低差点儿一半的时间。

Hash: cdea65709b783ee0741a
Version: webpack 1.10.0
Time: 320ms
Asset Size Chunks Chunk Names
bundle.js 148 kB 0 [emitted] main
[0] ./entry.js 125 bytes {0} [built]
factory:11ms building:9ms = 20ms
[1] ../~/moment/min/moment-with-locales.min.js 146 kB {0} [built] [1 warning]
[0] 20ms -> factory:8ms building:263ms = 291ms
[2] (webpack)/buildin/module.js 251 bytes {0} [built]
[0] 20ms -> [1] 271ms -> factory:3ms building:1ms = 295ms WARNING in ../~/moment/min/moment-with-locales.min.js
Module not found: Error: Cannot resolve 'file' or 'directory' ./locale in */webpack_performance/node_modules/moment/min
@ ../~/moment/min/moment-with-locales.min.js 1:2731-2753

Webpack中忽略对已知文件的解析

module.noParsewebpack 的还有一个非常实用的配置项,假设你 确定一个模块中没有其他新的依赖 就能够配置这项,webpack 将不再扫描这个文件里的依赖。

  module: {
noParse: [/moment-with-locales/]
}

这样改动。再结合前面重命名的样例,更新后的流程是:

  • webpack 检查到 entry.js 文件对 moment的请求;
  • 请求被 alias 重定向,转而请求 moment/min/moment-with-locales.min.js;
  • noParse 规则中的 /moment-with-locales/一条生效,所以 webpack 就直接把依赖打包进了 bundle.js

Hash: 907880ed7638b4ed70b9
Version: webpack 1.10.0
Time: 76ms
Asset Size Chunks Chunk Names
bundle.js 147 kB 0 [emitted] main
[0] ./entry.js 125 bytes {0} [built]
factory:13ms building:13ms = 26ms
[1] ../~/moment/min/moment-with-locales.min.js 146 kB {0} [built]
[0] 26ms -> factory:13ms building:5ms = 44ms

时间进一步被压缩,仅仅须要 76ms,比前一步还降低了 75%。

在 Webpack 中使用公用 CDN

Webpack 是如此的强大。用其打包的脚本能够执行在多种环境下。Web 环境仅仅是其默认的一种,也是最经常使用的一种。考虑到 Web 上有非常多的公用 CDN 服务。那么 怎么将 Webpack 和公用的 CDN 结合使用呢?方法是使用 externals声明一个外部依赖。

  externals: {
moment: true
}

当然了 HTML 代码里须要加上一行

<script src="//apps.bdimg.com/libs/moment/2.8.3/moment-with-locales.min.js"></script>

这次打包。结果仅仅用了 49 ms。差点儿达到了极限。

总结

本文结合本地时钟的样例,展示了定位 Webpack 性能问题的步骤,以及所须要的两个參数 :--display-modules--profile。然后,重点介绍了 resolve.alias 即利用别名做重定向的方法和场景。在此基础上,配合module.noParse 忽略某些模块的解析能够进一步加高速度。最后介绍了用 externals 定义外部依赖方法来使用公用 CDN。

关于

本文相关的源代码在: https://github.com/wyvernnot/webpack_performance/tree/master/moment-example;


本文系

utm_source=Common&utm_medium=Articles&utm_campaign=TechnicalArticles&from=matefiseco">OneAPMproject师原创文章。

OneAPM是中国基础软件领域的新兴领军企业,能帮助企业用户和开发人员轻松实现:缓慢的程序代码和SQL语句的实时抓取。想阅读很多其他技术文章。请訪问OneAPM官方技术博客

Webpack 性能优化 (一)(使用别名做重定向)的更多相关文章

  1. webpack性能优化-实战

    题外话:年初项目重构上线,项目技术栈使用vue+webpack,测试执行整个打包流程需要10分钟,同时又因涉及三个渠道,部署好环境就需半个小时,这严重延误了上线进度,因此提高webpack构建效率,成 ...

  2. webpack 性能优化 dll 分包

    webpack 性能优化 dll 分包 html-webpack-externals-plugin DLLPlugin https://www.webpackjs.com/configuration/ ...

  3. webpack性能优化——DLL

    Webpack性能优化的方式有很多种,本文之所以将 dll 单独讲解,是因为 dll 是一种最简单粗暴并且极其有效的优化方式. 在通常的打包过程中,你所引用的诸如:jquery.bootstrap.r ...

  4. webpack 性能优化小结

    背景 如今前端工程化的概念早已经深入人心,选择一款合适的编译和资源管理工具已经成为了所有前端工程中的标配,而在诸多的构建工具中,webpack以其丰富的功能和灵活的配置而深受业内吹捧,逐步取代了gru ...

  5. Web前端性能优化,应该怎么做?

    摘要:本文将分享一些前端性能优化的常用手段,包括减少请求次数.减小资源大小.各种缓存.预处理和长连接机制,以及代码方面的性能优化等方面. base64:尤其是在移动端,小图标可以base64(webp ...

  6. webpack性能优化

    Webpack优化打包速度以及性能优化 1.跟上技术的迭代(Node.Npm.Yarn) 2.在尽可能少的模块上应用loader 3.Plugin尽可能精简并确保可靠 4.resolve参数合理配置 ...

  7. webpack 性能优化 -- 待续

    文章 这篇文章挺不错的, 各方面优化都提到了, 有空研究下 文章 这个文章提出 , 增量打包用 webpack-watch 会让你打包速度飞快,  react不参与打包, 不require, 而是放在 ...

  8. 浅谈webpack4.0 性能优化(转)

    前言:在现实项目中,我们可能很少需要从头开始去配置一个webpack 项目,特别是webpack4.0发布以后,零配置启动一个项目成为一种标配.正因为零配置的webpack对项目本身提供的“打包”和“ ...

  9. H5教程:移动页面性能优化

    随着移动互联网的发展,我们越发要关注移动页面的性能优化,今天跟大家谈谈这方面的事情. 首先,为什么要最移动页面进行优化? 纵观目前移动网络的现状,移动页面布局越来越复杂,效果越来越炫,直接导致了文件越 ...

随机推荐

  1. 第6月第19天 lua动态链接库(luaopen_*函数的使用) skynet

    1. 给这个测试库取名为dylib,它包含一个函数add.lua中这样使用: local dylib = require "dylib.test"    local c = dyl ...

  2. bash脚本:集群资源争夺战crazy-killer

    背景 公司的集群很多人一起用,有时候就难免资源紧张,某次需要用的时候没资源等了半天还是没资源,再等半天还是没资源,于是就写了个脚本泄愤,建议看到的人拷走放在自己公司集群上长期运行 :) 实现 此脚本运 ...

  3. 【译】EntityFramework6与EntityFrameworkCore的区别

    EntityFramework6 EF6 是一个久经考验的数据库访问技术,发展多年,拥有许多特性,并且成熟稳定.2008年EF作为 .Net 3.5 Sp1 和Visual Studio 2008 S ...

  4. ASP.NET MVC3 Model的常用验证示例

    1.金额(10位整数,2位小数) #region 余额 /// <summary> /// 余额 /// </summary> [DisplayName("余额&qu ...

  5. 解决阿里云安骑士漏洞警告:wordpress WPImageEditorImagick 指令注入漏洞

    解决:wordpress WPImageEditorImagick 指令注入漏洞 前些天在阿里云服务器上安装了wordpress,阿里云提示有wordpress WP_Image_Editor_Ima ...

  6. Java基础85 MVC开发模式

    1.MVC开发模式 本文用 Servlet+JSP+javaBean 的开发模式来讲解 Model:用javabean实现,用于封装业务数据View:用jsp实现,用于显示数据Controller:用 ...

  7. 有没有 linux 命令可以获取我的公网 ip, 类似 ip138.com 上获取的 ip?

    curl ipinfo.iocurl ifconfig.me 阿里云 :139.129.242.131赤峰:   219.159.38.197开平:   221.194.113.146定州:  121 ...

  8. mavean项目的jar位置的影响

    由于项目的数据库需求改变了,有mysql数据库变为oracle的,那么对于项目就是需要改变数据库连接池.这个项目运用了mavean框架,那么下载jar在pom.xml文件中填写就可以了,但是oracl ...

  9. Angular快速学习笔记(3) -- 组件与模板

    1. 显示数据 在 Angular 中最典型的数据显示方式,就是把 HTML 模板中的控件绑定到 Angular 组件的属性. 使用插值表达式显示组件属性 要显示组件的属性,最简单的方式就是通过插值表 ...

  10. Linux详细安装步骤

    Linux详细安装步骤(CentOS_6.7_64位) 1.先安装好VMware10软件 2.验证VM是否安装成功: (有些机器在安装vmware的时候会出现一个错误:virtual XT,这需要重启 ...