开发提效之npm私服搭建(verdaccio)

搭建私服目的

  1. 使用私有包:如果你想在你的公司内部使用 npm 包系统,而不把所有的代码公开,并且像使用公共包一样容易地使用你的私人包。
  2. 连接多个注册中心:如果你在你的组织中使用多个注册中心,并且需要在一个项目中从多个源获取软件包,你可以将多个注册中心连接起来,从一个单一的端点获取。
  3. 缓存 npmjs.org registry:如果你有一个以上的服务器要安装软件包,你可能想用这个来减少延迟并限制故障。
  4. 覆盖公共包:如果你想使用某个第三方软件包的修改版本,你可以在本地以相同的名称发布你的版本。

技术选型

最佳实践 | Verdaccio

笔者的环境配置

  • CentOS v7.6
  • docker v23

搭建步骤

  1. 使用docker拉取镜像5版本(目前最新稳定版) docker pull verdaccio/verdaccio:5
  2. 在指定目录下(eg: path/for/verdaccio/conf)新建配置文件config.yaml
  3. 复制官网配置到我们新建的文件下verdaccio/conf/docker.yaml at 5.x · verdaccio/verdaccio (github.com)
  4. 运行镜像
shell 复制代码
V_PATH=/path/for/verdaccio; docker run -it --rm --name verdaccio \  
-p 4873:4873 \  
-v $V_PATH/conf:/verdaccio/conf \  
-v $V_PATH/storage:/verdaccio/storage \  
-v $V_PATH/plugins:/verdaccio/plugins \  
verdaccio/verdaccio:5

5.此时我们可以看到服务已启动 6.查看本地ip地址(ifconfig指令),浏览器打开http://ip地址:4873 可以看到我们的ui页面(在这个页面可以查看我们已发布的私有包) 7.设置npm源地址为我们的私服npm set registry http://ip地址:4873

8.最后直接在本地执行npm install(pnpm/yarn 都行),同时查看我们的verdaccio容器的输出,可以看到,成功走了代理,并生成了npm包的缓存目录

conf.yaml配置

yaml 复制代码
# 缓存npm包的目录
storage: /verdaccio/storage/data
# 插件目录
plugins: /verdaccio/plugins

# webui配置,详情见https://verdaccio.org/docs/webui
web:
  title: 私有npm
  # comment out to disable gravatar support
  # gravatar: false
  # by default packages are ordercer ascendant (asc|desc)
  # sort_packages: asc
  # convert your UI to the dark side
  # darkMode: true
  # html_cache: true
  # by default all features are displayed
  # login: true
  # showInfo: true
  # showSettings: true
  # In combination with darkMode you can force specific theme
  # showThemeSwitch: true
  # showFooter: true
  # showSearch: true
  # showRaw: true
  # showDownloadTarball: true
  #  HTML tags injected after manifest <scripts/>
  # scriptsBodyAfter:
  #    - '<script type="text/javascript" src="https://my.company.com/customJS.min.js"></script>'
  #  HTML tags injected before ends </head>
  #  metaScripts:
  #    - '<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>'
  #    - '<script type="text/javascript" src="https://browser.sentry-cdn.com/5.15.5/bundle.min.js"></script>'
  #    - '<meta name="robots" content="noindex" />'
  #  HTML tags injected first child at <body/>
  #  bodyBefore:
  #    - '<div id="myId">html before webpack scripts</div>'
  #  Public path for template manifest scripts (only manifest)
  #  publicPath: http://somedomain.org/

# https://verdaccio.org/docs/configuration#authentication
auth:
  htpasswd:
    file: /verdaccio/storage/htpasswd
    # 最多可以注册的用户
    # 可以先注册好公共账号后,在设为-1,重启容器,保证权限
    # max_users: 1000
    # Hash algorithm, possible options are: "bcrypt", "md5", "sha1", "crypt".
    # algorithm: bcrypt # by default is crypt, but is recommended use bcrypt for new installations
    # Rounds number for "bcrypt", will be ignored for other algorithms.
    # rounds: 10

# 镜像源地址,按书写顺序读取 https://verdaccio.org/docs/configuration#uplinks
uplinks:
  taobao: 
    url: https://registry.npmmirror.com/
  npmjs:
    url: https://registry.npmjs.org/

# 配置安装access,发布publish,取消发布unpublish三者的权限
# $all 允许所有人操作
# $authenticated 允许注册用户操作
# https://verdaccio.org/docs/protect-your-dependencies/
# https://verdaccio.org/docs/configuration#packages
packages:
  '@*/*':
    # scoped packages
    access: $all
    publish: $authenticated
    unpublish: $authenticated

  '**':
    # allow all users (including non-authenticated users) to read and
    # publish all packages
    #
    # you can specify usernames/groupnames (depending on your auth plugin)
    # and three keywords: "$all", "$anonymous", "$authenticated"
    access: $all

    # allow all known users to publish/publish packages
    # (anyone can register by default, remember?)
    publish: $authenticated
    unpublish: $authenticated

    # if package is not available locally, proxy requests to 'npmjs' registry
    proxy: taobao npmjs

