一、首先下载Nexus
官网下载需要vpn翻墙,所以就找了一个网盘上的版本-3.37




    
.3。下载地址:
链接: https://pan.baidu.com/s/1GC9tDlsaqcmMECxWAwjG-g 提取码: kvi7

解压后不用安装,直接可以使用,解压到指定的目录。

三、配置环境变量
四、启动Nexus

1、切换到解压Nexus目录的bin目录下

cd D:\Program Files (x86)\nexus-3.37.3-02\bin

2、执行运行命令

// 此命令是前台运行,关闭命令窗口后结束运行
.\nexus.exe /run 
// 此命令是后台运行,关闭命令窗口后仍运行
.\nexus.exe /start
// 停止运行
.\nexus.exe /stop
五、验证启动成功

打开浏览器输入localhost:8081/即可访问,或者使用ip地址代替localhost

六、登录Nexus

首次登录提示admin的密码存储位置,到相应位置拷贝输入后登录

七、创建仓库

npm仓库一共有三种类型:group、hosted、proxy

1、创建hosted仓库

2、创建proxy仓库

3、创建group仓库

组仓库的设定是为了将私有库和代理库同时管理起来,在开发的时候就不需要不断的切换镜像源,只需要使用组仓库就可以了。

八、配置权限

此处是把npm的权限给激活。如果不激活,就不能adduser和publish。

九、下载npm tgz包

在公司内网不能访问外网的情况下,可以把npm包的tgz压缩包下载下来上传到Nexus上,其他人就可以使用Nexus的镜像地址,进行npm install了。

下载方式:

1、网上说使用 node-tgz-downloader 进行下载,尝试后发现并不可以,未查原因。

2、自己实现下载:通过解析package-lock.json文件中依赖的resolved地址下载tgz包,可能是npm包的镜像地址对下载做了限制,如果一次性下载的过多,就需要重复执行多次,才能下载完全【暂时没有解决这个问题】。具体代码如下:

// command.js
module.exports = {
  PATH: '--path'

在install.js中对ts类型的库做了处理。

// install.js
const download = require('download');
const jsonfile = require('jsonfile');
const path = require('path');
const fs = require('fs');
const axios = require('axios');
const command = require('./command');
const packagesPath = path.resolve(__dirname, 'packages');
const packagesTypesPath = path.resolve(__dirname, 'packages\\types');
const argv = process.argv;
const pathIdx = argv.findIndex((val, idx) => {
  if (val === command.PATH) {
    return idx;
let filePath = path.resolve(__dirname, 'package-lock.json');
(function () {
  if (pathIdx !== -1 && pathIdx < argv.length - 1) {
    filePath = argv[pathIdx + 1]
})();
jsonfile.readFile(filePath, async function (err, jsonData) {
  if (!err) {
    // 存储npm包
    const resolvedUrl = [];
    // 重复多少个
    const havedUrls = [];
    // 存储types包
    const typesUrl = [];
    const loopDependencies = (dependenciesData) => {
      const dependencies = dependenciesData.dependencies || {};
      Object.keys(dependencies).forEach(function (key) {
        if (key) {
          const dependencie = dependencies[key]
          const resolved = dependencie.resolved
          const name = resolved.split('/').pop()
          const find = resolvedUrl.find((obj) => obj.resolved === resolved)
          const findTypes = typesUrl.find((obj) => obj.resolved === resolved)
          if (!find && !findTypes) {
            if (!key.includes('@types')) {
              resolvedUrl.push({
                name,
                resolved,
            } else {
              typesUrl.push({
                name,
                resolved,
          } else {
            havedUrls.push(resolved)
          loopDependencies(dependencie)
    loopDependencies(jsonData)
    console.log(`总共${resolvedUrl.length}+${typesUrl.length}个依赖,${havedUrls.length}个重复`);
    if (!fs.existsSync(packagesPath)) {
      fs.mkdirSync(packagesPath);
    if (!fs.existsSync(packagesTypesPath)) {
      fs.mkdirSync(packagesTypesPath);
    // fs.writeFileSync('a.json', JSON.stringify(resolvedUrl));
    const finishTotal = [];
    resolvedUrl.forEach(async (obj, idx) => {
      await download(obj.resolved, packagesPath);
      finishTotal.push(idx);
      console.log(finishTotal.length, 'finishTotal');
      if (finishTotal.length === resolvedUrl.length) {
        console.log('完成所有下载');
      // const {
      //   data
      // } = await axios({
      //   url: obj.resolved,
      //   headers: {
      //     'Content-Type': 'multipart/form-data'
      //   },
      //   responseType: 'arraybuffer'
      // })
      // await fs.promises.writeFile(packagesPath + '\\' + obj.name, data);
      // finishTotal.push(idx);
      // console.log(finishTotal.length, 'finishTotal');
      // if (finishTotal.length === resolvedUrl.length) {
      //   console.log('完成所有下载');
    const finishTypesTotal = [];
    typesUrl.forEach(async (obj, idx) => {
      await download(obj.resolved, packagesTypesPath);
      finishTypesTotal.push(idx);
      console.log(finishTypesTotal.length, 'finishTypesTotal');
      if (finishTypesTotal.length === typesUrl.length) {
        console.log('完成所有Types包下载');
      // const {
      //   data
      // } = await axios({
      //   url: obj.resolved,
      //   headers: {
      //     'Content-Type': 'multipart/form-data'
      //   },
      //   responseType: 'arraybuffer'
      // })
      // await fs.promises.writeFile(packagesTypesPath + '\\' + obj.name, data);
      // finishTypesTotal.push(idx);
      // console.log(finishTypesTotal.length, 'finishTypesTotal');
      // if (finishTypesTotal.length === typesUrl.length) {
      //   console.log('完成所有types下载');

使用方式:

cd到install.js的目录下,执行 node install.js --path D:\King-Project\temp-npm\package-lock.json,path后是package-lock.json所在的目录,下载完成后,在当前目录下有一个packages文件夹,里边就是tgz包了。

十、上传下载的npm tgz包

创建shell脚本文件upload.sh和upload-type.sh,脚本如下:

#!/bin/bash
targetDir=tgz文件所在目录(packages | packages/types)
publishRestful=ip地址:port端口/service/rest/v1/components?repository=npm仓库名
echo ">>> 文件所在目录:$targetDir <<<"
dir=$(ls -l $targetDir | awk '/.tgz$/ {print $NF}')
cd $targetDir
for file in $dir
  echo ">>> $targetDir/$file 上传开始 \n"
  ret=`curl -u nexus用户名:nexus密码 -X POST "$publishRestful" -H "Accept: application/json" -H "Content-Type: multipart/form-data" -F "npm.asset=@$file;type=application/x-compressed"`
  echo $ret
  echo ">>> $targetDir/$file 上传完成 \n"

在终端直接运行:.\upload.sh .\upload-type.sh

如有好的建议,请留言,谢谢