分分钟教会你搭建企业级的 npm 私有仓库

这是第 55 篇不掺水的原创,想获取更多原创好文,请扫 👆 上方二维码关注咱们吧~ 本文首发于政采云前端团队博客:分分钟教会你搭建企业级的 npm 私有仓库html

前言

npm 做为一种包管理工具,不管你是泛前端仍是大前端都已经离不开它。它的出现方便了万千少年。让咱们跨过了 Ctrl+C、Ctrl+V ,经过 npm install x 的方式将别人的优秀代码模块引入到本身的项目中。这些优秀的模块能被共享的缘由,一方面是有 npm 这么一个包管理工具,另外就是 npm 仓库。前端

对于 npm 仓库,若是你还停留在使用 npm 或者 cnpm 这类官方源的状况下。那么你有必要想一想如何搭建一个私有的 npm 仓库。下面从三个方面讲解企业级 npm 私有仓库搭建那些事儿,分分钟教会你。node

  • 为何须要搭建公司的私有 npm 仓库mysql

  • 如何搭建私有仓库linux

  • 搭建私有仓库扩展篇nginx

为何须要搭建公司的私有 npm 仓库

照惯例,先讲讲为啥要搭建私有仓库。目前已经有不少成熟的 npm 源可使用,好比:git

在已经有如此多公共仓库的状况下,是否有必要搞一套私有 仓库?重复"造轮子"?仍是自嗨?若是从下面几方面来考虑的话,或许能打消心中的疑问。github

1. 稳定性web

首先是网络访问稳定性,私有仓库由于是本身公司在维护,有什么问题能第一时间处理,好比服务宕机…其次资源的稳定性,试想一下,若是哪天你依赖的某个很重要的模块忽然被做者删了,那是否是完犊子了,毕竟咱们不少时候都奉行的是“拿来主义”,一旦碰见这种状况,基本上全抓瞎。若是有私有仓库,上面的问题能够从容面对,有效的保障了业务稳定。sql

2. 私密性

每一个公司都有和本身业务强相关的模块,或者对某些开源模块进行个性化的改造,改造后的模块只知足本公司的业务场景,这些模块咱们并不但愿发布到公共的仓库中去,这时就能够发布到本身的私有仓库在公司内部共享。

3. 安全性

有了私有仓库后,能够在 npm 模块的质量和安全上作文章,可以有效的防治恶意代码攻击。

综上,搭建本身公司的私有仓库彻底有必要,这并非秀。固然,若是你所在的公司比较 mini ,对于上面的几点需求并非那么迫切,使用公共仓库也挺好。但当公司发展到必定规模,在将来可预见的状况下,那就是时候准备搭建本身的私有仓库了。

如何搭建私有 npm 仓库

目前已经有许多成熟开源方案,选择站在巨人的肩膀上不失为一种良策。这里选择cnpmjs.org方案,缘由有三:

  1. 目前国内像淘宝这样的大厂内部也是选择的它,足以证实它的可靠行和稳定性

  2. 扩展性强

  3. 配置多样化

固然缺点也不是没有,就是部署有那么一丢丢复杂。

准备工做

兵马未动,粮草先行,既然是搭建企业级的应用,基础环境得备好。

  • Linux 服务器

  • node 环境

  • 数据库( Mysql )

  • nginx

大概就这些,若是你只是熟悉一下,搭着玩儿。也不必定得用 Linux 服务器,Windows 也行,可是若是是做为线上应用,建议仍是使用 Linux 服务器,毕竟 Linux 的稳定性在那里摆着。

下面的示例是在云服务器(Ubuntu)上完成的。

安装

  1. 安装cnpmjs.org

建议经过 git 将 cnpmjs.org 的项目源码克隆到服务器本地某个目录下。或者将代码fork到本身git仓库后,再基于内部仓库进行部署,这样方便之后对源码进行个性化的改造。

git clone https://github.com/cnpm/cnpmjs.org.git
复制代码

安装项目依赖:

