Home

Awesome

npm基础知识总结

1.我们的模块都会在系统下缓存

C:\Users\Administrator\AppData\Roaming\npm-cache\registry.npmjs.org

在这个目录下的每一个文件都会有一个.cache.json,其中文件有Etag与lastModified这两个HTTP头,其都是为了保证防止多于的http请求而产生的。

"_etag":"W/\"58c793d3-7259\"",
"_lastModified":"Tue, 14 Mar 2017 06:55:15 GMT"

你可以查看npm cache配置。至于文件缓存目录的获取你可以通过如下命令查看:

npm config get cache//缓存的相关文件

对于一些不是很关键的操作(比如npm search或npm view),npm会先查看.cache.json里面的模块最近更新时间,跟当前时间的差距,是不是在可接受的范围之内。如果是的,就不再向远程仓库发出请求,而是直接返回.cache.json的数据。上面第一个参数很好理解就是服务器发送过来的,客户端请求会发送ifModifiedSince,而第二个头会通过ifNoneMatch发送到服务器端,通过这两个请求头可以判断文件是否已经发生了修改,即缓存内容是否依然有效

2.我们的package.json中的内容都是可以通过process.env来获取到的

假如我们的package.json的内容如下:

{
  "name": "yo-my",
  "private": true,
  "version": "0.0.1",
  "description": "yo-my - Generated by generator-react-webpack",
  "main": "src/index.js",
  "entry": {
    "index": "./src/client.js"
  },
  "scripts": {
    "eslint": "eslint ./src",
    "dist": "wcf --dev  --config ./cfg/dist.js --htmlTemplate ./src/index.html",
    "devServer": "wcf --dev --devServer --config ./cfg/devServer.js --htmlTemplate ./src/index.html",
    "watch": "wcf --dev --watch --config ./cfg/watch.js --htmlTemplate ./src/index.html",
    "test": "cross-env NODE_ENV=test karma start",
    "test:watch": "cross-env NODE_ENV=test karma start --autoWatch=true --singleRun=false --reporters=mocha,coverage"
  },
  "repository": "",
  "keywords": [],
  "author": "Your name here",
  "devDependencies": {
    "babel-eslint": "^7.2.1",
    "babel-plugin-transform-object-rest-spread": "^6.23.0",
    "eslint": "^3.0.0",
    "eslint-config-airbnb": "^13.0.0",
    "eslint-loader": "^1.3.0",
    "eslint-plugin-import": "^2.2.0",
    "eslint-plugin-jsx-a11y": "^4.0.0",
    "eslint-plugin-react": "^6.0.0",
    "karma": "^1.0.0",
    "karma-chai": "^0.1.0",
    "karma-coverage": "^1.0.0",
    "karma-junit-reporter": "^1.0.0",
    "karma-mocha": "^1.0.1",
    "karma-mocha-reporter": "^2.0.3",
    "karma-phantomjs-launcher": "^1.0.4",
    "karma-sinon": "^1.0.5",
    "karma-sourcemap-loader": "^0.3.7",
    "karma-webpack": "^1.8.1",
    "mocha": "^3.0.0",
    "phantomjs-prebuilt": "^2.1.7",
    "react-addons-test-utils": "^15.0.0-rc.2",
    "rimraf": "^2.5.2",
    "sinon": "^1.17.3",
    "webpack": "^2.2.0",
    "webpack-dev-server": "^2.4.1"
  },
  "dependencies": {
    "normalize.css": "^4.0.0",
    "react-dom": "^15.0.2",
    "react": "^15.3.0",
    "enzyme": "^2.8.0",
    "webpackcc": "^2.0.20",
    "react-hot-loader": "^3.0.0-beta.6",
    "cross-env": "^3.1.0"
  }
}

当你执行"npm run dist"的时候,在"./cfg/dist.js"文件中你就可以通过process.env获取到所有的关于该package的信息。

2.1 npm_package_开头的配置信息

 npm_package_author_name: 'Your name here',
 //对应于package.json中的  "author": "Your name here"
 npm_package_dependencies_cross_env: '^3.1.0',
 npm_package_dependencies_enzyme: '^2.8.0',
 npm_package_dependencies_normalize_css: '^4.0.0',
 npm_package_dependencies_react: '^15.3.0',
 npm_package_dependencies_react_dom: '^15.0.2',
 npm_package_dependencies_react_hot_loader: '^3.0.0-beta.6',
 npm_package_dependencies_webpackcc: '^2.0.20',
 npm_package_description: 'yo-my - Generated by generator-react-webpack',
 npm_package_devDependencies_babel_eslint: '^7.2.1',
 npm_package_devDependencies_babel_plugin_transform_object_rest_spread: '^6.23.
