前言最近打算更新项目中的npm依赖包,结果一试就惊呆了!批量更新真的很麻烦。各种package需要一个一个更新,就算直接改package.json也很麻烦。于是度娘就上了npm-check,然后琢磨了一会儿,结合cnpm搭建了一个自己很满意的包更新环境。所以我决定写一篇博文分享给大家。阅读本文需要有一定的node、npm、webpack基础(不高,相当低<( ̄ ̄ ̄)/)本文为个人理解,属个人观点。如有不当或错误的地方,请指正,谢谢!博文地址:高级npm模块管理——npm-check+cnpm搭建包更新环境1.npm-checknpm是node下的包管理工具,它为我们提供了强大的包管理功能,简化了项目的代码部署过程。不过npm并不完美,批量更新的时候很急。npm-check应运而生。npm-check是一个npm包更新工具。它还可以检查项目的npm依赖项是否更新、丢失、错误或未使用。它的主要优点如下:1.提供图形界面和表情符号。点个赞(不用看黑白界面!我也想用emoji写字!:-))2.批量更新依赖包,3.更新支持自动的“dependencies”和“devDependencies”项目下包检测,更新“package.json”信息!1.1npm-check安装>npminstall-gnpm-check//全局安装。可以选择在项目下安装>npminstallnpm-check//在项目下安装,在项目根目录下执行1.2npm-checkprojectdependencypackageupdate(1)查看包更新信息,会有一点黄色face提醒你包(需要更新,丢失,错误,未使用等)(表情包...)>npm-check(2)更新包。按类别显示,用空格选择包,回车开始更新。自动更新package.json中的相关包信息>npm-check-u//-update这是基础,这里是npm-check指令列表:-u,--update显示一个交互式UI,用于选择要更新的模块,并自动更新“package.json”中的包版本号信息-g,--global检查全局下的包-s,--skip-unused忽略未使用包的更新检查-p,--productionignore"-d,--dev-only忽略对"dependencies"下的包的检查-i,--ignore忽略对指定包的检查。-E,--save-exact保存确切的包版本存储在"package.json”(注意这个命令会存储'x.y.z'而不是'^x.y.z')1.3npm-check的问题当npm-check更新包时,它会根据版本号动态生成更新语句并执行它的本质依旧是npminstall命令:so,问题不是npminstall,而是国内的问题,由于网络等因素,国内用户更倾向于使用cnpm,也比较稳定和快速。下面介绍如何使用npm-check使用cnpm进行更新。3.npm-check+cnpmcnpm是阿里提供的一个完整的npmjs.org镜像,方便国内用户使用npm。我不会在这里详细介绍。准备工作:安装cnpm和npm-check本文将介绍两种将cnpm添加到npm-check的方法及其原理,如下。3.1两种方法的简要说明1.源码修改方法(1)在npm-check包下找到“npm-check\lib\”和“npm-check\lib-es5\”下的cli.js文件。(2)修改文件中代码“options”的属性“installer”:installer:process.env.NPM_CHECK_INSTALLER||'npm'//更改安装程序之前:process.env.NPM_CHECK_INSTALLER||'cnpm'//更改后2.修改环境变量值,将NPM_CHECK_INSTALLER设置为cnpm。后面会介绍三种修改方法,效果有些不同。3.2两种方法的原理1.源码修改方法npm-check目录结构如下。一眼就能看出“./lib”和“./lib-es5”的目录结构完全一样。有什么理由吗?没错,后面看了你就明白了。首先,最基础的,我们来看一下npm-check的“package.json”。(其中的“dependencies”等部分属性与本文无关,为了避免代码过长,我删掉了它们的内容){"name":"npm-check","version":"5.4.5","description":"检查过时的、不正确的和未使用的依赖项。","main":"lib","bin":{"npm-check":"bin/cli.js"},"engines":{"node":">=0.11.0"},"types":"./index.d.ts","typings":"./index.d.ts","scripts":{"lint":"xo./lib/*.js","test":"npmrunlint&&./bin/cli.js||echo退出状态:$?","transpile":"babellib--out-dirlib-es5","watch":"babellib--out-dirlib-es5--watch","prepublish":"npmruntranspile"},"xo":{"space":4,"rules":{"no-warning-comments":[0],"global-require":[0]}},"repository":{"type":"git","url":"https://github.com/dylang/npm-check.git"},"keywords":[],"author":{"name":"DylanGreene","email":"dylang@gmail.com"},"license":"麻省理工学院”,“错误”:{“网址”:“https://github.com/dylang/npm-check/issues"},"主页":"https://github.com/dylang/npm-check","文件":["bin","lib","lib-es5"],"dependencies":{},"devDependencies":{},"_from":"npm-check@5.4.5","_resolved":"http://registry.npm.taobao.org/npm-check/download/npm-check-5.4.5.tgz"}可以看到"bin"属性值为{"npm-check":"bin/cli.js"},其作用是链接"bin/cli.js"to"npm-check"在命令行执行“npm-check”时,会执行“bin/cli.js”。那么我们就来看看“bin/cli.js”到底有什么玄机。在查看之前,你可能觉得里面代码很多,看着头晕,但事实是里面只有9行:#!/usr/bin/envnodevarisEs2015;try{isEs2015=newFunction('()=>{}');}catch(e){isEs2015=false;}isEs2015?require('../lib/cli'):require('../lib-es5/cli');代码意思很明显,判断js环境是否支持es6(Es2015).isEs2015=newFunction('()=>{}');通过es6的箭头函数判断js环境,如果支持,isEs2015为真,导入'../lib/cli',否则导入'../lib-es5/cli'。所以上面说的“./lib”和“./lib-es5”目录结构是完全一样的,所以一目了然,因为它们分别是es6和es5下npm-check的实现。接下来我们分析一下“./lib/cli,js”的源码。毕竟es6是趋势。“./lib-es5/cli.js”是一样的。"./lib/cli,js":#!/usr/bin/envnode'usestrict';constmeow=require('meow');constupdateNotifier=require('update-notifier');constisCI=require('is-ci');constcreateCallsiteRecord=require('callsite-record');constpkg=require('../package.json');constnpmCheck=require('./index');conststaticOutput=require('./out/static-output');constinteractiveUpdate=require('./out/interactive-update');constdebug=require('./state/debug');constpkgDir=require('pkg-dir');updateNotifier({pkg}).notify();constcli=meow({...});//"npm-check-u,-g等指令的相关设计"constoptions={cwd:cli.input[0]||cli.flags.dir,更新:cli.flags.update,全局:cli.flags.global,skipUnused:cli.flags.skipUnused,ignoreDev:cli.flags.production,devOnly:cli.flags.devOnly,saveExact:cli。flags.saveExact,特价商品:cli.flags.specials,表情符号:cli.flags.emoji,安装程序:process.env.NPM_CHECK_INSTALLER||'npm',调试:cli.flags.debug,spinner:cli.flags.spinner,ignore:cli.flags.ignore};if(options.debug){...}//"是否显示调试输出"npmCheck(options)//"根据选项数据npm-check".then(currentState=>{...}).catch(err=>{...});具体代码太长,我换成了...,里面的功能我会看懂的,注释在后面,供参考。最重要的“选项”对象如下:constoptions={cwd:cli.input[0]||cli.flags.dir,更新:cli.flags.update,全局:cli。flags.global,skipUnused:cli.flags.skipUnused,ignoreDev:cli.flags.production,devOnly:cli.flags.devOnly,saveExact:cli.flags.saveExact,specials:cli.flags.specials,emoji:cli.flags。表情符号,安装程序:process.env.NPM_CHECK_INSTALLER||'npm',调试:cli.flags.debug,旋转器:cli.flags.spinner,忽略:cli.flags.ignore};其中定义了npm-check运行时的一些默认配置。查看“installer”属性:installer:process.env.NPM_CHECK_INSTALLER||值'npm'定义了npm-check在更新包时使用的包管理工具:process.env.NPM_CHECK_INSTALLER或npm。process.env.NPM_CHECK_INSTALLER是环境变量,与第二种方法有关,这里不再介绍。由于process.env.NPM_CHECK_INSTALLER通常未定义,因此将采用第二个值npm。将其更改为cnpm以使用cnpminstall。("./lib-es5"同上)多说一句:我分析实际源码的时候挺麻烦的。以上就是给大家的介绍,比较简单。这里简单描述一下我个人阅读源码后的理解,供大家参考:首先,在“./lib/out/install-packages.js”中定义了install()函数,负责解析输出包更新信息通过npm-check更新语句的函数,然后导出install()函数。“./lib/out/interactive-updates.js”引入install(),添加图形界面的实现后导出。最后,“./lib/cli.js”引入并组合选项,实现完整包更新的功能。2.修改环境变量修改源码的方法毕竟不是很好,修改环境变量相对好一些。回到前面,在“./lib/cli,js”中:installer:process.env.NPM_CHECK_INSTALLER||'npm'需要运行process.env.NPM_CHECK_INSTALLER>'process':Node的全局对象,提供当前Node的进程信息。>'process.env':存放“当前Shell”的环境变量。通常的做法是创建一个新的环境变量“NODE_ENV”,并用它来确定当前的开发阶段;将生产阶段设置为production,将开发阶段设置为develop或staging;然后读取脚本中的process.env.NODE_ENV,判断开发Condition。process.env.NPM_CHECK_INSTALLER是NPM_CHECK_INSTALLER变量。因为这是一个自定义变量,默认环境下是不存在这个值的,修改源码的方法可以成功。定义此变量后,安装程序的第二个参数将无效。(当然||规则,如果NPM_CHECK_INSTALLE为false结果的值,第二个参数仍然有效)2.1节点变量设置方法>setNPM_CHECK_INSTALLER=cnpm//win方,cnpm不加引号,否则是一个字符串值,是错误输入节点查看,设置成功。之后,在执行npm-checkupdates时使用cnpm。注意:该设置方式下环境变量的生命周期为当前shell。这个设置不能通过关闭终端或者使用其他shell等方式读取,环境不同!2.2项目“package.json”配置该方法针对具体的项目进行配置,一个项目中只需配置一个即可。另外,你也可以自己优化。“package.json”中的“scripts”对象可以自定义脚本命令。它的key是要运行的事件名称,value是要运行的命令,通过npmrun***来运行。在“scripts”中添加一个新的属性“nc-u”,如下所示:}使用npmrunnc-u一步执行即可。有几点需要注意:1、“nc-u”是自己自然命名的,符合规范的就可以;2.“setNPM_CHECK_INSTALLER=cnpm&&npm-check-u”也很清楚。先执行setNPM_CHECK_INSTALLER=cnpm,再执行npm-check-u。3、注意NPM_CHECK_INSTALLER=cnpm&&中的&&后面需要跟cnpm。如果&&前面有空格,那么这个空格也会分配给NPM_CHECK_INSTALLER,执行更新包的时候会报错。4、脚本命令中环境变量值的生命周期是在命令执行期间。这条命令执行后,NPM_CHECK_INSTALLER会被回收,恢复为undefined,不会污染整个世界。2.3项目“package.json”配置进阶——使用cross-env上面2.2配置中&&、set等的使用是因为window环境需要。如果转成Mac就会出错,而且有很多细节在不同的平台上是不一样的。如何跨平台使用?这时候我们就可以使用cross-env。cross-env是一个解决跨平台设置“脚本”的工具,使用后就不用再考虑平台问题了。大多数项目基本上都是默认添加cross-env。>npminstall--save-devcross-env//本地安装,写入依赖//package.json"scripts":{"start":"webpack-dev-server","nc-u":"cross-envnpm_check_installer=cnpmnpm-check-u"},"devDependencies":{"cross-env":"^5.0.5"}只需要在句首加上cross-env,cross-env会执行处理命令.注意:使用cross-env时使用&&会改变周围的语句环境,即每个语句段都有自己的环境,即环境变量设置会失效。谨慎使用&&。4.总结本文首先简单介绍了npm-check及其使用方法,然后介绍了如何将cnpm与cnpminstall结合起来,以及方法原理。至此,结合npm-check模块更新工具和cnpm国内镜像,提升了模块更新的操作性和速度,搭建了模块更新环境!5.断断续续写后记已经快一天了。写完后,我校对了它。一下子就快1点了,感觉和早上开始写的时候一样。终于写完了这篇博文。事实上,这是我第一篇正式意义上的博文。感觉莫名其妙。写完了还是有点心酸。。W( ̄_ ̄)W,不过写完了,还是很开心的。快乐的!遗憾的是,第一次写,还是有很多遗憾没能做好。尤其是看了npm-check之后,好想用几个小黄脸表情包:-)!但是不支持!遗憾的是,这是我第一次写,有不当或错误的地方还望大家多多包涵,欢迎大家指出,以便我改正。另外,如果觉得不错,希望大家喜欢,谢谢!