npm i
复制代码

安装完成后找到项目根目录下的配置文件config/index.js ,这里配置文件很是多,刚开始能够只关注下面几项便可,详细配置戳这里。

  • 服务访问端口

    registryPort: 7001,         //仓库服务访问端口
    webPort: 7002,              //web站点访问端口
    bindingHost: '',   //监听绑定的 Host,默认127.0.0.1,外网访问注释掉此项便可,通常咱们不会把咱们内部端口暴露出去,能够在nginx层作一个转发,因此这个配置能够注释掉。若是直接外网访问,配置为 0.0.0.0
    复制代码
  • 数据库配置

    database: {
      db: 'npm',数据库名称
      username: 'admin',//用户
      password: 'admin123',//密码
      // 数据库类型
      // - 目前支持 'mysql', 'sqlite', 'postgres', 'mariadb'
      dialect: 'mysql',//默认是sqlite,我选择的mysql
      host: '127.0.0.1', //数据库服务地址
      port: 3306,    // 端口
      // 数据库链接池使用默认配置就好
      // 目前只支持 mysql 和 postgresql (since v1.5.0)
      pool: {
        maxConnections: 10,
        minConnections: 0,
        maxIdleTime: 30000
      },
      ...//其余的暂时不用关注
    },
    复制代码
  • 是否启用私有模式

    enablePrivate: false,//默认不启用
    复制代码

    私有模式下,只有管理员才能发布模块。非管理员发布模块式命名必须以 scopes 字段开头例如:@catfly/packagename

  • 发布前缀

    scopes: ['@catfly'],
    复制代码

    这个和启用非私有模式配套使用,非私有模式要发布必须配置该项。

  • 管理员帐号配置

    admins: {
          fengmk2: 'fengmk2@gmail.com',
          admin: 'admin@cnpmjs.org',
          dead_horse: 'dead_horse@qq.com',
    }
    复制代码

    若是启用私有模式,只有该配置项中的用户能够发布私有包。至于其余的配置项暂时不用关注,后面根据须要在逐渐配置起来。

  • 同步模式

    // 同步模式选项
    // none: 不进行同步,只管理用户上传的私有模块,公共模块直接从上游获取
    // exist: 只同步已经存在于数据库的模块
    // all: 定时同步全部源registry的模块
    syncModel:'exist'
    复制代码
  1. 数据库

    我选择的 mysql ,这里不介绍怎么安装 mysql 了,有须要请戳这里。固然你也能够选择其余数据库,目前支持mysql 、 sqlite 、 postgres 、 mariadb ,默认是 sqlite 。

    先检查一下数据库服务状态,确保数据库服务没毛病:

  • 登陆数据库

    mysql -u root -p test123456
    复制代码
  • 建立数据库

    create database npm;
    复制代码

    查看数据库列表:

  • 建立数据库表

    cnpmjs.org 项目 docs 目录下已经给咱们备好了建立数据库的脚本 db.sql 。执行:

    source docs/db.sql;
    复制代码

    默认当前操做路径就在 cnpmjs.org 项目下,若是不是,请用 db.sql 的绝对路径。

    查看结果:

上面两步完成后,就能够将项目跑起来一睹芳容了。由于咱们经过 git 克隆的,因此须要进入到项目目录下执行启动服务的命令

npm run start
复制代码

启动成功后,访问 web 页面,发现以前配置文件中的 web 端口 7002 访问不了。

这是由于服务器防火墙的缘由,能够选择关闭防火墙,可是这种方式不推荐;另一种就是开放指定端口。

iptables -A INPUT -p tcp --drop -j 7002 DROP
复制代码

若是你是使用的云服务器,须要去云服务控制台,新增安全组,将暴露的端口放开。

端口开放后,访问 web 页面:xxx.xxx.xxx.xx:7002,就能够看见熟悉的 cnpm 页面了。