',
 npm_package_devDependencies_eslint: '^3.0.0',
 npm_package_devDependencies_eslint_config_airbnb: '^13.0.0',
 npm_package_devDependencies_eslint_loader: '^1.3.0',
 npm_package_devDependencies_eslint_plugin_import: '^2.2.0',
 npm_package_devDependencies_eslint_plugin_jsx_a11y: '^4.0.0',
 npm_package_devDependencies_eslint_plugin_react: '^6.0.0',
 npm_package_devDependencies_karma: '^1.0.0',
 npm_package_devDependencies_karma_chai: '^0.1.0',
 npm_package_devDependencies_karma_coverage: '^1.0.0',
 npm_package_devDependencies_karma_junit_reporter: '^1.0.0',
 npm_package_devDependencies_karma_mocha: '^1.0.1',
 npm_package_devDependencies_karma_mocha_reporter: '^2.0.3',
 npm_package_devDependencies_karma_phantomjs_launcher: '^1.0.4',
 npm_package_devDependencies_karma_sinon: '^1.0.5',
 npm_package_devDependencies_karma_sourcemap_loader: '^0.3.7',
 npm_package_devDependencies_karma_webpack: '^1.8.1',
 npm_package_devDependencies_mocha: '^3.0.0',
 npm_package_devDependencies_phantomjs_prebuilt: '^2.1.7',
 npm_package_devDependencies_react_addons_test_utils: '^15.0.0-rc.2',
 npm_package_devDependencies_rimraf: '^2.5.2',
 npm_package_devDependencies_sinon: '^1.17.3',
 npm_package_devDependencies_webpack: '^2.2.0',
 npm_package_devDependencies_webpack_dev_server: '^2.4.1',
 //对应于package.json中的devDependencies,dependencies
 npm_package_entry_index: './src/client.js',
 //对应于package.json中的entry
 npm_package_main: 'src/index.js',
 //对应于package.json中的main
 npm_package_name: 'yo-my',
 //对应于package.json中的"name"
 npm_package_private: 'true',
 //对应于package.json中的"private",如果设置为true那么npm会拒绝发布这个库
 npm_package_readmeFilename: 'README.md',
 //对应于package.json中的readme
 npm_package_repository: undefined,
 //对应于package.json中的repository
 npm_package_scripts_devServer: 'wcf --dev --devServer --config ./cfg/devServer
js --htmlTemplate ./src/index.html',
 npm_package_scripts_dist: 'wcf --dev  --config ./cfg/dist.js --htmlTemplate ./
rc/index.html',
 npm_package_scripts_eslint: 'eslint ./src',
 npm_package_scripts_test: 'cross-env NODE_ENV=test karma start',
 npm_package_scripts_test_watch: 'cross-env NODE_ENV=test karma start --autoWat
h=true --singleRun=false --reporters=mocha,coverage',
 npm_package_scripts_watch: 'wcf --dev --watch --config ./cfg/watch.js --htmlTe
plate ./src/index.html',
//对应于package.json中的scripts部分
 npm_package_version: '0.0.1',
 //对应于package.json中的version字段

通过上面的内容你可以清楚的知道:对于如entry:{index:""}都会直接被转化为entry_index这种类型,然后在前面添加npm_package,对于其他的如devDependencies或者dependencies也是一样的规则~

同时如果在scripts中有"test:watch",那么也会被转化为"test_watch"~

2.2 npm_config_开头的配置信息

2.2.1 Command line的方式

我们也可以通过command line的方式来传递环境变量,如--foo bar或者--foo,前者设置foo为"bar",后者设置为true

2.2.2 环境变量的方式

哪些以npm_config_开头的环境变量都会被解析为配置参数。例如,npm_config_foo=bar将会设置foo这个配置信息的值为bar。哪些没有被设置为特定值的环境变量配置都会被设置为true。同时,环境变量本身是大小写不敏感的,因此NPM_CONFIG_FOO=bar和上面的结果是一样的。同时你要注意,npm-scripts会设置自己的环境变量,而Node会更加倾向于接受小写的环境变量。

2.2.3 .npmrc的方式

该文件有四个相关的问题,分别为:

(1)每一个项目都有的一个配置文件,即/path/to/my/project/.npmrc,也就是你的项目的根目录。举一个例子,如果你的package.json具有"config"这个key,那么其可以轻易地被CLI中的命令覆盖掉。假如package.json为:

{ "name" : "foo"
, "config" : { "port" : "8080" }
, "scripts" : { "start" : "node server.js" } }

同时我们的server.js内容为:

http.createServer(...).listen(process.env.npm_package_config_port)

那么用户可以通过下面的CLI命令来设置端口为80:

npm config set foo:port 80

(2)每一个用户都有的一个配置文件,默认是"$HOME/.npmrc",你也可以通过CLI的配置,即"userconfig",或者环境变量"$NPM_CONFIG_USERCONFIG"。你可以在git bash中输入"$HOME/.npmrc"可以看到你自己的.npmrc,如下:

