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的例子:
"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进行处理
}
"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命令
参考资料: