前端工程之npm

package.json是npm package的配置文件,存储当前项目相关的信息。若是下载npm中的包,包内会自带该文件。node

具体属性

{
  "name" : "underscore",  //当前包(项目)的名字
  "description" : "JavaScript's functional programming helper library.",
  "homepage" : "http://documentcloud.github.com/underscore/",
  "keywords" : ["util", "functional", "server", "client", "browser"],
  "author" : "Jeremy Ashkenas",
  "contributors" : [],
  "dependencies" : [],//生产依赖
  "devDependencies”:[],//开发依赖
  "repository" : {"type": "git", "url": "git://github.com/documentcloud/underscore.git"},
  "scripts": {
    "build": "node build.js"
  }
  "main" : "underscore.js",   //当前项目(包)的入口文件,该文件的导出对象做为该模块的导出对象 
  "version" : "1.1.6"
}

main:the main entry point for the libary; when someone runs require(<library name>), require resolves this call to require(<package.json:main>).react

dependencies :used to list all the dependencies of your project that are available on npm. When someone installs your project through npm, all the dependencies listed will be installed as well. Additionally, if someone runs npm install in the root directory of your project, it will install all the dependencies to ./node_modules.webpack

devDependencies :these are dependencies not required for normal operation, but required/recommended if you want to patch or modify the project. If you built your unit tests using a testing framework, for example, it would be appropriate to put the testing framework you used in your devDependencies field. To install a project's devDependencies, simply pass the --dev option when you use npm install.git

scripts:每个属性,对应一段脚本。每当执行npm run xxx 时就会自动新建一个 Shell,在这个 Shell 里面执行指定的脚本命令。npm run新建的Shell会将当前目录的node_modules/.bin子目录append到PATH变量,执行结束后,再恢复原样。因此当前目录的node_modules/.bin子目录里面的全部脚本,均可以直接用脚本名调用,在没有全局安装时也没必要加上路径。因此只要是 Shell能够运行的命令,均可以写在 npm 脚本里面。github

  传入参数:npm run <command> [-- <args>] ,因此在scripts中要用 -- 双中线分隔传给npm命令的参数和传给脚本的参数。node server.js --port=8888 转换成  npm run server -- --port=8888 web

  执行多个脚本:并行执行多个命令使用&符号,顺序执行(前一个任务成功才执行下一个任务)使用&&符号。typescript

全局安装vs本地安装:

Global packages are for anything that you need to access from the shell. By contrast local packages are for using within your apps.shell

npm install xxx -g :属于全局安装将包安装在C:\Users\admin\AppData\Roaming\npm\node_modules目录下,同时在node_modules平级目录生成批处理文件,这样能够在任何地方执行xxx的CIL命令。不然须要cd到项目的cmd命令所在目录再执行/双引号包含可执行命令的全路径,很繁琐。全局安装时的包不能够经过 require() 来引入。npm

@IF EXIST "%~dp0\node.exe" (
  "%~dp0\node.exe"  "%~dp0\node_modules\gulp\bin\gulp.js" %*
) ELSE (
  @SETLOCAL                 //变量本地化
  @SET PATHEXT=%PATHEXT:;.JS;=;%    //删除js后缀的默认执行文件,不直接执行gulp.js
  node  "%~dp0\node_modules\gulp\bin\gulp.js" %*    //在命令行输入gulp时,实际上调用的是这条命令:用node解释器调用批处理文件所在目录下的js文件
)
 :属于将包安装在项目根目录下的node_modules目录下的.bin目录下,生成对应的cmd命令,在项目根目录下能够直接运行。能够经过 require() 来引入本地安装的模块。npm install xxx –save-dev本地安装

  

 
@IF EXIST "%~dp0\node.exe" (
  "%~dp0\node.exe"  "%~dp0\..\._gulp@3.9.1@gulp\bin\gulp.js" %*        //"执行其余目录下的文件"  "node执行的js文件地址"   %*其余任意变量
) ELSE (
  @SETLOCAL
  @SET PATHEXT=%PATHEXT:;.JS;=;%
  node  "%~dp0\..\._gulp@3.9.1@gulp\bin\gulp.js" %*  //%~dp0表明的是bat文件所在的文件目录,不可变;指向当前项目依赖的gulp模块的js
)
若是不安装全局包,则在pro目录下是不能执行对应的命令行命令,必须cd到.bin目录下,或者经过npm link命令或经过package.json的scripts字段设置:
"scripts" : {
  "build" : "webpack ./entry.js bundle.js""deploy": "export NODE_ENV=production && `npm bin`/webpack --config webpack.config.production.js && npm start",
}
 

而后运行npm run build命令。
json

require()查找文件的顺序

当require一个文件模块时,先从当前执行文件平级的的node_modules目录中查找;而后查找上一级的node_modules目录;依次迭代,直到根目录下的node_modules目录。若是尚未查找到指定模块的话,就会去NODE_PATH注册的路径中查找

require绝对路径的文件,查找时不用去遍历每个node_modules目录,其速度最快。