registry.npmjs.org/:_authToken=241af75d-680d-46e7-8df9-042dccdb6cb3
prefix=C:\Users\Administrator\AppData\Roaming\npm
//这里的prefix就是我的npm的安装路径

(3)全局的配置文件,默认是$PREFIX/etc/npmrc;你也可以通过CLI的--globalconfig或者环境变量$NPM_CONFIG_GLOBALCONFIG来设置

(4)npm内置的配置文件,路径为"/path/to/npm/npmrc"。细节请查看npmrc文件

2.2.4 .npmrc具体配置信息
 npm_config_access: undefined,
 //发布的包是否可以被查看或者安装,如果要设置为restricted那么必须付费,查看https://docs.npmjs.com/cli/access,默认是restricted,可以通过npm access来设定
 npm_config_also: undefined,
 //其值可以是"dev"或者"development",默认是null。当值为"dev"或者"development",执行npm shrinkwrap,npm outdated,npm update,那么其相当于--dev
 npm_config_always_auth: undefined,
 //默认是false,强制npm每次获取注册的库的时候都要求授权,即使是GET请求
 npm_config_argv: '{"remain":[],"cooked":["run","dist"],"original":["run","dist
]}',
 npm_config_bin_links: 'true',
 //如果该包可以执行,让npm为该包产生symlink,在windows上指的是cmd
 npm_config_browser: undefined,
 //为npm docs命令(该命令用于打开某一个包的readme文件)设定一个打开readme的浏览器
 npm_config_ca: undefined,
 //默认是npm CA中心。CA签名的证书用于以SSL连接的方式访问某一个库
 npm_config_cache: 'C:\\Users\\Administrator\\AppData\\Roaming\\npm-cache',
 //指的是npm的缓存目录,windows下为%AppData%\npm-cache,可以通过npm config get cache获取
 npm_config_cache_lock_retries: '10',
 //获取缓存中某一个加锁文件最大的尝试次数
 npm_config_cache_lock_stale: '60000',
 //过了多少毫秒后才需要判断该缓存文件是否过期
 npm_config_cache_lock_wait: '10000',
 //缓存文件过期需要等待多少毫秒
 npm_config_cache_max: 'Infinity',
 //等待多少秒后重新检测缓存中注册的文件,默认是不会主动删除缓存中注册的文件的,即Infinity。注意:除非你明确执行npm cache clean,否则不会清楚缓存数据。
 npm_config_cache_min: '10',
 //缓存中的数据最少保存的秒数,超过指定的秒数就会检测该库是否已经更新。注意:除非你明确执行npm cache clean,否则不会清除缓存数据。(具体见下面分析)
 npm_config_cafile: undefined,
 //包含一个或者多个CA签名的文件路径
 npm_config_cert: undefined,
 //当访问一个公共的库的时候需要携带的客户端证书,该配置不是一个文件
 npm_config_color: 'true',
 //布尔值或者'always',是否显示颜色
 npm_config_depth: 'Infinity',
 //当执行npm ls/npm cache ls/npm outdated时候递归查看文件的深度
 npm_config_description: 'true',
 //npm search显示的description信息,你可以试一下npm search webpackcc
 npm_config_dev: undefined,
 //是否在安装该包的时候一起安装devDependencies
 npm_config_dry_run: undefined,
 //显示你是否需要npm对你的包产生修改,而只是需要npm输出它到底做了什么手脚
 npm_config_editor: 'notepad.exe',
 //编辑器环境变量,Posix上是'vi'
 npm_config_engine_strict: undefined,
 //如果设置为true。那么npm就会拒绝安装那些与当前npm版本不兼容的包
 npm_config_fetch_retries: '2',
 //安装某一个包的时候尝试的次数
 npm_config_fetch_retry_factor: '10',
 //重新安装某一个包的使用有用
 npm_config_fetch_retry_maxtimeout: '60000',
  //重新安装某一个包的使用有用
 npm_config_fetch_retry_mintimeout: '10000',
  //重新安装某一个包的使用有用
 npm_config_force: undefined,
 //生命周期相关的script如果失败不会退出;当获取一个库的时候不从cache中获取;如果安装的不是npm的模块也不进行检测;可以发布一个以前已经发布的版本
 npm_config_git: 'git',
 //git命令执行时候运行的程序,如果安装了git使用git,否则就是设置一个Git二进制文件的完整路径
 npm_config_git_tag_version: 'true',
 //当执行npm version的时候是否打一个tag
 npm_config_global: undefined,
 //我们的包都会被安装在prefix指定的文件夹内,而不是当前的工作目录。也就是{prefix}/lib/node_modules,而二进制文件被链接到{prefix}/bin。
 npm_config_globalconfig: 'C:\\Users\\Administrator\\AppData\\Roaming\\npm\\etc
