利用 verdaccio 搭建私有npm平台及在内网中使用
    
  
      
      
     
    
      
        verdaccio 的安装使用方法,其官网上有更详情的内容。
这里我给大家重点介绍一下使用 docker 来安装,还有一些个性化的配置,以及邮件通知的配置方法。
安装
首先拉取 verdaccio 的镜像:
1
   | docker pull verdaccio/verdaccio
   | 
 
利用 docker-compose.yml 来启动容器:
1 2 3 4 5 6 7 8 9 10 11 12 13
   | version: "3" services:     verdaccio:         image: verdaccio/verdaccio:latest         container_name: npm-verdaccio         restart: always         ports:             - 4873:4873         volumes:             - ./data/verdaccio/conf:/verdaccio/conf             - ./data/verdaccio/storage:/verdaccio/storage             - ./data/verdaccio/plugins:/verdaccio/plugins         tty: true
   | 
 
在上面的配置中,我们将环境配置、库文件、插件目录都挂载到了本地当前对应的目录中,方便后面修改和数据的持久化。
运行启动容器:
之后,会看到挂载的目录会生成对应的文件,下面我们来修改配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   |  uplinks:     npmjs:         url: https://registry.npm.taobao.org
 
  storage: ../storage
 
  web:     enable: true     title: npm私有库     logo: /verdaccio/conf/logo.svg     primary_color: "#de0000"     favicon: /verdaccio/conf/favicon.ico     pkgManagers:         - pnpm         - npm     showInfo: false     showSettings: false     showThemeSwitch: false     showFooter: false     scriptsBodyAfter:         - "<style></style>"
 
  | 
 
内网
如果你的 verdaccio 是搭建在内网的,还需要将外网的第三方包下载安装转移到内网。
这个工作首先需要在可以连接互联网的设备上同样使用 docker 安装 verdaccio 环境。
安装成功后,默认会在本地启一个 4873 的 http 服务。
本地还要安装 node 环境,通过 node 的 npm init 创建本地项目,通过当前项目的根目录文件 .npmrc,如果没有可自行创建,内容为:
1
   | registry=http://localhost:4873
   | 
 
这样,在本地安装安装的项目,将会从私有平台 4873 上下载获取第三方包,verdaccio 通过其设置的上游链接,去互联网上下载后,会缓存放置在 storage 目录中。
这样操作之后,在 verdaccio 的 storage 目录中就会存在我们需要的第三方包,我们可以将其转移到内网环境中。
1
   | sudo tar --exclude=storage/@sg --exclude=storage/@wgl --exclude=storage/.verdaccio-db.json -zcvf storage.tar storage
   | 
 
上面的压缩命令,我们排除了本地测试的自定义包,和 verdaccio 的版本数据文件,是为了覆盖时不要把内网 verdaccio 里的私有数据覆盖了,只允许覆盖第三方包。
解压覆盖到内网 verdaccio 的 storage 目录后,重启内网的 docker 容器即可。
通知
verdaccio 给我们提供了 publish 的通知功能,当有新包被推送时,可以及时通知相关引用使用者,下面是一个比较好的通知配置:
1 2 3 4 5
   | notify:     method: POST     headers: [{ "Content-Type": "application/json" }]     endpoint: http://172.17.0.1:5000/send_email     content: '{"subject":"{{ publishedPackage }}已推送","sendMail":"`{{#each versions}} {\"enable\":\"{{ sendMail.enable }}\",\"msg\":\"{{sendMail.msg}}\",\"to\":\"{{sendMail.to}}\"}{{/each}}`","message":"User:{{ publisher.name }}<br/>Package:{{ publishedPackage }}`{{#each versions}} <br/> Author:{{author.name}}<br/>Email:{{author.email}}<br/>Integrity:{{dist.integrity}}<br/>Tarball:{{dist.tarball}}{{/each}}`","notify":true,"message_format":"text"}'
   | 
 