在上面这张的访问地址能够看到,用了域名,并非用的 IP+ 端口的形式,由于做为一个企业级的应用,IP+ 端口的方式就如同裸奔同样,建议采用域名的方式。我在本身的云服务域名管理下新增了一个子域名。

而后配置 nginx 将 IP 和域名进行绑定,统一使用默认的 80 端口,尽可能不要将私有仓库服务的真实端口和 IP 暴露出来。这里顺便把 nginx 配置也说一下,若是你能接受 IP+ 端口访问的方式,能够跳过下面这一步。

  1. nginx配置

若是没有安装nginx,戳这里。找到 nginx 配置文件,在 conf.d 文件夹信息新增 npm.conf 配置文件,这样功能清楚明白,由于不少时候 nginx 不是只代理这个一个服务。

server{
      listen  80;
       server_name www.mirrors.catfly.vip;
       #charset koi8-r;
       #access_log  logs/host.access.log  main;
       location / { 
            proxy_pass http://127.0.0.1:7002/; #代理到cnpmjs.org提供的web服务
            proxy_set_header        X-Real-IP $remote_addr;
       }
       location /registry/ {
           proxy_pass http://127.0.0.1:7001/; # 代理到cnpmjs.org提供的注册服务
           proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header Host $host;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       }
       #error_page  404              /404.html;
       # redirect server error pages to the static page /50x.html
       # error_page   500 502 503 504  /50x.html;
       location = /50x.html {
           root   html;
       }
}
复制代码

重启 nginx :

service nginx restart
复制代码

检查 nginx 状态,防止配置错误,致使重启失败。

经过上面的环境搭建和部署,基本工做就完成了,下面开始验证功能。

功能验证

在验证以前推荐安装一个 npm 源管理模块 nrm ,有了它咱们能够在各类源之间自由切换。

npm i nrm -g
复制代码

安装成功后新增咱们本身的私有源到nrm源列表中。

nrm add catfly http://www.mirrors.catfly.vip/registry
复制代码

切换到私有源:

nrm use catfly
复制代码

这个时候本地执行 npm 操做的时候就会去找到咱们本身的私有地址。

  1. 私有包发布

    注册用户:

    npm adduser
    复制代码

    登陆私有仓库:

    npm login
    复制代码

    登陆成功后,发布 npm ,在已准备好的模块目录执行:

    npm publish
    复制代码

    这个时候可能会出现各类错误,主要是403权限问题,由于私有仓库在不一样模式下须要知足不一样的条件,例如:

    在非私有模式( enablePrivate: false)下,当用户不用具有管理员权限,模块命名前缀必须带有配置中规定的scope ,若是不存在或者 scopes 中不包含该 scope 就会报错。

    在私有模式(enablePrivate: true)下,若是用户不在配置文件的 admins 中,则不容许执行发布操做,反过来若是在,那么他的权限就很是大了,不只能发布还能删除。因此真实场景下不要让管理员帐号泛滥。

  2. 包下载安装

    发布成功后,尝试安装发布的私有包:

    npm i xxxxx
    复制代码

    没毛病。

  3. Web工做台

    访问私有仓库的web站点

    经过这个 站点能够对私有包的发布、删除以及下载进行统计,还能够私有包搜索功能。也能够对这个 web站点进行个性化改造。代码、数据都在咱们这边,想怎么造就怎么造。

私有npm仓库搭建扩展篇

在真实的企业级应用中,在上面的基础上还能够进行扩展,下面介绍一下能够扩展的几个方面:

进程管理

推荐使用 pm2 进行进程管理,虽然项目自己提供了npm run startnpm run stop的能力,可是这对于一个企业级的应用来讲仍是太弱了,使用 pm2 的好处以下:

  1. 随时随地多进程管理
  2. 完善的监控机制,咱们能够清晰地看见整个集群的模式、状态,CPU 利用率甚至是内存大小
  3. 负载均衡
  4. 进程守护
  5. ...
  • 全局安装pm2
npm i pm2 -g
复制代码
  • 启动项目