\npmrc',
//从那个文件来读取全局配置文件,默认{prefix}/etc/npmrc
 npm_config_globalignorefile: 'C:\\Users\\Administrator\\AppData\\Roaming\\npm\
etc\\npmignore',
//忽略的文件配置
 npm_config_global_style: undefined,
 //是否使用全局的node_modules架构来安装本地的模块。此时,只有直接的依赖会在node_modules中显示,其他的模块都是在依赖的模块的node_modules文件夹。此时会产生很多重复模块
 npm_config_group: undefined,
 //当以root用户来执行包中的script文件的时候使用什么组,默认为用户的GID。http://blog.chinaunix.net/uid-30126070-id-5073564.html
 npm_config_heading: 'npm',
 //默认为"npm",开启调试log输出
 npm_config_https_proxy: undefined,
 //为发出的请求设置代理,如果设置了HTTPS_PROXY or https_proxy or HTTP_PROXY or http_proxy等环境变量,那么代理设置会被请求库所处理。类型是URL
 npm_config_if_present: undefined,
 //如果设置为true,那么package.json的script部分(通过npm run运行的部分)不存在该script的时候不会抛出错误代码。当这个script可选的时候非常有用
 npm_config_ignore_scripts: undefined,
 //是否忽略package.json中的script部分
 npm_config_init_author_email: undefined,
 //npm init默认设置的用户的email
 npm_config_init_author_name: undefined,
//npm init默认设置的用户的用户名
 npm_config_init_author_url: undefined,
//npm init默认设置的用户的默认主页
 npm_config_init_license: 'ISC',
 //npm init默认设置的package的license
 npm_config_init_module: 'C:\\Users\\Administrator\\.npm-init.js',
 //npm init命令加载的模块,默认为~/.npm-init.js
 npm_config_init_version: '1.0.0',
 //默认版本
 npm_config_json: undefined,
 //是否应该输出JSON类型的数据,目前只有npm ls --json和npm search --json可用
 npm_config_key: undefined,
 //访问一个包的时候传递的客户端的私钥
 npm_config_legacy_bundling: undefined,
 //像npm1.4之前那样安装包,因此此时对于安装的包是不会去重的
 npm_config_link: undefined,
 //如果设置为true,那么本地安装的包将会链接到全局安装的包。这表示,本地的安装可能导致一些包安装到全局的空间。发生link的条件:这个包没有全局安装+全局安装的包和局部安装的包的版本一致。默认为false
 npm_config_local_address: undefined,
 //访问线上的包本机使用的IP地址
 npm_config_loglevel: 'warn',
 //默认是'warn',高于这个级别会输出
 npm_config_long: undefined,
 //在npm ls与npm search中显示扩展的信息
 npm_config_maxsockets: '50',
 //该配置会被传入到Http Agent中,表示每一个域名最多的连接数,是为了保护客户端程序
 npm_config_message: '%s',
 //npm version使用的提交信息,任何"%s"的信息将会被版本数替换
 npm_config_node_version: '6.9.5',
 //检测安装的模块的engines map所用的node版本
 npm_config_npat: undefined,
 npm_config_onload_script: undefined,
 //当npm加载完成的时候通过require加载的node模块,是一个文件路径
 npm_config_only: undefined,
 //当设置为"dev",'development'同时npm install执行的时候没有任何参数,那么只有devDependencies里面的模块会被安装。当设置为"dev",'development'同时运行npm ls,npm outdated,npm update,那么相当于传入--dev。如果设置为"prod"或者"production",同时npm install没有任何参数,那么只会安装dependencies里面的模块
 npm_config_optional: 'true',
 //尝试安装optionalDependencies 里面的模块,即使错误也不会影响整体的安装进度
 npm_config_parseable: undefined,
 npm_config_prefix: 'C:\\Users\\Administrator\\AppData\\Roaming\\npm',
 //全局安装模块的安装路径,如果在命令行输入,那么表示该路径下不能运行非全局的命令
 npm_config_production: undefined,
 //如果设置为true那么表示在"production"模式下运行。此时devDependencies 不会安装如果你运行npm install没有任何参数,同时该模式也会设置NODE_ENV设为"production"
 npm_config_progress: 'true',
 //如果设置为true,那么对于那些耗时的操作我们会显示的一个进度条,当然前提是process.stderr是TTY
 npm_config_proprietary_attribs: 'true',
 //是否展示所有者相关的属性,一般不要修改
 npm_config_proxy: undefined,
 npm_config_rebuild_bundle: 'true',
 //安装特定的包以后,重新构建打包的那些依赖
 npm_config_registry: 'https://registry.npmjs.org/',
 //Base URL of npm package registry, 默认为https://registry.npmjs.org/
 npm_config_rollback: 'true',
 //移除那些没有安装成功的包
 npm_config_save: undefined,
 //将安装的包保存到package.json的dependencies中。当和npm rm同时使用的时候,将会从dependencies中移除
 npm_config_save_bundle: undefined,
 //如果安装的时候指定了--save,--save-dev或者--save-optional,那么我们会同时将该模块添加到bundleDependencies,如果和npm rm同时使用,那么将会从bundleDependencies中移除
 npm_config_save_dev: undefined,
 //与上面一样
 npm_config_save_exact: undefined,
 //保存到Dependencies中的版本信息是完全精确的,而不是使用semver的range范围
 npm_config_save_optional: undefined,
 //optionalDependencies
 npm_config_save_prefix: '^',
 //默认是"^"
 npm_config_scope: undefined,
 //对于第一次登入私有库有帮助:npm login --scope=@organization --registry=registry.organization.com
 npm_config_searchexclude: undefined,
 //将搜寻的结果进行限制
 npm_config_searchopts: undefined,
 //传入到npm search的配置项
 npm_config_searchsort: 'name',
 npm_config_shell: 'C:\\Windows\\system32\\cmd.exe',
 //npm explore运行的shell命令
 npm_config_shrinkwrap: 'true',
 //如果设置为false,安装时候那么就会忽略npm-shrinkwrap.json文件
 npm_config_sign_git_tag: undefined,
 //If set to true, then the npm version command will tag the version using -s to add a signature.
 npm_config_strict_ssl: 'true',
 //当使用https访问某一个库的时候是否使用ssh key检验
 npm_config_tag: 'latest',
 //告诉npm安装的具体的tag
 npm_config_tag_version_prefix: 'v',
 //npm version修改版本的前缀
 npm_config_tmp: 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp',
 //保存临时文件和文件夹的位置
 npm_config_umask: '0000',
 //对于文件夹或者可执行文件给出的只为0777,其他文件是0666.默认是0755和0644
 npm_config_unicode: undefined,
 //如果设置为true,那么使用unicode,否则使用ascii
 npm_config_unsafe_perm: 'true',
 //如果设置为false,那么非root的用户安装包的时候会抛出错误。
 npm_config_usage: undefined,
 //更加简洁的help信息
 npm_config_user: undefined,
 //当以root用户运行package.json中的script的时候设置的UID(默认为"nobody")
 npm_config_userconfig: 'C:\\Users\\Administrator\\.npmrc',
 //用户级别的配置文件路径,默认是"~/.npmrc"
 npm_config_user_agent: 'npm/3.10.10 node/v6.9.5 win32 ia32',
 //设置User Agent请求头,默认是node/{process.version} {process.platform} {process.arch}
 npm_config_version: undefined,
 //如果设置为true,那么会打印npm版本然后成功退出
 npm_config_versions: undefined,
 //打印npm版本以及node的process.versions
 npm_config_viewer: 'browser',
 //查看的help信息的程序,如果设置为'html'那么就会以html的模式查看

