当前位置: 首页 > 后端技术 > Node.js

内外网npm私服(verdaccio)搭建及依赖包上传

时间:2023-04-03 10:56:54 Node.js

由于公司是基于内网开发环境开发的,所有的依赖包都要从外网复制到内网,当有依赖包发生变化,必须同步更新转到内网无疑会降低开发效率。另外,我们可以将常用的开发组件打包发布到自己的npm仓库中,方便复用。1、外网全局安装verdaccionpminstall-gverdaccio首先启动verdaccio,任意控制台执行命令verdaccio出现如下信息,说明安装成功warn---configfile-/home/yg/.config/verdaccio/config.yaml//配置文件位置warn---插件成功加载:htpasswdwarn---插件成功加载:auditwarn---http地址-http://localhost:4873/-verdaccio/3.10.1//仓库地址4873表示默认在端口浏览器中输入地址http://localhost:4873/启动服务。我之前上传的组件显示在这里。2.config.yaml配置说明###后面是注释#所有包的缓存目录storage:./storage#插件目录plugins:./plugins#开启web服务,可以通过web访问web:#WebUI是默认启用,如果要禁用,只需取消注释这一行+信息”。#您可以将其设置为-1以禁用注册。#max_users:1000#我们可以访问的其他已知存储库列表#public仓库配置uplinks:npmjs:url:https://registry.npmjs.org/packages:'@*/*':#scopedpackagesaccess:$allpublish:$authenticated#Agent意思是如果没有仓库,就去这个npmjs找,#npmjs指向https://registry.npmjs.org/,也就是上面的uplinkConfigureproxy:npmjs'**':#三种身份,所有人,匿名用户,认证(登录)用户#"$all","$anonymous","$authenticated"#需要的权限是否可访问access:$all#发布包的权限publish:$authenticated#如果包不存在,则向代理的上游服务发起请求proxy:npmjs#要使用`npmaudit`取消注释followingsectionmiddlewares:audit:enabled:true#监听端口,重点,不要配置这个,只有本机可以访问listen:0.0.0.0:4873#允许离线发布publish:allow_offline:true#logsettingslogs:-{type:stdout,format:pretty,level:http}#-{type:file,path:verdaccio.log,level:info}特别注意一定要配置listen:0.0.0.0:4873才能运行其他机器访问!!!离线发布依赖包,必须设置allow_offline:true!!!3、添加用户并设置npm镜像源#当前npm服务指向本地npmsetregistryhttp://localhost:4873#注册用户在本地注册一个用户,指向我们的地址,然后我们就可以发布包了npmadduser--registryhttp://xxx:4873Username:xxxPassword:xxxPassword:xxxEmail:(thisISpublic)xxx在http://xxx/(你的ip地址)上以yg-ui登录,这时候我们要注册一个用户,我们可以使用Usethisusernameandpasswordtologin.到上面的窗口进行登录,下次登录只需要输入npmlogin然后依次输入账号密码,然后查看当前用户npmwhoami查看当前用户是否登录成功4.发布依赖包首先要设置镜像源:npmsetregistryhttp://localhost:4873为了方便管理npm源,它建议安装nrm。如何使用这里就不多介绍了,大家可以直接百度。接下来以vuecli3库方式为例,将vue组件发布到私服1、在package.js中添加一条编译成库的命令"lib":"vue-cli-servicebuild--targetlib--namevcolorpicker--destlibpackages/index.js"--target:构建目标,默认为应用模式。此修改为lib启用库模式。--dest:输出目录,默认dist。这里我们改成lib[entry]:最后一个参数是入口文件,默认是src/App.vue。这里我们指定编译packages/组件库目录。在library模式下,Vue是external的,也就是说即使在代码中引入了Vue,打包后的文件也不包含Vue。如果我们在dependencies中引入lodash等生产环境必须安装的依赖库,我们可以在vue.config.js中配置external属性,不打包相应的依赖包。module.exports={configureWebpack:{externals:{'vue':'Vue','vue-router':'VueRouter','axios':'axios','lodash':'\_'}}}2、配置package.json{"name":"packagename","version":"0.1.5","description":"基于Vue组件库","main":"lib/index.js","keyword":"vcolorpickercolorpickercolor-picker","files":['dist','page'],"private":false}其中private:必须设置为faslefiles:设置上传到npm库main的文件目录:项目入口,默认是同级目录的index.jsname:npm包名,也就是我们importxxxfrompackagename中的包名也可以这样理解。importxxxfrompackagename,xxx是主入口导入lib/index.js暴露出来的变量名。3、添加.npmignore文件,忽略发布文件设置为与package.json的files属性相同。当我们发布到npm时,只需要发布编译好的lib、package.json、README.md等文件即可。所以我们需要设置忽略目录和文件。语法与.gitignore的语法相同。需要提交什么文件,根据自己的实际情况而定。#忽略目录examples/packages/public/#忽略指定文件vue.config.jsbabel.config.js*.map4,登录npmnpmlogin具体登录过程同上,就不说了很多关于它。5.发布到npmnpmpublish执行后显示发布成功,就可以在npm私服上找到自己的包了。如果发布不成功,可能是包名或版本重复,更改配置即可。5、内网npm私服搭建复制如下对应的外网目录到内网环境文件:C:\\Users\\用户名\\AppData\\Roaming\\npm\\verdaccio文件:C:\\Users\\用户名\\AppData\\Roaming\\npm\\verdaccio.cmd目录:C:\\Users\\用户名\\AppData\\Roaming\\npm\\node\_modules\\verdaccio文件:C:\\Users\\用户名\\AppData\\Roaming\\npm\\node\_modules\\verdaccio文件:C:\\Users\\用户名\\AppData\\Roaming\\verdaccio\\config.yaml目录:C:\\Users\\Username\\AppData\\Roaming\\verdaccio\\storage注意storage目录是存放npm依赖包的地方,我们可以先直接在外网发布npm包,然后将storage文件夹复制到内网,然后打开内网的verdaccio地址,可以发现这些依赖包已经自动发布到内网了。我们将依赖包发布到npm私服。包有两种,一种是自己开发的包,一种是外网npm上的开源包。如果你想发布一个开源包到你的私服上使用,请注意几点(我是踩坑过来的!!!):1:要发布的npm依赖包最好用npm下载,不是cnpm,因为cnpm包含各种快捷方式,复制到其他电脑会出现各种问题2:注意查看发布的npm包中package.json中的脚本是否包含republish等hook属性。republish会在发布之前执行命令,而往往我们没有执行命令的环境,所以报错。我们可以设置Itdeletes3:依赖包中可能嵌套了其他依赖包。在依赖包的子目录下的node_modules文件夹中查看依赖。它也必须在发布之前发布。因为node_modules冒泡查找依赖,同一个依赖包有不同的版本,公共版本被提取到依赖包的最外层,特殊版本只能存在于当前目录下的node_modules文件夹中4:如果你想发布指定的package.json正常情况下所有的npm包至少有100个依赖包,我们手动发布是非常困难的。不过verdaccio不支持一键导入,所以我们只能一一发布。这里我写了一个node,自动读取node_modules目录下的文件,自动将依赖包发布到npm的publish文件中,供大家试试!constfs=require('fs');constpath=require('路径');constprocess=require('process');//导入方法执行控制台命令constexec=require('child_process').execSync;//保存根路径constrootPath=__dirname;letresult=fs.readdirSync(rootPath);constconsoleLogPath=path.join(rootPath,'log');result.forEach(fName=>{constdPath=path.join(__dirname,fName);conststat=fs.statSync(dPath);if(stat.isDirectory()){constmodulePath=path.join(dPath,'node_modules');if(!fs.existsSync(modulePath))return;conststatModules=fs.statSync(modulePath);if(statModules.isDirectory()){constres=fs.readdirSync(modulePath)getVersion(res,consoleLogPath,modulePath,fName)}}})functiongetVersion(result,logPath,modulePath,fName){result.forEach(item=>{//加入当前包路径constdPath=path.join(模块路径,物品);//获取路径的statconststat=fs.statSync(dPath);//判断包路径是否为目录if(stat.isDirectory()){//如果是目录,执行如下操作//当前包目录下的package.json文件路径constpackageJsonPath=path.join(dPath,'package.json');if(fs.existsSync(packageJsonPath)){//读取当前包目录下的package.json文件内容,返回字符串constpackageJsonContentString=fs.readFileSync(packageJsonPath,'utf8');//将package.json文件的内容解析成json格式的对象constparsedPackJson=JSON.parse(packageJsonContentString);if(parsedPackJson.scripts&&Object.keys(parsedPackJson.scripts).length!==0){parsedPackJson.scripts={};fs.writeFileSync(packageJsonPath,JSON.stringify(parsedPackJson));}//将当前目录切换到当前包路径process.chdir(dPath);//在包路径下执行cmd控制台命令npmpublishtry{exec('npmpublish');}catch{console.log(`package${fName}:${item}已发布`);}//操作完成后,将当前路径切换到原来的根目录process.chdir(rootPath);console.log(fName,parsedPackJson.name,parsedPackJson.version)//如果解析出来的json格式对象有scripts属性,并且该属性不是空对象,则将其内容设置为空对象fs.appendFileSync(logPath,`${fName}/${parsedPackJson.name}/@${parsedPackJson.version}\n`);}}})}参考文档《npm 模块安装机制简介》《node_modules 困境》