pm2 start ./dispatch.js //dispatch.js在cnpmjs.org项目的根目录下
复制代码

执行完后,能够看见该服务的基本信息,简洁明了。

  • 查看服务进程信息
pm2 monit dispatch //diapatch为当前进程name
复制代码

这里能够实时查看进程运行的详细信息,方便平时项目的维护。pm2 还有好多强大的功能,这里就不一一介绍了,有兴趣的戳这里

私有包存储上云

cnpmjs.org 项目配置项里面有一个 nfs配置,这里定义了一个 npm 文件系统(NFS)。私有仓库在同步和上传的时候,会交给 NFS 对象相应的函数去处理,NFS 对象返回处理结束以后再返回下载连接,因此经过自定义 NFS 模块能够实现 npm 包的各类定制存储。目前官方默认使用fs-cnpm,该模块会将上传或者同步的包保存在服务器本地的/root/.cnpmjs.org/doenloads/目录下。这种方式比较传统,一方面随着私有包数量的不断增长,存储资源会是一个瓶颈。另外一方面须要定时的备份资源,否则哪天磁盘坏了,那就只有

这个时候将私有包或者同步的资源放到云上就是一个很是好的方案。cnpmjs.org 官方早就为咱们想到了这点,给出了下面几种 NFS 模块:

这些模块已经可以知足咱们绝大部分的场景,若是你有特殊的需求,能够参看nfs模块规范进行定制化开发。这里拿阿里云 oss 存储做为示例。

首先在 cnpmjs.org 项目目录下安装oss-cnpm模块

cnpm i oss-cnpm
复制代码

而后在云服务控制台 oss 管理中新增了一个 bucket 来存储 npm 包,也能够经过上传路径区分来复用其余 bucket,毕竟在公司中 bucket 资源通常仍是比较紧张的。而后修改项目配置文件,将默认的fs-cnpm模块替换成oss-cnpm

var oss = require("oss-cnpm");
var nfs = oss.create({
  accessKeyId: 'xxxx',
  accessKeySecret: 'xxx',
  endpoint: 'oss-cn-beijing.aliyuncs.com',
  bucket: 'catfly-xxx',
  mode: 'private',
})
var config = {
  ...,
  nfs:nfs,
  ...
}
复制代码

重启项目,这个时候再发布或者同步资源的时候,服务器本地目录不会有新发布或同步的包了,在 oss 对应的 bucket 里面能找到刚刚发布或者同步的资源。

但愿这篇文章对你有所帮助。

参考文献

pm2使用介绍

部署和定制 CNPM——自定义包存储层

招贤纳士

政采云前端团队(ZooTeam),一个年轻富有激情和创造力的前端团队,隶属于政采云产品研发部,Base 在风景如画的杭州。团队现有 50 余个前端小伙伴,平均年龄 27 岁,近 3 成是全栈工程师,妥妥的青年风暴团。成员构成既有来自于阿里、网易的“老”兵,也有浙大、中科大、杭电等校的应届新人。团队在平常的业务对接以外,还在物料体系、工程平台、搭建平台、性能体验、云端应用、数据分析及可视化等方向进行技术探索和实战,推进并落地了一系列的内部技术产品,持续探索前端技术体系的新边界。

若是你想改变一直被事折腾,但愿开始能折腾事;若是你想改变一直被告诫须要多些想法,却无从破局;若是你想改变你有能力去作成那个结果,却不须要你;若是你想改变你想作成的事须要一个团队去支撑,但没你带人的位置;若是你想改变既定的节奏,将会是“ 5 年工做时间 3 年工做经验”;若是你想改变原本悟性不错,但老是有那一层窗户纸的模糊… 若是你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的本身。若是你但愿参与到随着业务腾飞的过程,亲手推进一个有着深刻的业务理解、完善的技术体系、技术创造价值、影响力外溢的前端团队的成长历程,我以为咱们该聊聊。任什么时候间,等着你写点什么,发给 ZooTeam@cai-inc.com

相关文章
相关标签/搜索