为何要全局安装和本地安装两次?

本地安装可让每一个项目依赖独立的包,不受全局包的影响,保证不一样版本的包之间的相互依赖,能够经过require()使用引入的模块。是npm的默认安装模式。

全局安装并不依赖引入的模块。它会在'C:\Users\admin\AppData\Roaming\npm'生成对应的cmd文件,保证在任何地方均可以经过命令行执行该程序,不用cd到项目目录执行。如全局安装gulp是为了在任何地方均可以执行gulp任务,本地安装gulp则是为了调用gulp插件的功能。

npm 经常使用命令

安装模块

npm install      //安装package.json中定义的全部依赖的包
npm install [<@scope>/]<name>@<version>    //安装指定版本的包,如不指定版本,默认安装最新的包
alias: npm i
options: 
-S|--save    //保存版本信息到package.json文件的dep字段中
-D|--save-dev    //保存版本信息到package.json文件的devDep字段中
npm install --production  # 添加了production参数后将仅仅安装package.json中dependencies 里面的包,不会安装devDependencies 里的模块,不然get all  &  installed。一个模块不能同时在两种环境中安装。dependenciesdevDependencies

卸载模块

npm uninstall <pkg>
aliases: remove, rm, r, un, unlink
options:
-S|--save    //删除package.json中dev字段对应的信息
-D|--save-dev //删除package.json中devDep字段对应的信息

更新模块

npm outdated [<pkg>]    //列出全部过期的包
npm update [-g] [<pkg>...]    //更新指定到包到最新版本;若是未指定,则更新全部包,包括全局和本地
aliases: up, upgrade
options:同上

其余命令

npm config get prefix              //获取全局模块安装路径;
where node                           //获取node所在路径;
npm <command> -h              //查看该命令的全部使用帮助信息;
npm view package@2.3.1 [version|dependencies] //查看远程包内的package.json信息
npm config ls –l                    //查看npm内置的配置参数
npm install 或者 npm install –save-dev   //自动将所在目录的package.json中的模块安装到node-modules文件夹下,不用一个一个安装模块。
npm ls xxx [–depth=0]                 //查看本地安装的模块版本信息,只看当前目录,不遍历子目录。注意:子模块的devdependency依赖包不会被安装,只安装dep包。

cnpm

由于npm是从国外服务器下载,常常出现异常,能够使用淘宝团队开发的镜像cnpm,cnpm跟npm用法同样。

安装命令:npm install cnpm -g --registry=https://registry.npm.taobao.org

create-react-app安装模块慢,能够设置永久使用cnpm:

$:npm config set registry https://registry.npm.taobao.org

$:npm config set registry http://registry.npmjs.org   #官方地址

使用nrm管理registry地址:

1.安装nrm:npm install -g nrm

2.注册registry地址:

  nrm add npm http://registry.npmjs.org

  nrm add cnpm https://registry.npm.taobao.org

3.切换registry地址

  nrm use npm/cnmp

依赖包版本管理 

包版本号为X.Y.Z三位,表明主版本号、次版本号和补丁版本号。当代码变动时,按如下原则更新版本号:
主版本号:有不兼容的API 修改时; 
次版本号:有向下兼容的功能性新增时;
补丁版本号:作了向下兼容的bug修正时。

依赖包版本号管理(固定写死须要手动更新):
~匹配最近的小版本依赖包,好比~1.2.3会匹配全部1.2.x的包,可是不包括1.3.0。
^匹配最新的大版本依赖包,好比^1.2.3会匹配全部1.x.x的包,可是不包括2.0.0。

 

配置npm仅安装精确版本号的模块: npm config set save-exact true

 

package-lock.json

npm 5.0新增特性。package-lock.json is automatically generated for any operations where npm modifies either the node_modules tree, or package.json. It describes the exact tree that was generated, such that subsequent installs are able to generate identical trees, regardless of intermediate dependency updates.若是package.json中使用了~或^指定版本,在从新npm i时会安装可用的最新版本,同时package-lock.json也会改变。可是若是以前的版本固定,package-lock.json也会固定。
It stores an exact, versioned dependency(including nested dependencies) tree rather than using starred versioning like package.json itself (e.g. 1.0.*). This means you can guarantee the dependencies for other developers or prod releases, etc. It also has a mechanism to lock the tree but generally will regenerate if package.json changes.
This is intended to lock down your full dependency tree. Let's say typescript v2.4.1 requires widget ~v1.0.0. When you npm install it grabs widget v1.0.0. Later on your fellow developer (or CI build) does an npm install and gets typescript v2.4.1 but widget has been updated to widget v1.0.1. Now your node module are out of sync. This is what package-lock.json prevents.(控制嵌套依赖包的版本)
忽略项目开发过程当中有些依赖已经发生的更新而锁定当前项目全部依赖包的版本号,避免后来者新拉项目时因从新安装的依赖包版本不一样而出现bug。(同事甲:为何个人电脑上是正常的?!) 
相关文章
相关标签/搜索