下面我重点说几个配置:

(1) npm_config_production:

如果设置为true那么表示在"production"模式下运行。此时devDependencies 不会安装,如果你运行npm install没有任何参数;同时该模式也会设置NODE_ENV设为"production"

(2)npm_config_save_prefix

该配置的作用是:例如一个包的版本是1.2.3,默认情况下那么在package.json中就会被设置为'^1.2.3',这样,对于minor部分的更新依然是可以的。但是如果你设置了npm config set save-prefix="~",那么就会被设置为"~1.2.3",此时只允许最后一位数字的版本更新

(3)npm_config_shrinkwrap: 'true', 如果设置为false,安装时候那么就会忽略npm-shrinkwrap.json文件

(4) npm_config_sign_git_tag: undefined, If set to true, then the npm version command will tag the version using -s to add a signature.

(5) npm_config_tag: 'latest', 告诉npm安装的具体的tag

(6) npm_config_tag_version_prefix 默认是 'v',npm version修改版本的前缀

(7)npm_config_cache_min

运行npm install的时候,只会检查node_modules目录,而不会检查~/.npm目录。也就是说,如果一个模块在~/.npm下有压缩包,但是没有安装在node_modules目录中,npm 依然会从远程仓库下载一次新的压缩包。 这种行为固然可以保证总是取得最新的代码,但有时并不是我们想要的。最大的问题是,它会极大地影响安装速度。即使某个模块的压缩包就在缓存目录中,也要去远程仓库下载,这怎么可能不慢呢? 另外,有些场合没有网络(比如飞机上),但是你想安装的模块,明明就在缓存目录之中,这时也无法安装。为了解决这些问题,npm 提供了一个--cache-min参数,--cache-min参数指定一个时间(单位为分钟),只有超过这个时间的模块,才会从 registry 下载,用于从缓存目录安装模块,而判断是否时间就是通过我们第一点讲的.cache.json的_lastModified来判断的。

(8) npm_config_umask: '0000',

对于文件夹或者可执行文件给出的只为0777,其他文件是0666。默认是0755和0644

Linux中的权限有四个部分:

(1)setUid/setGid/粘着位(sticky)

