npm包管理npm其实是Node.js的一个包管理工具(nodepackagemanager)。为什么我们需要包管理工具?因为我们在Node.js上开发的时候,会用到很多别人写的JavaScript代码。如果我们要使用别人写的包,每次都要根据名字去官网搜索,下载代码,解压,再使用,非常麻烦。于是一个集中管理的工具应运而生:大家把自己开发的模块打包放到npm官网。如果他们想使用它们,可以直接通过npm安装来使用,而不管代码存在于何处或应该从哪里下载。更重要的是,如果我们要使用模块A,而模块A依赖于模块B,模块B又依赖于模块C和模块D,npm可以根据依赖关系下载并管理所有依赖包。否则,我们自己手动管理肯定会很麻烦,而且容易出错。npm的基础使用npm的指令及其经常使用的并不少官方文档;列如下:accessSetaccesslevelonpublishedpackagesadduserAddaregistryuseraccountauditRunasecurityauditbinDisplaynpmbinfolderbugsBugsforapackageinawebbrowsermaybebuildBuildapackagebundleREMOVED*已删*cacheManipulatespackagescacheciInstallaprojectwithacleanslatecompletionTabCompletionfornpmconfigManagethenpmconfigurationfilesdedupeReduceduplicationdeprecateDeprecateaversionofapackagedist-tagModifypackagedistributiontagsdocsDocsforapackageinawebbrowsermaydoctorCheckyourenvironmentseditEditaninstalledpackageexploreBrowseaninstalledpackagehelp-searchSearchnpm帮助文档帮助获取有关npmhook的帮助管理注册表挂钩init创建一个package.json文件install-ci-test从头开始安装一个项目并运行测试install-test安装包并运行测试install安装一个包linkSymlink一个包文件夹logout注销注册表ls列出已安装的包esnpmjavascriptpackagemanageroutdatedCheckforoutdatedpackagesowner管理包所有者pack从包中创建压缩包downdependencyversionsforpublicationstar标记你最喜欢的包stars查看标记为收藏的包start开始一个包停止停止一个包team管理组织团队和团队成员测试测试一个包token管理你的身份验证令牌uninstall删除一个包unpublish从注册表中删除一个包update更新一个包versionBump一个包版本view查看注册表信息whoami显示npmusernameinit初始化package.jsonnpminit[--force|-f|--yes|-y|--scope]npminit<@scope>(与npx<@scope>/create相同)npminit[<@scope>/](与npx[<@scope>/]create-相同)search搜索以查看远程npm相关资源包信息npmsearch[-l|--long][--json][--parseable][--no-description][searchterms...]别名:s,se,finindinstall可以说是beinstall官方介绍了最常用的命令,npminstall(withnoargs,inpackagedir)npminstall[<@scope>/]npminstall[<@scope>/]@npminstall[<@scope>/]@npminstall[<@scope>/]@npminstall:/npminstallnpminstallnpminstallnpminstall别名:npmicommon选项:[-P|--save-prod|-D|--save-dev|-O|--save-optional][-E|--save-exact][-B|--save-bundle][--no-save][--dry-run]在全局模式下(即,在命令后附加-g或--global),它会安装c当前包上下文(即当前工作目录)作为全局包。-g或--global参数将导致npm在全局而不是本地安装包。-f或--force参数将强制npm获取远程资源,即使磁盘上存在本地副本也是如此。上面的介绍已经很详细了,这里只说说npminstallpackageName[|--save|--save-prod|--save-dev];的区别。npminstall在babelnpm5之前,X包会安装在node_modules目录下,package.json的dependencies字段不会被修改。稍后运行npminstall命令时,不会自动安装Xnpm。babelnpm5之后,X包会安装在node_modules目录下。它会修改package.json的dependencies字段,然后当你运行npminstall命令时,X会自动安装,在线环境下会安装npminstallbabel-P-P,--save-prod:包将出现在您的依赖项中。这是默认设置,除非存在-D或-O。包将出现在您的依赖项中,使用--production标志(或当NODE_ENV环境变量设置为生产时),npm将安装dependencies中列出的模块。npminstallbabel-DPackage将出现在您的devDependencies中,使用--production标志(或当NODE_ENV环境变量设置为生产时),npm将不会安装devDependencies中列出的模块。PackageX会被安装到node_modules目录下,X会被添加到package.json的devDependencies属性下,稍后运行npminstall命令时,X会自动安装到node_modules目录下。当你运行npminstall–production或者指定NODE_ENV变量的值为production后,X不会自动安装到node_modules目录下更新升级某个资源包或所有资源。打包到某个版本或者最新匹配的版本npmupdate[-g][...]别名:up,upgradeuninstall删除一个资源包npmuninstall[<@scope>/][@]...[-S|--save|-D|--save-dev|-O|--save-optional|--no-save]别名:remove,rm,r,un,unlinknpmpackagesCreate、编写、测试、维护在Node出现之前,JavaScript缺乏包结构。CommonJS致力于改变这种情况,因此它定义了包的结构规范。NPM的出现就是在CommonJS规范的基础上解决包的安装卸载、依赖管理、版本管理等问题。清楚了require的查找机制之后,我们再来看一下包的细节。一个符合CommonJS规范的包应该有如下结构:包的顶层目录应该有一个package.json文件。二进制文件应包含在bin目录中(可选)。JavaScript代码存放在index.js,其他包含在lib目录下的文件应该在doc目录下(可选)单元测试应该在test目录下(可选)初始化包创建包的根目录mkdirtestpackage初始化npminit//需要写一些基本的配置来创建入口文件touchindex.js写代码constupdateQueryString=function(url,key,value){leturlParts=url.split('#'),hash='',uri=urlParts.shift(),re=newRegExp(`([?&])${key}=.*?(&|$)`,'i'),separator=uri.indexOf('?')!==-1?'&':'?',encodeKey=encodeURIComponent(key),encodeValue=encodeURIComponent(value);urlParts.length>0&&(hash=`#${urlParts.join('#')}`);如果(uri.match(re)){returnuri.replace(re,`$1${encodeKey}=${encodeValue}$2`)+hash;}else{return`${uri}${separator}${encodeKey}=${encodeValue}${hash}`;}};//最后的导出部分module.exports={updateQueryString};测试创建包根目录npmimocha-D//安装测试库npmichai-D//安装断言库mkdirtestcdtesttouchindex.test.js编写测试代码constutils=require('./../index.js');constexpect=require('chai').expect;让{updateQueryString}=utils;describe('updateQueryStringfunctiontest',function(){it('https://test.com/path?test=11修改test参数为22,应该等于https://test.com/path?test=22',function(){expect(updateQueryString('https://test.com/path?test=11','test',22)).to.be.equal('https://test.com/path?test=22');});});运行测试cd.../node_modules/mocha/bin/mochanpmpackagerelease注册账号npm官网终端执行npmlogin,输入用户名和密码,邮箱npmpublishpublish组织包我们经常可以看到@angular和@ionic都可以@开头,我们的也可以,原来angular和ionic属于一个组织(Organization)。只有在创建了一个新的Organization之后,我们才能创建一个类似@testorg/testpackname的包!!!然后我们就可以去官网创建我们的Organization,命名之后,官方步骤,初始化npminit--scope=npminitfoo->npxcreate-foonpminit@usr/foo->npx@usr/create-foonpminit@usr->npx@usr/create修改package.json中name字段为@your_org_name/publishnpmpublish--accesspublic//公共包发布npmpackagesupportsesmodule使用babel来进行一些现代JavaScript的支持,创建配置文件touch.babelrc安装先打包配置babel{"presets":[["@babel/preset-env",{"targets":{"browsers":["最后2个版本","safari>=7"],"chrome":52,"node":"6.10.0"},"modules":"commonjs","useBuiltIns":"usage"}]],“插件”:[“@babel/plugin-syntax-dynamic-import”,“@babel/plugin-syntax-import-meta”,“@babel/plugin-proposal-class-properties”,“@babel/plugin-proposal-json-strings",["@babel/plugin-proposal-decorators",{"legacy":true}],"@babel/plugin-proposal-function-sent","@babel/plugin-proposal-export-namespace-from","@babel/plugin-proposal-numeric-separator","@babel/plugin-proposal-throw-expressions","@babel/plugin-proposal-export-default-from","@babel/plugin-proposal-logical-assignment-operators","@babel/plugin-proposal-optional-chaining",["@babel/plugin-proposal-pipeline-operator",{"proposal":"minimal"}],"@babel/plugin-proposal-nullish-coalescing-operator","@babel/plugin-proposal-do-expressions"]}compile./node_modules/.bin/babelsrc-dlib最终测试代码地址test-demo-npm