前端高级进阶:在生产环境中使你的 npm i 速度提升 50%

字节行者说
• 阅读 4804

这是山月关于高级前端进阶暨前端工程系列文章的第 M 篇文章 (M 随便打的,毕竟也不知道能写多少篇),关于前 M-1 篇文章,可以从我的 github repo shfshanyue/blog 中找到,如果点进去的话可以捎带~点个赞~,如果没有点进去的话,那就给这篇文章点个赞。

本篇文章地址在 前端工程化系列,欢迎订阅。

  1. 前端高级进阶:javascript 代码是如何被压缩
  2. 前端高级进阶:如何更好地优化打包资源
  3. 前端高级进阶:网站的缓存控制策略最佳实践及注意事项
  4. 前端高级进阶:在生产环境中使你的 npm i 速度提升 50%

前端高级进阶:在生产环境中使你的 npm i 速度提升 50%

对于一个前端应用,或者说是一个 Node 应用,在 CICD pipeline 中,无论是构建,测试,部署,其中必不可少的环节就是依赖安装: npm i

npm i 不仅是必不可少的环节,而且很可能也是耗时最长的一个环节。

打蛇打七寸,优化应该从瓶颈处开始,如果能从依赖安装下手,将能极大地缩短部署时间,提高产品交付效率,改善 DevOps 流程,从而促进敏捷开发。

CI 环境中的优化不同于本地开发环境,其中最大的不同在于: 在本地环境中安装依赖是有状态的,如 node_modules~/.npmrc~/.npm 一系列硬盘目录及文件,无不构成状态。而在生产环境中,往往结合 CICD 工具,每次分配的 Runner 不一定是一台服务器(容器),往往被视为无状态,因而无法有效利用缓存而导致 CI 中部署用时过长。

但也正因为 CICD Runner 的无状态化,这意味着你只要参考构建脚本,如 .gitlab-ci.yaml.travis.yaml 或者 .github/workflows/deploy.yaml,就可以从零把项目跑起来,而避免过多在熟悉新项目时求助他人。

不同的部署方式,不同的持续集成工具有不同的实践方法,但优化的原理大同小异。

<!--more-->

前端高级进阶:在生产环境中使你的 npm i 速度提升 50%

如果嫌文章太长,直接直接拉到最下方看总结

只安装有必要的库

npm install 的速度显然与它依赖的包的多少是正相关的,那减少包的数量就可以减少装包所花费的时间。这个道题如同每天都少吃一顿饭就会变瘦一样简单。

使用 --production 可以只安装 package.jsondependencies 中的依赖项,只把要安装在 CI 中需要使用到的依赖。在生产环境部署时可以指定 --production

npm install --production

另外,通过设置环境变量 NODE_ENV=production 相当于指定 --production,测试如下:

$ NODE_ENV=production npm config get production
true

这唯一的不足就是需要你谨小慎微战战兢兢,如临深渊如履薄冰地把 packages 分拣到 devDependenciesdependencies 中。

使用私有镜像仓库

npm 的官方仓库可以发布与拉取 package,比如 reactvueexpress 都发布在官方仓库中。官方 registory 地址是 https://registry.npmjs.org/,这对国内的前端应用来说,由于远在国外,远程仓库的服务器时延过大,此时的瓶颈在于网络。

国内的公有镜像库是一个不错的选择,如淘宝镜像,它每隔十分钟与官方镜像仓库同步一次,而它位于国内,网络不至于太慢。

对于企业级项目的生产环境来说,在集群内部搭建私有仓库是一个更好的选择,也更能缩短时延。 流量能在局域网完成的,就不需要去互联网中溜圈了。

使用 npm config 来设置 npm 仓库,它将把仓库信息写入 ~/.npmrc 中,这足以适用于 CICD 中。

npm config set registry https://registry-npm.shanyue.tech/

缓存:人不能两次踏进同一条河流

人不能踏进同一条河流两次,一个接口不能连续慢两次,npm install 同样不能慢两次。

正如 http cache 一样,npm install 也可以充分利用缓存,npm 的缓存在 linux 系统中存在于以下路径:

  • ~/.npm

命令 npm cache verify 可以校验缓存,如下所示:

$ npm cache verify
Cache verified and compressed (~/.npm/_cacache):
Content verified: 4415 (156612117 bytes)
Index entries: 6239
Finished in 14.017s

结合 npm install --prefer-offline 缓存优先策略充分利用缓存

但是有一个悖论,在 CI 中是无状态的: 你本次装的 node_modules 和生成的 ~/.npm 将会在下次装包时丢失。

这时候就需要利用 CI 的缓存功能,如以下是 travis ci 的配置

install:
- npm ci
# keep the npm cache around to speed up installs
cache:
  directories:
  - "$HOME/.npm"

progress: 屏蔽非必要打印信息

当设置 progress 为 true 时,npm install 时将会显示进度条,把它设置为 false 可小幅提高 npm install 的速度。

修改设置:

npm set progress=false

官方文档 中对 progress 有以下介绍:

Default: true, unless TRAVIS or CI env vars set.
Type: Boolean

因此,只需要在构建服务器中简单设置一个 CI=true 的环境变量即可以很轻便地解决问题

使用 npm ci 替代 npm i