# To improve your security configuration and  avoid dependency confusion
# consider removing the proxy property for private packages
# https://verdaccio.org/docs/best#remove-proxy-to-increase-security-at-private-packages

# https://verdaccio.org/docs/configuration#server
# You can specify HTTP/1.1 server keep alive timeout in seconds for incoming connections.
# A value of 0 makes the http server behave similarly to Node.js versions prior to 8.0.0, which did not have a keep-alive timeout.
# WORKAROUND: Through given configuration you can workaround following issue https://github.com/verdaccio/verdaccio/issues/301. Set to 0 in case 60 is not enough.
server:
  keepAliveTimeout: 60
  # Allow `req.ip` to resolve properly when Verdaccio is behind a proxy or load-balancer
  # See: https://expressjs.com/en/guide/behind-proxies.html
  # trustProxy: '127.0.0.1'

# https://verdaccio.org/docs/configuration#offline-publish
publish:
  allow_offline: true

# https://verdaccio.org/docs/configuration#url-prefix
# url_prefix: /verdaccio/
# VERDACCIO_PUBLIC_URL='https://somedomain.org';
# url_prefix: '/my_prefix'
# // url -> https://somedomain.org/my_prefix/
# VERDACCIO_PUBLIC_URL='https://somedomain.org';
# url_prefix: '/'
# // url -> https://somedomain.org/
# VERDACCIO_PUBLIC_URL='https://somedomain.org/first_prefix';
# url_prefix: '/second_prefix'
# // url -> https://somedomain.org/second_prefix/'

# https://verdaccio.org/docs/configuration#security
# security:
#   api:
#     legacy: true
#     # recomended set to true for older installations
#     migrateToSecureLegacySignature: true
#     jwt:
#       sign:
#         expiresIn: 29d
#       verify:
#         someProp: [value]
#    web:
#      sign:
#        expiresIn: 1h # 1 hour by default
#      verify:
#         someProp: [value]

# https://verdaccio.org/docs/configuration#user-rate-limit
# userRateLimit:
#   windowMs: 50000
#   max: 1000

# https://verdaccio.org/docs/configuration#max-body-size
# max_body_size: 10mb

# https://verdaccio.org/docs/configuration#listen-port
# listen:
# - localhost:4873            # default value
# - http://localhost:4873     # same thing
# - 0.0.0.0:4873              # listen on all addresses (INADDR_ANY)
# - https://example.org:4873  # if you want to use https
# - "[::1]:4873"                # ipv6
# - unix:/tmp/verdaccio.sock    # unix socket

# The HTTPS configuration is useful if you do not consider use a HTTP Proxy
# https://verdaccio.org/docs/configuration#https
# https:
#   key: ./path/verdaccio-key.pem
#   cert: ./path/verdaccio-cert.pem
#   ca: ./path/verdaccio-csr.pem

# https://verdaccio.org/docs/configuration#proxy
# http_proxy: http://something.local/
# https_proxy: https://something.local/

# https://verdaccio.org/docs/configuration#notifications
# notify:
#   method: POST
#   headers: [{ "Content-Type": "application/json" }]
#   endpoint: https://usagge.hipchat.com/v2/room/3729485/notification?auth_token=mySecretToken
#   content: '{"color":"green","message":"New package published: * {{ name }}*","notify":true,"message_format":"text"}'

middlewares:
  audit:
    enabled: true

# https://verdaccio.org/docs/logger
# log settings
log: { type: stdout, format: pretty, level: http }
#experiments:
#  # support for npm token command
#  token: false
#  # enable tarball URL redirect for hosting tarball with a different server, the tarball_url_redirect can be a template string
#  tarball_url_redirect: 'https://mycdn.com/verdaccio/${packageName}/${filename}'
#  # the tarball_url_redirect can be a function, takes packageName and filename and returns the url, when working with a js configuration file
#  tarball_url_redirect(packageName, filename) {
#    const signedUrl = // generate a signed url
#    return signedUrl;
#  }

# translate your registry, api i18n not available yet
# i18n:
# list of the available translations https://github.com/verdaccio/verdaccio/blob/master/packages/plugins/ui-theme/src/i18n/ABOUT_TRANSLATIONS.md
#   web: en-US

