如何使用 package.json ——所有 Node.js 项目或 npm 包的核心
package.json 文件是所有 Node.js 项目和 npm 包的枢纽, 和 HTML 文档中的 <head> 区域用来描述网页的配置信息(元数据)一样,它存储项目的相关信息。 它由单个 JSON 对象组成,并以键值对的形式存储项目信息, 且至少包含两个必填字段:“name”和“version”——但是最好提供有关项目的其他信息,这将对用户或者维护者有所帮助。
如果能找到项目的文件树,那么可以在文件树的最外层找到 package.json, 在接下来的几个挑战中将完善这个文件。
在这个文件中最常见的信息之一是 author 字段, 它说明了项目的创建者,它可以是字符串,也可以是带有联系人详细信息的对象。 对于较大的项目,建议使用对象;但是在我们的项目中,一个简单的字符串就够了,比如下面的例子:
"author": "Jane Doe",
在项目的 package.json 文件的 author 键中添加你的名字。
{
"author": "corn6",
"name": "fcc-learn-npm-package-json",
"dependencies": {
"express": "^4.14.0"
},
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"repository": {
"type": "git",
"url": "https://idontknow/todo.git"
}
}
给 package.json 添加描述
一个好的 package.json 文件的下一部分就是 description 字段——简短精悍的的项目描述。
如果你计划将来把这个包发布到 npm,请注意 description 字段的作用是告知用户这个包的用途,这样用户就可以决定是否要安装你发布的包。 然而,这并不是使用描述的唯一场景:它也是一种很好的总结项目的方式, 可以帮助其它开发者、维护者甚至自己在未来快速地了解项目,对于任何一个 Node.js 项目来说都非常重要。
无论项目计划是什么,都建议使用描述。 类似这样:
"description": "A project that does something awesome",
给 package.json 添加关键词
在 keywords 字段中可以使用相关的关键字描述项目。 下面是一个示例:
"keywords": [ "descriptive", "related", "words" ],
正如你所见的,这个字段的结构是一个由双引号字符串组成的数组。
给 package.json 添加许可证
license 字段将告知用户允许他们拿这个项目干什么。
开源项目常见的协议有 MIT 和 BSD 等。 许可证信息并不是必须的。 大多数国家的版权法会默认让你拥有自己创作的作品的所有权。 但是,明确说明用户可以做什么和不能做什么会是一个很好的做法。 这里有一个 license 字段的例子:
"license": "MIT",
给 package.json 添加版本号
version 是 package.json 文件中必填字段之一, 这个字段描述了当前项目的版本, 下面是一个示例:
"version": "1.2.0",
使用 npm 的外部包扩展项目
强大的依赖管理特性是使用包管理器的最大原因之一。 每当在新的计算机上开始一个项目时,无需手动,npm 会自动安装所有的依赖项。 但是 npm 如何准确地知道项目需要哪些依赖呢? 来看看 package.json 文件中 dependencies 这一部分。
在这部分,你的项目需要按照下面这种格式来存储依赖包:
"dependencies": {
"package-name": "version",
"express": "4.14.0"
}
通过语义化版本来管理 npm 依赖关系
在 package.json 文件的依赖项中,npm 包的 Versions 遵循语义化版本(SemVer,Semantic Versioning),它是一种旨在使管理依赖项更加容易的软件版本控制的行业标准。 在 npm 上发布的库、框架或其它工具都应该使用语义化版本,以便让用户清晰地知道如果项目升级将带来哪些改变。
在使用外部依赖项(大多数情况都是这样)进行软件开发时,了解语义化版本会很有用。 这些数字保存着项目的偶然发生的破坏性改变,不会让人对项目昨天还正常,今天却无法运行而百思不解。 根据官网,这是语义化版本的工作方式:
"package": "MAJOR.MINOR.PATCH"
当做了不兼容的 API 修改,应该增加主版本号(MAJOR); 当新增了向下兼容的新功能时,应该增加次版本号(MINOR); 当修复了向下兼容的 bug 时,应该增加修订号(PATCH)。 这意味着修订号是用来修复错误的,次版本号则是添加了新功能,但它们都没有破坏之前的功能。 主版本号(MAJOR)是添加了不兼容早期版本的更改。
用波浪号维持依赖项的最新修订号
在上一个挑战中,npm 只包含特定版本的依赖包。 如果想让项目各个部分保持相互兼容,锁定依赖包版本是一个行之有效的办法。 但是大多数情况下,我们并不希望错过依赖项的问题修复,因为它们通常包含重要的安全补丁,而且它们理论上也会兼容我们既有的代码。
可以在依赖项的版本号前加一个波浪号(~),以让 npm 依赖项更新到最新的修订版。 这里有一个允许升级到任何 1.3.x 的例子:
"package": "~1.3.8"
用脱字符(^)来使用依赖项的最新次要版本
和上一个挑战中我们学到的用波浪号来安装最新的修订版依赖一样,脱字符(^)也允许 npm 来安装功能更新。 它们的不同之处在于:脱字符允许次版本和修订版更新。
现在项目中的 moment 依赖包的版本应该是“~2.10.2”,这意味着 npm 可以安装最新的 2.10.x 版的 moment, 如果使用脱字符(^)来替换版本号的前缀,那么 npm 可以将 moment 升级安装到任何 2.x.x 的版本。
"package": "^1.3.8"
这会将依赖包更新到任意的 1.x.x 版本。
从依赖项中删除依赖包
已经尝试过一些通过项目 package.json 文件中依赖项管理依赖的方式了, 也添加了一些外部的依赖包到项目中,甚至通过一些特殊的字符比如波浪号或者脱字符来告诉 npm 想要的版本类型。
但是,如果想要删除不再需要的依赖包,该怎么办呢? 可能已经猜到了——只需要从依赖项中删除相应的键值对就行了。
同样的方法也适用于删除 package.json 中的其它字段。
Node.js
Node.js 是一个 JavaScript 运行时,它允许开发人员在 JavaScript 中写入后端(服务器侧)程序。
Node.js 有几个内置的模块——小型、独立的程序——来帮助实现这一点,一些核心模块包括像服务器一样运作的 HTTP 和文件系统,一个读取和修改文件的模块。
在上一组课程中,你学到了怎么从 npm下载和管理软件包。这些软件包是较小模块的集合,可以帮助你构建更大更复杂的程序。
Express 是一个轻量级的网络应用程序框架,是最受欢迎的 npm 软件包之一。Express 使为应用程序创建服务器和处理路由变得更容易。当用户访问某个端点例如 /blog 时,把人们引导到正确的页面。
启动一个 Express 服务
在 myApp.js 文件的前两行中,你可以看到创建一个 Express 应用对象很简单。
var express = require('express');
var app = express();
这个对象有几种方法,在后面的挑战中将学习到其中的许多部分。 一个基础的方法是 app.listen(port)。 它处于运行状态时告诉服务器监听指定的端口。 出于测试的原因,需要应用在后台运行,所以在 server.js 中已经添加了这个方法。
让我们在服务端输出第一个字符串! 在 Express 中,路由采用这种结构:app.METHOD(PATH, HANDLER), METHOD 是 http 请求方法的小写形式, PATH 是服务器上的相对路径(它可以是一个字符串,甚至可以是正则表达式), HANDLER 是匹配路由时 Express 调用的函数, 处理函数采用这种形式:function(req, res) {...},其中 req 是请求对象,res 是响应对象, 例如:
function(req, res) {
res.send('Response String');
}
将会响应一个字符串“Response String”。
当 GET 请求 /(根路由 )时,使用 app.get() 方法响应一个“Hello Express”字符串:
var express = require('express');
var app = express();
app.get("/", (req, res) => {
res.send("Hello Express");
});
module.exports = app;