这里的 endpoint 是接口地址,我们可以使用 express 框架来建立一个发送邮件的服务。
index.js 的服务文件内容如下:
点击查看完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
   | const express = require("express"); const nodemailer = require("nodemailer"); const bodyParser = require("body-parser");
 
 
 
  const app = express(); const PORT = 5000;
 
  app.use(bodyParser.json());
 
  app.use(bodyParser.urlencoded({ extended: true }));
 
  const baseFormat = (obj) => {     for (let key in obj) {         if (typeof obj[key] === "string") {             obj[key] = obj[key].replaceAll("`", "").trim();         }     }     return obj; };
 
  const emailConfig = {     defaultTo: ["webape@qq.com"],     from: "webape@qq.com",     host: "smtp.qq.com",     port: 465,     user: "webape@qq.com",     pass: "******", };
 
  app.post("/send_email", (req, res) => {     const body = baseFormat(req.body);     const { sendMail, subject, message } = body;     console.log("body", body);
      const sendMailObj = baseFormat(JSON.parse(sendMail));
      if (["true", ""].indexOf(sendMailObj.enable) > -1) {         const defaultTo = emailConfig.defaultTo;                  const mailOptions = {             from: emailConfig.from,             to: sendMailObj.to                 ? sendMailObj.to.split(",").map((item) => item.trim())                 : defaultTo,             subject: subject,             html:                 message.replaceAll("`", "") +                 (sendMailObj.msg                     ? '<div style="background-color:red;color:#fff">' +                       sendMailObj.msg +                       "</div>"                     : ""),         };
                   const transporter = nodemailer.createTransport({             host: emailConfig.host,             port: emailConfig.port,             auth: {                 user: emailConfig.user,                 pass: emailConfig.pass,             },         });
                   transporter.sendMail(mailOptions, (error, info) => {             if (error) {                 console.log(error);                 res.status(500).send("邮件发送失败");             } else {                 console.log("Email sent: " + info.response);                 res.send("邮件发送成功");             }         });     } else {         res.send("无需发送邮件");     } });
 
  app.listen(PORT, "172.17.0.1", () => {     console.log(`Server is running on http://172.17.0.1:${PORT}`); });
  | 
 
 
可以看到上面的服务是绑定在 ip:172.17.0.1 上的,这个是 docker 的网关地址,使 docker 内部可以访问外部宿主机的 http 服务。
我们可以在和 verdaccio 同一服务器中后台启动该服务:
1 2 3 4
   | # 在后台执行程序 nohup node index.js & # 将该进程与当前 shell 分离,避免关闭当前 shell 连接后进程关闭 disown
   | 
 
由于 verdaccio 的通知是读取的项目的 package.json 的数据在我们的项目的 package.json 文件中,我们可以添加以下内容来配合邮件通知的发送行为和内容:
1 2 3 4 5
   | "sendMail":{     "enable":true,     "msg":"提示信息",     "to":["webape@qq.com"] },
  | 
 
配置说明:
- 当 
package.json 中没有定义 sendMail 对象时,默认会向内置的默认用户发送通知邮件。 
- 当 
sendMail.enable 为 true 时,表示发送邮件,false 时表示不发送邮件,默认为 true。 
- 用户可以通过 
sendMail.msg 来在邮件中指定提示信息,例如,“此版本为测试版本,请勿使用”。 
- 用户可以通过指定 
to 来限定邮件的发送范围,为空数组时,默认会向内置的默认用户发送。 
注意
- 
私有库绑定域名后,用什么域名第一次访问,则默认就是哪个域名。我们一般还会配合绑定域名使用成功一个可以对外提供服务的站点,需要注意的时,绑定域名后,第一次访问后,再次访问需要使用该域名才能访问。但是我们可以使用环境变量 VERDACCIO_PUBLIC_URL 来指定域名地址。
 
- 
私有库需要 npm adduser 添加用户后输入邮箱后半天没有反应,应该是 htpasswd 文件写权限问题。可以给其 775 的权限。
 
- 
使用 pnpm 时的缓存问题。因为 pnpm 本身也会创建本地的存储库,当想在外网缓存外部库转到内网中时,.nprc 配置 registry=[地址],执行 pnpm store prune,pnpm store path 查看缓存库位置删除,删除 node_modules 和 pnpm-lock.yaml,后执行 pnpm install。
 
      
     
    
      
  
  
    
      
      
        
        致力于网站建设与Web开发。喜欢新事物,关注前后端动态,对新的技术有追求, 做一个优秀的web全栈工程师。