package.json文件各字段的说明

全部用npm下载的包或者要上传至npm的模块都会有一个package.json文件,这个文件老是存在于模块(或者包)的根目录下,这个文件究竟是干吗的,如今就来作一个简要说明。html

1.package.json是什么

package.json是对下载的包或模块的描述信息,若是你要上传包到npm服务器也要有对应的模块说明。说明包括项目名称、版本、做者等等。package.json必须是一个严格的json格式,也就是说每个字段都要使用双引号,不管是key值仍是value值。vue

2.package.json字段说明

若是你要在npm上发布你的包,则package.json必需要有两个字段:name和version。其中name是包的名称,version是版本,对于这两个字段会有些约束。node

name:
1)名称不能超过214个字符
2)名称不能以点或者下划线开头
3)包的名称中不能包含大写字母
4)此名称将会成为URL的一部分,所以不能包含非URL的字符webpack

version:
1)版本号由主版本.此版本.补丁版本组成
2)版本必需要由node-semver解析,它与npm捆绑在一块儿做为依赖项。git

除了这两个字段外,还有其余对应的描述信息,下面对经常使用的字段作一个说明。github

description和keyword字段:这两个都是对应的描述信息,使用两个字段其中的某些内容进行搜索,能够在npm官网搜索到相关的包。不过这两个也有他们的区别,前者对应一个字符串,是对项目的一个简要说明,能够是一段描述的语句。然后者是一个字符串数组,就像写论文开头的关键字,咱们能够看一下vue项目的package.json,他里面的description和keyword以下:web

"description": "Reactive, component-oriented view layer for modern web interfaces.",
"keyword": [
    "vue"
]

能够看出,keyword字段必须是一个数组,即便数组中只有一个成员。另外,数组的成员要使用双引号,而数组的[]表示不须要双引号。npm

author字段:做者json

homePage字段:该包的官网地址数组

main字段:字段指定了程序的主入口文件,使用遵循CommonJS规范的require('moduleName')就会加载main字段指定的目录下的文件。这个字段的默认值是模块根目录下面的index.js,也就是说若是不指定main字段,在其余模块引用此模块会默认加载根目录下的index.js文件。

module字段:此字段指定了使用ES6的module模块引入该模块时加载的文件路径,即便用import 'xx' from './xx'所指定的路径。关于main字段和module字段的区别会在下面讲。

dependencies字段和devDependencies字段:这两个字段表示项目的依赖,前者表示项目正常运行(生产环境)时须要的依赖,后者指开发(开发环境)时所须要的依赖。开发环境和生产环境后面会作说明。这两个字段都是一个对象,对象的成员又指定的模块和对应的版本组成,表示依赖的模块和版本范围,注意是版本范围。

scripts字段:由脚本命令组成的字典,这些命令运行在包的各个生命周期中。这里的键是生命周期事件名,值是要运行的命令。好比下面的字段:

"script": {
    "install": "scripts/install.js",
    "postinstall" : "scripts/install.js",
    "uninstall" : "scripts/uninstall.js",
    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
    "build": "node build/build.js"
}

好比上面的install,在安装npm包时就应用后面的命令,即npm install会运行"script/install.js"命令。上面前三个是npm安装的生命周期,后面的几个就是自定义的命令了,好比使用npm run build运行build后面的命令。

engine字段:表示你的项目所运行的node版本。不指定engine字段,或者用*表示不限制node版本。

3.main字段和module字段

要理解main字段和module字段的不一样要先明白Tree-Shaking的机制,简单来说,Tree-Shaking的做用是将没有用到的代码所有过滤掉,可是在使用main字段做为入口导入的文件是遵循CommonJS规范的,也就是说暴露出的代码是做为export对象的一个属性,举例来说,若是暴露出一个add的方法做为export的属性,那在外部访问的时候若是使用"a"+"dd"的方式访问,打包工具是没法检测到是否使用了add这个方法,由于访问js的对象属性实在是太灵活了。若是使用ES6的module新特性,则不须要将其做为export对象的属性暴露出来的,并且ES6提出的module模块有更好的模块特性。这样的话打包的时候打包工具就可以检测到暴露出来的那些方法没有用到的,以便除去这些代码。