单看名字,里边有个 CI,它就像适用在 CI 中,事实也如此。它在 CI 环境中做了一系列优化,如去除掉一些面向用户的特性来加强速度。除了性能,它也有一些在 CI 上基于完整性与安全性的检查,如 package.jsonpackage-lock.json 版本不一致的问题。

为了更好地提高速度,npm ci 基于一个独立的库 libcipm 安装依赖,而它拥有和 npm install 兼容的 API。并且当它安装依赖时,默认是缓存优先的,它会充分利用缓存,从而加速装包。

经实验,npm ci 可以减少将近一半的的依赖安装时间。

$ npm install
added 1154 packages in 60s

$ npm ci
added 1154 packages in 35s

总结

最后总结一下如何减少 npm install 的时间,都是很简单的设置,一分钟搞定

  1. 选择时延低的 registry,需要企业技术基础建设支持
  2. NODE_ENV=production,只安装生产环境必要的包
  3. CI=true,npm 会在此环境变量下自动优化
  4. 结合 CI 的缓存功能,充分利用 npm cache
  5. 使用 npm ci 代替 npm i,既提升速度又保障应用安全性

与我交流

扫码添加我的机器人微信,将会自动(自动拉人程序正在研发中)把你拉入前端高级进阶学习群

前端高级进阶:在生产环境中使你的 npm i 速度提升 50%


大厂招聘

推荐一个关于大厂招聘的公众号【互联网大厂招聘】,作者将在公众号里持续推送各个大厂的招聘职位及要求,并与大厂面试官以及招聘负责人直通,感兴趣的可以直接与负责人交流。

另外,作者也将持续推送优质的大厂面试经验,各种大厂独家面试题以及优秀文章分享,不限于前端,后端,运维和系统设计。

我在 github 上新建了一个仓库 每日一题,每天一道面试题,欢迎交流。

前端高级进阶:在生产环境中使你的 npm i 速度提升 50%

点赞
收藏
评论区
推荐文章
blueju blueju
4年前
umi + qiankun 动态注册子应用解决方案
前言首发于<br/本篇文章可以被视为上一篇文章()的延续,上一篇文章大致讲述了搭建一个简易微前端平台的过程,其中关于子应用注册的配置是通过硬编码的方式,在构建打包前写入的。<br/<br/但是真实项目中,更需要的是动态注册子应用,比如说我正参与的这个项目。<br/<br/本篇文章的示例代码是基于上一篇文章示例代码改动的,上一篇文
马丁路德 马丁路德
4年前
推荐程序员必备的 10 大 GitHub 仓库,前端占了 7 个!
大家好,我是你们的猫哥,一个不喜欢吃鱼、又不喜欢喵的超级猫关于猫哥,大家可以看看我的年终总结前端工程师的2020年终总结乾坤未定,你我皆黑马(https://github.com/biaochenxuying/blog/issues/79)。前言初级前端与高级前端之间,很大原因就是投入学习前端的时间、经验的差别,其实就
徐小夕 徐小夕
4年前
前端进阶之从零到一实现单向 & 双向链表
前言前端工程师对于算法和数据结构这块的知识的掌握程度,是进阶高级工程师的非常重要的标志之一,为了总结一下数据结构和算法方面的知识,笔者今天继续把链表这一块的知识补上,也作为自己知识体系的一个梳理,笔者早在去年就写过一篇关于使用javascript实现二叉树和二叉搜索树的文章,如果感兴趣或者想进阶高级的朋友们可以参考学习一下:JavaScript中的二
Stella981 Stella981
3年前
Spring 3 mvc hello world例子
本篇文章中,我会使用maven构建一个基于SpringMVC的入门例子,前端标签库使用的是jstl。在开始之前,请确保你已经安装maven、eclipse以及tomcat。1.创建maven工程在eclipse的工作区中使用maven命令行创建一个空白工程,当然你也可以用eclipse的m2eclipse插件来创建。mvnarch
Stella981 Stella981
3年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Wesley13 Wesley13
3年前
CSS 奇思妙想:超级酷炫的边框动画
点上方蓝字关注公众号「前端从进阶到入院」精选原创好文助你进入大厂文章转载自公众号「iCSS前端趣闻」今天逛博客网站shoptalkshow\1\,看到这样一个界面,非常有意思:!(https://oscimg.oschina.net/oscnet/9655b35af5a045999ff55c144a3f7c
可莉 可莉
3年前
2017年前端开发工具趋势
你有两年以上的前端开发经验吗?你会用Sass和Autoprefixer等高级的CSS辅助技能吗?你的JavaScript知识是否融汇贯通,你是否喜欢使用Gulp,npm和jQuery?如果是这样,根据AshleyNolan的前端问卷调查,你是一个典型的前端开发工程师。01谎言,该死的谎言,统计数字和调查问卷谎言,该死的谎
Stella981 Stella981
3年前
2017年前端开发工具趋势
你有两年以上的前端开发经验吗?你会用Sass和Autoprefixer等高级的CSS辅助技能吗?你的JavaScript知识是否融汇贯通,你是否喜欢使用Gulp,npm和jQuery?如果是这样,根据AshleyNolan的前端问卷调查,你是一个典型的前端开发工程师。01谎言,该死的谎言,统计数字和调查问卷谎言,该死的谎