如何发布私有包

  1. npm adduser --registry http://ip地址:4873 (ps: 账号密码随便输入,默认会注册私服账号,只要yaml文件中的max_users不为-1)
  2. npm publish --registry http://ip地址:4873
  3. 打开私服web地址查看发布结果

搭建问题及解决

问题一:发布/安装报错 查看容器日志可以看到是配置的缓存目录权限问题导致

解决:原因是docker用户组没有写删权限,这里我们给storage的父目录verdaccio配置上权限

问题二 安装报错到某些npm包时报错

解决:删除node_modules后重新安装

验证安装速度

在powershell下执行Measure-Command { npm install }得出我们安装所花费的时间 。主要验证下面几种常见场景

  • 场景一:私服上没有缓存我们下载所需要的tarball包时(在客户端触发npm i时私服需要去上游镜像拉取,再返回给客户端)
  • 场景二:私服完全缓存了我们下载所需要的tarball包
  • 场景三:私服完全缓存,我们本地项目有package-lock.json,但是没有本地缓存npm cache(即测试我们新拉一个已有项目下来进行安装时的情况)
  • 场景四:私服完全缓存,我们本地项目有package-lock.json,本地也有缓存npm cache
场景 淘宝镜像时间(Seconds) 私服时间(Seconds)
66.1365592 112.9423327
同上 91.9693539
29.0035019 28.2227523
19.0764919 19.7750994

综上我们可以看到,在有package-lock.json的情况下,淘宝镜像和私服下载速度几乎一致。但是没有package-lock.json的情况下,私服下载速度要慢了非常多。通过阅读源码发现,在没有package-locak的情况下,在进行npm i 时通,每一个依赖包都会发两个请求(请求地址为我们uplink所配置的源地址)。

一个是请求该包的注册表(用来生成package-lock.json中的信息)

另外一个是请求tarball包(也就是依赖的压缩包)来下载到本地。

私服缓存的注册表和tarball

从上面可以看到,有时候注册表比我们真正所需要的依赖包要大非常多,因为注册表里面放了该依赖包的所有版本信息及一些readme信息等。在有package-lock.json的情况下,只会进行tarball的下载,而不会触发去更新注册表,所以会快很多。从verdaccio的打印日志我们也可以验证。

验证离线安装

为了模拟离线安装,我们使用whistle对淘宝镜像进行代理,返回500。

  1. 安装whistlenpm i -g whistle
  2. 启动whistlew2 start
  3. 设为全局代理w2 proxy
  4. 安装https证书w2 ca
  5. 在浏览器打开whistle页面(http://localhost:8899/),配置我们的代理%25EF%25BC%258C%25E9%2585%258D%25E7%25BD%25AE%25E6%2588%2591%25E4%25BB%25AC%25E7%259A%2584%25E4%25BB%25A3%25E7%2590%2586 "http://localhost:8899/)%EF%BC%8C%E9%85%8D%E7%BD%AE%E6%88%91%E4%BB%AC%E7%9A%84%E4%BB%A3%E7%90%86")
  6. 勾上https
  7. 本地电脑搜索代理,找到这个框取消勾上,使代理可以挂到全局
  8. 配置规则
  9. 为命令窗口配置代理,指向whistle地址,并验证代理结果

离线环境准备完毕,清除本地缓存 rm -rf node_modules && rm package-lock.json && npm cache clean --force 。然后进行npm i操作

结果 :verdaccio请求镜像源失败,但是客户端安装成功,验证离线功能正常可用

相关推荐
并不会28 分钟前
常见 CSS 选择器用法
前端·css·学习·html·前端开发·css选择器
衣乌安、31 分钟前
【CSS】居中样式
前端·css·css3
兔老大的胡萝卜32 分钟前
ppk谈JavaScript,悟透JavaScript,精通CSS高级Web,JavaScript DOM编程艺术,高性能JavaScript pdf
前端·javascript
低代码布道师34 分钟前
CSS的三个重点
前端·css
耶啵奶膘2 小时前
uniapp-是否删除
linux·前端·uni-app
王哈哈^_^4 小时前
【数据集】【YOLO】【目标检测】交通事故识别数据集 8939 张,YOLO道路事故目标检测实战训练教程!
前端·人工智能·深度学习·yolo·目标检测·计算机视觉·pyqt
cs_dn_Jie4 小时前
钉钉 H5 微应用 手机端调试
前端·javascript·vue.js·vue·钉钉
开心工作室_kaic5 小时前
ssm068海鲜自助餐厅系统+vue(论文+源码)_kaic
前端·javascript·vue.js
有梦想的刺儿5 小时前
webWorker基本用法
前端·javascript·vue.js
cy玩具5 小时前
点击评论详情,跳到评论页面,携带对象参数写法:
前端