在package.json文档中并无提到module字段,那为何会出现module的字段,其实这是rollup最先提出的概念pkg.module。在早期不少npm包都是遵循CommonJS规范的,那时package.json长这样:

{
    "name": "xxx",
    "version": "1.0.0",
    "main": "lib/index.js"
}

在模块中使用require('xxx'),会将require的参数(xxx)做为一个包来进行查找,读取该目录下package.json文件,取得main字段指定的文件做为入口。但在ES6盛行以后有了module模块,而且这是官方标准,用起来更顺手,而CommonJS仍是传统格式,因此rollup利用ES6的module新特性,在打包的性能上有了一个很好的提升。

那既然main字段能够做为文件的入口,何须还要module字段的呢?缘由有如下两点:

1)按照约定发布在npm上面的包都是基于ES5规范的,并且一般咱们在使用babel工具将ES6编译为ES5的过程当中是将node_modules目录下的文件过滤掉的,也就是说node_modules目录下的文件将不会被babel工具编译,这是由于避免babel编译node_modules目录下的文件会极大提升编译速度。但若是咱们把main字段直接指向咱们用ES6语法写的源码上用户就要打开babel编译工具配置其编译node_modules目录下的文件。

2)若是用户开发的是node环境下的项目使用到咱们发布的基于ES6语法写的源码,可能连打包的步骤都不会有,而他的是node环境恰巧不支持ES6的语法,那代码就会报错。

所以main字段应该是指向编译后的ES5的代码,因而就应该出现一种新的字段解决这个问题,此时module字段就出现了,那如今的package.json长这样:

{
    "name": "xxx",
    "version": "1.0.0",
    "main": "lib/index.js",
    "module": "lib/index.esm.js" 
}

以上说明,咱们的main字段应该指向基于CommonJS规范而使用ES5语法写的源码,而moudle字段应该是指向遵循ES6模块规范的(也就是说使用ES6模块导出的,这样是为了可以让打包工具使用Tree-Shaking机制打包代码)而使用ES5语法编写的源码,这是为了不用户在使用babel编译工具屏蔽掉了node_modules目录中的文件。咱们能够看一下Vue源码中package.json中main和module字段指定的源码就是这样作的。

在webpack2.0版本以上打包过程当中,也逐渐开始支持module字段。在打包过程当中,若是遇到module字段会优先使用module字段表示的路径下的文件,若是module不存在,则用main字段表示的做为入口,并按照CommonJS的规范打包。

4.开发环境、生产环境和测试环境

开发环境就是开发时候的服务器,配置比较随意,会打开全部的错误提醒,尽可能让开发中的错误、bug等所有暴露出来方便调试。

测试环境通常是模拟真实运行环境,拷贝一份与真实环境相同的配置作各类测试,使其尽量多的暴露出程序的问题出来方便修改。

生产环境就是真实运行环境,是对外提供服务的,通常会关闭错误报告,打开错误日志,收集错误,方便修改bug。

这三个环境就是一个项目所经历的三个过程,开发 --> 测试 --> 上线

项目中咱们可使用process.env.NODE_ENV来取得当前的环境,开发环境返回字符串'development',生产环境返回字符串'production'

5.建立package.json

使用npm的init命令建立一个package.json文件。以后会逐行提示你输入每一个字段的值。固然也可输入npm init -y生成一个各字段默认值的packake.json文件

6.总结

本文讲了package.json文件的做用、其中个字段的说明以及如何生成package.json文件。其中还分析了package.json文件中main字段和module字段的不一样以及dependencies和devDependencies两个字段的区别。文中如有表述不妥或是知识点有误之处,欢迎留言指正批评!