以下是server.js
/******************************************************
* PLEASE DO NOT EDIT THIS FILE
* the verification process may break
* ***************************************************/
var bGround = require('fcc-express-bground');
var myApp = require('./myApp');
var express = require('express');
var app = express();
if (!process.env.DISABLE_XORIGIN) {
app.use(function(req, res, next) {
var allowedOrigins = ['https://narrow-plane.gomix.me', 'https://www.freecodecamp.com'];
var origin = req.headers.origin || '*';
if(!process.env.XORIG_RESTRICT || allowedOrigins.indexOf(origin) > -1){
console.log(origin);
res.setHeader('Access-Control-Allow-Origin', origin);
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
}
next();
});
}
var port = process.env.PORT || 3000;
bGround.setupBackgroundApp(app, myApp, __dirname).listen(port, function(){
bGround.log('Node is listening on port '+ port + '...')
});
/******************************************************
* PLEASE DO NOT EDIT THIS FILE
* the verification process may break
* ***************************************************/
提供 HTML 文件服务
通过 res.sendFile(path) 方法给请求响应一个文件, 可以把它放到路由处理 app.get('/', ...) 中。 在后台,这个方法会根据你想发送的文件的类型,设置适当的消息头信息来告诉浏览器如何处理它, 然后读取并发送文件, 此方法需要文件的绝对路径。 建议使用 Node. js 的全局变量 __dirname 来计算出这个文件的绝对路径:
absolutePath = __dirname + relativePath/file.ext
发送文件 /views/index.html 作为 / 的 GET 请求的响应。 如果实时查看应用,你会看到一个大的 HTML 标题(以及我们稍后将使用的表单……),目前它们还没有任何样式。
var express = require('express');
var app = express();
app.get("/", function(req, res) {
res.sendFile(__dirname + "/views/index.html");
});
module.exports = app;
提供静态资源服务
HTML 服务器通常有一个或多个用户可以访问的目录。 你可以将应用程序所需的静态资源 (样式表、脚本、图片) 放在那里。
在 Express 中可以使用中间件 express.static(path) 来设置此功能,它的参数 path 就是包含静态资源文件的绝对路径。
如果你不知道什么是中间件……别担心,我们将在后面详细讨论。 其实,中间件就是一个拦截路由处理方法并在里面添加一些信息的函数。 使用 app.use(path, middlewareFunction) 方法来加载一个中间件, 它的第一个参数 path 是可选的, 如果没设置第一个参数,那么所有的请求都会经过这个中间件处理。
使用 app.use() 为路径 /public 的请求安装 express.static() 中间件, 静态资源的绝对路径是 __dirname + /public。
现在应用应该能提供 CSS 样式表, 请注意, /public/style.css 文件被项目模板的 /views/index.html 引用, 首页应该更好看了。
app.use("/public", express.static(__dirname + "/public"));
在指定路由上提供 JSON 服务
HTML 服务器提供 HTML 服务,而 API 提供数据服务。 REST(REpresentational State Transfer)API 允许以简单的方式进行数据交换,对于客户端不必要知道服务器的细节。 客户只需要知道资源在哪里(URL),以及想执行的动作(动词)。 GET 动词常被用来获取无需修改的信息。 如今,网络上的移动数据首选格式是 JSON, 简而言之,JSON 是一种可以方便地用字符串表示 JavaScript 对象的方式,因此它很容易传输。
我们来创建一个简单的 API,创建一个路径为 /json 且返回数据是 JSON 格式的路由, 可以像之前那样用 app.get() 方法来做。 然后在路由处理部分使用 res.json() 方法,并传入一个对象作为参数, 这个方法会结束请求响应循环(request-response loop),然后返回数据。 原来,一个有效的 JavaScript 对象会转化为字符串,然后会设置适当的消息头来告诉浏览器:“这是一个 JSON 数据”,最后将数据返回给客户端。 一个有效的对象通常是这种结构:{key: data}, data 可以是数字、字符串、嵌套对象或数组, data 也可以是变量或者函数返回值,在这种情况下,它们先求值再转成字符串。
当向路由 /json 发送 GET 请求,将对象 {“message”: “Hello json”} 以 JSON 格式返回给客户端, 浏览器访问 your-app-url/json 时,应该在屏幕上看到这个消息。
app.get("/json", (req, res) => {
res.json({
message: "Hello json"
});
});
使用 .env 文件
.env 文件是一个用于将环境变量传给应用程序的隐藏文件, 这是一个除了开发者之外没人可以访问的私密文件,它可以用来存储你想保密或者隐藏的数据, 例如,它可以存储第三方服务的 API 密钥或者数据库 URI, 也可以使用它来存储配置选项, 通过设置配置选项,你可以改变应用程序的行为,而无需重写一些代码。
在应用程序中可以通过 process.env.VAR_NAME 访问到环境变量。 process.env 对象是 Node 程序中的一个全局对象,可以给这个变量传字符串。 习惯上,变量名全部大写,单词之间用下划线分隔。 .env 是一个 shell 文件,因此不需要用给变量名和值加引号。 还有一点需要注意,当你给变量赋值时等号两侧不能有空格,例如:VAR_NAME=value。 通常来讲,每一个变量定义会独占一行。
本文详细介绍了如何完善package.json文件,包括添加作者信息、描述、关键词、许可证、版本号,以及管理依赖和使用语义化版本。它是项目管理和协作的关键,不论你是新手还是老手,理解并优化它都能提升开发效率。
386

被折叠的 条评论
为什么被折叠?