(2)属主权限,即该文件所属的用户的权限

(3)组权限,用户所在的组的其他用户的权限

(4)其他用户的权限

但是对于umask来说我们有用的只是后三位,在bash中虽然可以带四位数字,但是第一个数字必须是0!对于后面的三位来说,每一位的都包含3个位数,所以每一位最大的值为111,也就是十进制的7!所以,如果该位的值为5,那么很显然就是101,而第一位表示read,第二位表示write,最后一位表示executable,因此如果umask为002,那么目录的权限的值是775,最后得到的就是rwx rwx r-x,而文件的权限就是664,也就是rw- rw- r--。而如果我们umask是022,那么目录的权限就是755,即rwx r-x r-x,而文件的权限为644,即rw- r-- r--!具体的计算可以参考这里 umask---设置权限掩码。注意,如果将umask设置为002,此时我们的umask也可以写成权限字符串的形式,即"--- --- -w-",此时权限想减也就很容易理解了!参照上面参考文件给出的一句话:chmod是设哪个位,哪么哪个位就有权限,而umask是设哪个位,则哪个位上就没权限

2.2.5 其他配置信息

 { ALLUSERSPROFILE: 'C:\\ProgramData',
 //all user profile
  APPDATA: 'C:\\Users\\Administrator\\AppData\\Roaming',
  'asl.log': 'Destination=file',
  CommonProgramFiles: 'C:\\Program Files\\Common Files',
  COMPUTERNAME: 'SC-201506221520',
  ComSpec: 'C:\\Windows\\system32\\cmd.exe',
  FP_NO_HOST_CHECK: 'NO',
  HOME: 'C:\\Users\\Administrator',
  HOMEDRIVE: 'C:',
  HOMEPATH: '\\Users\\Administrator',
  LOCALAPPDATA: 'C:\\Users\\Administrator\\AppData\\Local',
  LOGONSERVER: '\\\\SC-201506221520',
  MOZ_PLUGIN_PATH: 'C:\\Program Files\\Foxit Software\\Foxit Reader\\plugins\\',
  NODE: 'C:\\Program Files\\nodejs\\node.exe',
  NODE_EXE: 'C:\\Program Files\\nodejs\\\\node.exe',
  NPM_CLI_JS: 'C:\\Program Files\\nodejs\\\\node_modules\\npm\\bin\\npm-cli.js',
  npm_execpath: 'C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js',
  //npm command line所在的位置
  npm_lifecycle_event: 'dist',
  npm_lifecycle_script: 'wcf --dev  --config ./cfg/dist.js --htmlTemplate ./src/
index.html',
  npm_node_execpath: 'C:\\Program Files\\nodejs\\node.exe',
 NPM_PREFIX_NPM_CLI_JS: 'C:\\Users\\Administrator\\AppData\\Roaming\\npm\\node_
modules\\npm\\bin\\npm-cli.js',
  NUMBER_OF_PROCESSORS: '2',
  OS: 'Windows_NT',
  //操作系统
  Path: 'C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\node-gyp-bin;C:\\Use
rs\\Administrator\\Desktop\\yo-my\\node_modules\\.bin;C:\\Windows\\system32;C:\\
Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1
.0\\;C:\\Program Files\\nodejs\\;C:\\Program Files\\Git\\cmd;C:\\Users\\Administ
rator\\AppData\\Roaming\\npm',
  PATHEXT: '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JSE;.WSF;.WSH;.MSC',
  PROCESSOR_ARCHITECTURE: 'x86',
  PROCESSOR_IDENTIFIER: 'x86 Family 6 Model 23 Stepping 10, GenuineIntel',
  PROCESSOR_LEVEL: '6',
  PROCESSOR_REVISION: '170a',
  ProgramData: 'C:\\ProgramData',
  ProgramFiles: 'C:\\Program Files',
  PROMPT: '$P$G',
  PSModulePath: 'C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\Modules\\',
  PUBLIC: 'C:\\Users\\Public',
  SESSIONNAME: 'Console',
  SystemDrive: 'C:',
  SystemRoot: 'C:\\Windows',
  TEMP: 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp',
  TMP: 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp',
  USERDOMAIN: 'SC-201506221520',
  USERNAME: 'Administrator',
  USERPROFILE: 'C:\\Users\\Administrator',
  windir: 'C:\\Windows',
  windows_tracing_flags: '3',
  windows_tracing_logfile: 'C:\\BVTBin\\Tests\\installpackage\\csilogfile.log' }

3.package.json中的optionalDependencies/peerDependencies/bundleDependencies

3.1 optionalDependencies

如果一个依赖的模块没有被找到或者安装的时候失败了,你想要安装的过程继续进行,此时你可以将它放在这个字段中。这个字段和dependencies一样,指的是一些包的版本或者URL,唯一的区别在于,这个模块的安装失败不会导致整体安装进度的失败。但是,你的程序要为没有成功安装该依赖的模块而负责:

try {
  var foo = require('foo')
  var fooVersion = require('foo/package.json').version
} catch (er) {
  foo = null
}
if ( notGoodFooVersion(fooVersion) ) {
  foo = null
}
// .. then later in your program ..
if (foo) {
  foo.doFooThings()
}

如上面的例子就要求我们安装合适版本的foo,但是如果安装的版本不正确我们也不会报错!注意:在optionalDependencies中的配置会覆盖掉在dependencies中的同名的配置,因此我们最好将只放在一个位置。

3.2 peerDependencies

在一些情况下,你想要表达你的包和某一个工具或者库的兼容性,但是你不会直接通过require引入这个依赖的包。这经常发生在你想要引用某一个插件。因此,你的模块可以指定一个特定的接口,这个接口指定你依赖的包的信息,如:

{
  "name": "tea-latte",
  "version": "1.3.5",
  "peerDependencies": {
    "tea": "2.x"
  }
}

上面的配置表明,tea-latte可以同时和2.X版本的tea一起被安装。因此安装'tea-latte'的时候可以得到下面的结果:

├── tea-latte@1.3.5
└── tea@2.2.0

Npm1/NPM2会自动安装peerDependencies如果。在npm@3的时候不会自动安装,而是会给你一个warning,这样就可以避免npm1和npm2中的依赖地狱。注意:如果你安装了一个矛盾的版本将会导致错误,因此请确保你依赖的版本不仅仅是允许patch级别的升级!

3.3 bundleDependencies

这个参数可以是一系列包的数组,这些包在你发布自己的包的时候会一起打包成为一个文件。如果你想要本地保存你的包,或者在安装的时候只有一次文件下载,那么你可以将依赖的包放在这个配置项,同时执行npm pack

{
  "name": "awesome-web-framework",
  "version": "1.0.0",
  "bundledDependencies": [
    'renderized', 'super-streams'
  ]
}

如果你指定npm pack你就会得到"awesome-web-framework-1.0.0.tgz",而bundledDependencies中指定的包也会一起被打包进去

4.package.json中script部分深入讲解

我们看看如下的script例子:

 "scripts": {
    "release:major": "npm version prerelease && git push --follow-tags && npm publish --tag beta",
    "release:minor": "npm version prerelease && git push --follow-tags && npm publish --tag beta",
    "release:patch": "npm version prerelease && git push --follow-tags && npm publish --tag beta",
     "test": "cross-env NODE_ENV=test karma start",
    "test:watch": "cross-env NODE_ENV=test karma start --autoWatch=true --singleRun=false --reporters=mocha,coverage"
  },

其中npm version可以阅读这里。因为npm version每次都会产生一个tag,所以调用git push的时候要同时使用参数--follow-tags来将相应的tag推到远程的库,这是对git仓库的操作;同时我们也要调用npm publish --tag beta将我们的tag推送到npm上去

4.1 多个命令同时使用的方式

对于多个npm run命令使用&&来连接,而如cross-env来说,它只是设置NODE_ENV,其和其他命令之间不需要&&来分割

4.2 从eslint-config-airbnb-base展示生命周期

  "scripts": {
    "lint": "eslint .",
    "prepublish": "(eslint-find-rules --unused) && (npm test) && safe-publish-latest",
    //safe-publish-latest保证lastest这个tag指向正确
    "pretest": "npm run --silent lint",
    "test": "npm run --silent tests-only",
    "tests-only": "babel-tape-runner ./test/test-*.js",
    //Babel + Tape runner for your ESNext code,可以用于打包下一代的ES6
    "travis": "npm run --silent test"
  }

首先:babel-tape-runner可以用于打包下一代的ES代码;而上面eslint-find-rules传入的--unused参数表示不允许那些对程序没有影响的代码存在,如函数调用,new一个对象,赋值运算符等都表示程序允许的,因为他们都是会对程序产生影响的!,举个例子:

/*eslint no-unused-expressions: ["error", { "allowShortCircuit": true }]*/
a && b()
a() || (b = c)

此时对于{ "allowShortCircuit": true }这个规则来说是可以通过的,因为他是二元的,而其一个规则含有函数调用,而第二个规则同时含有函数调用与赋值运算符。但是对于下面三元的例子:

/*eslint no-unused-expressions: ["error", { "allowTernary": true }]*/
a ? b : 0
a ? b : c()

那么此时将不会通过检测,因为只有判断后面两个表达式都可以对程序的结果产生影响才行~!如下:

/*eslint no-unused-expressions: ["error", { "allowTernary": true }]*/
a ? b() : c()
a ? (b = c) : d()

下面我们来说说生命周期:即pre开头的生命周期在没有前缀的script前执行,post前缀最后执行,即pretest test posttest这样的顺序来执行。详见npm scripts

5.与package.json中script部分相关的一些工具

