问题背景
用Nexus搭建了内网的依赖仓库,需要将前端工程中node_modules中的依赖上传到Nexus上,但是node_modules中的依赖已经是解压后的状态,如果直接机械地将其简单地打包上传到Nexus,那么无法通过npm install下载使用。故有此文。
前置条件
- Nexus上已创建好hosted类型的npm仓库,假设起名为:npm-local
- 本地前端工程所在PC可以连接互联网
- 本地前端工程已执行npm install且已生成package-lock.json
批量下载
三种方式
- 通过 package.json 的 _resolved属性链接下载
- 通过 package-lock.json 的 resolved属性链接下载
- 本地直接打包方式
以下以package-lock.json方式进项下载,使用python代码
# -*-coding:utf-8-*-
import json
import os
from pathlib import Path
from urllib.request import urlretrieve
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)
# print(load_dict)
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)
# print(load_dict)
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):
""" 根据下载链接下载 """
# 判断输出的目录是否存在
if store_path is None:
store_path = 'C:\\Users\\yangr\\Desktop\\npm'
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("links:" + str(len(links)))
# print(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("down:" + url)
urlretrieve(url, filepath)
# else:
# print("file already exists:", filename)
except Exception as e:
print('Error Url:' + url)
print('Error:', e)
if __name__ == '__main__':
# down_link = "C:\\Users\\Administrator\AppData\Roaming\\npm\\node_modules"
# down_link = "D:\\Git\\vue\\1\package-yarn.lock"
# down_link = "D:\\Git\\vue\\node_modules"
down_link = "C:\\Users\\yangr\\Desktop\\npm\\package-lock.json"
download_file(down_link,"C:\\Users\\yangr\\Desktop\\npm\\tgz")
print("ok")
运行 python downloadFile.py
在py文件的目录中tgz的文件夹中tgz
批量上传
将tgz放到nexus服务器上,并将npmUpload.sh放到tgz中
#!/bin/bash
# 获取命令行参数
while getopts ":r:u:p:" opt; do
case $opt in
r) REPO_URL="$OPTARG"
;;
u) USERNAME="$OPTARG"
;;
p) PASSWORD="$OPTARG"
;;
esac
done
# find 并批量上传
find . -type f -name '*.tgz' | sed "s|^\./||" | xargs -I '{}' \
curl -u "$USERNAME:$PASSWORD" -X 'POST' -v \
${REPO_URL} \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'npm.asset=@{};type=application/x-compressed' ;
运行如下命令即可
sh npmUpload.sh -u 用户名 -p 密码 -r http://127.0.0.1:8089/service/rest/v1/components?repository=私库
上述方法使用的是nexus的API接口上传
为了方便集成和管理,Nexus提供了大量API,如下图所示为Nexus的设置-系统-API页面。我们可以看到Components分组下有一个上传单个组件的接口。