使用 Nexus3 搭建 npm 私库,超详细的图文教程
安装运行 Nexus3
1. 下载
2. 安装
- 将
nexus-3.46.0-01-win64.zip
文件解压到D:\Program Files\nexus3
目录下,如图所示:
其中:
nexus-3.46.0-01
为 nexus 服务器相关文件目录
sonatype-work
为 nexus 数据存储目录
-
新增全局变量。在
path
变量中新增D:\Program Files\nexus3\nexus-3.46.0-01\bin
-
注册服务。以管理员身份打开命令行窗口。运行
nexus /install nexus3
。 即可在系统同注册一个名为nexus3
的服务。 -
windows + r
打开运行窗口,输入services.msc
找到nexus3
服务,点击启动
,即可启动服务,如图所示:
- 更多命令。
# 启动服务
$ nexus /run nexus3
# 停止服务
$ nexus /stop nexus3
# 删除服务
$ nexus /uninstall nexus3
- 稍等片刻后,你可以通过在浏览器中输入
http://localhost:8081/
,进入服务,如图所示:
-
点击
Sign in
进行登录。其中用户名为admin
,密码在文件D:\Program Files\nexus3\sonatype-work\nexus3\admin.password
中查看,第一次登录需要修改密码,如修改成admin123
, 修改密码后admin.password
⽂件会⾃动删除。 -
至此,nexus 安装运行已全部完成。
创建新仓库
- 创建一个名为
vue-cms
的仓库,如图所示:
-
完成后,点击
Create repository
完成。 -
以上操作完成后,现在我们就可以在浏览列表看到
vue-cms
仓库了,如图所示:
上传 npm 依赖到自定义仓库
接下来我们测试一下,上传项目中的 npm 依赖到我们的自定义仓库
1. 创建项目
- 创建目录
test-project
- 执行
npm init -y
- 安装依赖
npm install chart.js
2. 下载 tgz 包
接下来我们要做的就是,将package.json
中的依赖 chart.js
进行下载。
方式1:
- 打开
package-lock.json
文件,找到dependencies
属性,将其下的所有依赖包依赖包,进行下载。
-
复制每个插件
resolved
属性后的链接到浏览器进行下载。 -
将下载的
.tgz
包放到与package.json
同级目录的node(需创建)
文件夹下。
方式2(推荐):
通过 python
脚本进行下载,需要有 python
环境
- 在
package.json
同级目录下创建download.py
文件, 脚本如下:
# -*-coding:utf-8-*-
import json
import os
import urllib.request
from pathlib import Path
def node_modules(file_dir):
# 通过递归遍历 node_modules 每个子包的 package.json 解析下载链接
links = []
for root, dirs, files in os.walk(file_dir):
if 'package.json' in files:
package_json_file = os.path.join(root, 'package.json')
try:
with open(package_json_file, 'r', encoding='UTF-8') as load_f:
load_dict = json.load(load_f)
if '_resolved' in load_dict.keys():
links.append(load_dict['_resolved'])
except Exception as e:
print(package_json_file)
print('Error:', e)
return links
def package_lock(package_lock_path):
# 通过递归遍历 package-lock.json 解析下载链接
links = []
with open(package_lock_path, 'r', encoding='UTF-8') as load_f:
load_dict = json.load(load_f)
search(load_dict, "resolved", links)
return links
def yarn_lock(package_lock_path):
# 通过递归遍历 xxx-yarn.lock 解析下载链接
links = []
with open(package_lock_path, 'r', encoding='UTF-8') as load_f:
for line in load_f:
if line.find('resolved') >= 0:
line = line.replace('resolved', '')
url = line.strip().strip('"')
links.append(url)
return links
def search(json_object, key, links):
# 遍历查找指定的key
for k in json_object:
if k == key:
links.append(json_object[k])
if isinstance(json_object[k], dict):
search(json_object[k], key, links)
if isinstance(json_object[k], list):
for item in json_object[k]:
if isinstance(item, dict):
search(item, key, links)
def download_file(path, store_path, flag):
# 根据下载链接下载
if not Path(store_path).exists():
os.makedirs(store_path, int('0755'))
links = []
if path.endswith("package-lock.json"):
links = package_lock(path)
elif path.endswith("yarn.lock"):
links = yarn_lock(path)
else:
links = node_modules(path)
print("link resolved number:" + str(len(links)))
for url in links:
try:
filename = url.split('/')[-1]
index = filename.find('?')
# 去掉 ? 参数和 # 哈希
if index > 0:
filename = filename[:index]
index = filename.find('#')
if index > 0:
filename = filename[:index]
filepath = os.path.join(store_path, filename)
if not Path(filepath).exists():
print("download:" + url)
# 以防以后对请求头做限制
opener = urllib.request.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
urllib.request.install_opener(opener)
if flag:
new_path = os.path.join(os.getcwd(), 'tgz')
if not Path(new_path).exists():
os.makedirs(new_path, int('0755'))
filepath = os.path.join(new_path, filename)
urllib.request.urlretrieve(url, filepath)
# else:
# print("file already exists:", filename)
except Exception as e:
print('Error Url:' + url)
print('Error:', e)
if __name__ == '__main__':
# 通过 xxx 文件解析对应依赖树
download_link = os.path.join(os.getcwd(), 'package-lock.json')
# 下载文件存放的路径
download_path = os.path.join(os.getcwd(), 'node')
# 下载文件是否存放到一个新的路径里,默认存放到 node 目录下, download_flag 为 True 时 存放到 tgz 目录下
download_flag = False
download_file(download_link, download_path, download_flag)
print("ok")
- 运行脚本,执行
python download.py
,也可以修改scripts
命令来执行。 执行后我们可以看到在node
目录下有了两个.tgz
包。
- 如有报错,请将当前目录下的
node
和tgz
文件夹删除后重新执行脚本。
3. 上传依赖
- 在
package.json
同级目录下创建publish.sh
。
#!/bin/bash
PACKAGE_PATH=./node
REPOSITORY=http://localhost:8081/repository/vue-cms/
npm login --registry=$REPOSITORY
for file in $PACKAGE_PATH/*.tgz; do
npm publish --registry=$REPOSITORY $file
done
如图所示:
- 在当前项目下,打开
Git Bash
,运行./publish.sh
。如图所示:
- 输入用户名
admin
和 密码admin123
以及邮箱123@qq.com(随意)
,回车。
- 靠,报错了401!,如图:
- 在 nexus 平台上添加
npm Bearer Token Realm
-
再次执行
./publish.sh
, 成功! -
我们可以去 nexus 平台上找到 vue-cms 仓库点进去看到我们已经上传的依赖。如图所示:
测试 npm install
既然 npm 依赖已经上传到了私库上了接下来我们测试一下是否可以成功下载。
- 删除
vue-cms
项目的node_modules
。 - 创建
.npmrc
文件,指定下载路径。
registry=http://localhost:8081/repository/vue-cms/
如图所示:
- 打开终端,执行
npm install
,成功!
如图所示:
常遇问题
1. 内网上传的 tgz
包无法下载成功
原因:
个别包(这里以 nw@0.36.4-sdk
为例),下载时会自动去它的官网下载安装,内网无法访问导致下载失败。
解决方案:
将下载的 nw-0.36.4-sdk-tgz
解压,其内是 package 文件夹。
阅读其 package.json
文件,发现 "scripts.postinstall": "node scripts/install.js"
走的是 scripts
下的install.js
文件。
阅读 install.js
文件, 发现其 urlBase
为 官网源,将其修改为 我们 nginx
文件下载的服务器,如 http://IP:Port/nwjs/nwjs-sdk-v0.36.4-win-x64.zip
, 这里的压缩包是 nw-0.36.4-sdk
的可执行包,点击下载,并将 url = urlBase
,注释其平台类型判断代码。
随后在 package
文件夹下新增 .npmrc
文件, 设置 registry
源为内网的 nexus
库, 设置完毕后执行 npm pulish
进行推送。
推送成功后即可测试下载。