如果你耐心的读到这里,那么我下面会介绍一些很好用的与script执行相关的库。这个文章提出了下面的script对象:

{
  "name": "my-silly-app",
  "version": "1.2.3",
  "private": true,
  "dependencies": {
    "browserify": "~2.35.2",
    "uglifyjs": "~2.3.6"
  },
  "devDependencies": {
    "watchify": "~0.1.0",
    "catw": "~0.0.1",
    "tap": "~0.4.4"
  },
  "scripts": {
    "build-js": "browserify browser/main.js | uglifyjs -mc > static/bundle.js",
    //管道符先打包后压缩
    "build-css":  "cat static/pages/*.css tabs/*/*.css > static/bundle.css",
    //合并css,cat来自于shell命令行而非库。cat myfile1.txt myfile2.txt > myfile.txt
    "build": "npm run build-js && npm run build-css",
    //build的时候同时处理css与js
    "watch-js": "watchify browser/main.js -o static/bundle.js -dv",
    //加上-dv表示verbose显示更多打包信息,-o表示outputFile
    "watch-css": "catw static/pages/*.css tabs/*/*.css -o static/bundle.css -v",
    //和shell的cat命令一样,但是会监听文件变化,-o指定输出文件,而-v表示输出verbose
    "watch": "npm run watch-js & npm run watch-css",
    //注意:如果是`&`那么表示并行子任务,而`&&`表示序列化任务
    "start": "node server.js",
    "test": "tap test/*.js"
    //A TAP test framework for Node.js. Detail:http://www.node-tap.org/basics/
  }
}

同时作者也指出,如果你的&&连接比较多,那么建议使用批处理命令放在./bin目录下,可以是bash,node,或者perl书写。只要添加如下内容:

#!/bin/bash
(cd site/main; browserify browser/main.js | uglifyjs -mc > static/bundle.js)
(cd site/xyz; browserify browser.js > static/bundle.js)

而在package.json中进行如下配置:

"build-js": "bin/build.sh"

其中很多工具在参考文件中你也可以看到!下面给出几个script的例子:

nsp的例子

 "scripts": {
    "lint": "eslint . bin/nsp",
    "setup-offline": "curl -sS https://api.nodesecurity.io/advisories -o advisories.json",
    //curl是shell命令,表示从某一个server下载资源(支持离线)
    "test": "lab -a code -t 100 -I Reflect",
    //lab是一个nodejs的测试框架
    "nsp": "bin/nsp check",
    //nsp用于对node security platform中已知的安全问题进行处理
    "shrinkwrap": "npm shrinkwrap && shrinkydink"
    //其中shrinkydink用于对shrinkwrap.json进行处理
  }

webpack的例子

"scripts": {
    "test": "mocha --harmony --check-leaks",
    "travis:test": "npm run cover -- --report lcovonly",
    "travis:lint": "npm run lint-files && npm run nsp",
    "appveyor": "node --max_old_space_size=4096 node_modules\\mocha\\bin\\mocha --harmony",
    "build:examples": "cd examples && node buildAll.js",
    "pretest": "npm run lint-files",
    "lint-files": "npm run lint && npm run beautify-lint",
    "lint": "eslint lib bin hot buildin test/**/webpack.config.js test/binCases/**/test.js examples/**/webpack.config.js",
    "beautify-lint": "beautify-lint 'lib/**/*.js' 'hot/**/*.js' 'bin/**/*.js' 'benchmark/*.js' 'test/*.js'",
    "nsp": "nsp check --output summary",
    "cover": "node --harmony ./node_modules/.bin/istanbul cover -x '**/*.runtime.js' node_modules/mocha/bin/_mocha",
    "publish-patch": "npm run lint && npm run beautify-lint && mocha && npm version patch && git push && git push --tags && npm publish"
  }

大部分这里的代码都已经说过了,不过其中的beautify-lint以及nsp建议还是看一下!而且publish-patch都是采用&&来链接的,也就是顺序执行的!

React-Demo的例子:

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server --hot --progress --host 0.0.0.0 --port 8000 --config webpack.client.config.js",
    "server-build": "export NODE_ENV=prod; webpack -p --progress --config webpack.server.config.js",
    //export来自于shell命令,必须在git bash而不是cmd中运行,建议使用cross-env
    "client-build": "export NODE_ENV=prod; webpack -p --progress --config webpack.client.config.js",
    //export来自于shell命令,必须在git bash而不是cmd中运行,建议使用cross-env
    "start": "concurrently \"npm run client-build\" \"npm run server-build\" && node build/server.js"
  }

这里主要看一下concurrently与shell的export命令

参考资料:

npm cache

umask---设置权限掩码

npm 模块安装机制简介

Linux下用户组、文件权限详解

npm-shrinkwrap

Task automation with npm run

cat

nsp

beautify-link

常见node攻击

shell的export命令

concurrently