要了解node.js还得追溯到 2009 年,一个名叫 Ryan Dahl 的开发者,决定要创造一种全新的方式来运行 JavaScript —— 不是在浏览器里,而是在服务器端。他利用 Google 的 Chrome V8 引擎,创造了一个神奇的东西,叫做 Node.js。
-
随着 Node.js 的日渐流行,开发者们开始渴望一个简单的方式来分享和管理他们的代码。于是,Isaac Schlueter 创造了 npm (Node Package Manager),从此 Node.js 的世界变得更加丰富多彩。
-
2011年,10月11日:Node.js 0.6.0 版本发布,标志着 npm 成为了一个稳定的工具。这就像是一场盛大的派对,庆祝 Node.js 正式步入成熟阶段。
-
截至 2024 年,Node.js 已经成为一个成熟且备受推崇的平台,被广泛应用于各种场景,从简单的 Web 服务器到复杂的实时应用程序。npm 作为最大的软件注册中心,支持着全球数百万开发者的工作。
Node.js 的故事就像是一个不断发展的传奇,它不仅改变了 Web 开发的方式,也激励着一代又一代的开发者不断探索新的可能。
1. CommonJS 规范
1.1 CommonJS 规范
- 目的:CommonJS 规范旨在解决 JavaScript 在不同环境中运行时缺乏标准模块化支持的问题。
- 目标:使得 JavaScript 可以在服务器端以及其他非浏览器环境中运行,如 Node.js。
1.1.1 模块应用 – require
API
- 功能:
require
函数用于加载模块。 - 用法:
let md = require('./xxx.js');
,其中'./xxx.js'
是一个相对于当前文件的路径。
1.1.2 模块定义 – exports
- 概念:每个
.js
文件都被视为一个模块。 - 执行环境:每个模块都在自己的作用域中执行,这意味着模块之间的变量和函数是隔离的。
- 暴露成员:使用
exports
对象可以将模块内部的变量或函数暴露给外部。
1.1.3 模块标识
- 路径标识:模块可以通过路径标识找到,例如
'./path/to/module'
。 - 核心模块:由 Node.js 提供的标准模块,可以直接通过名称引用,例如
require('fs')
。 - 文件模块:用户自定义的模块,需要指定文件路径。
1.1.4 exports
和 module.exports
- 区别:
exports
是module.exports
的别名。默认情况下,module.exports
是一个空对象。 - 使用:可以通过
module.exports
替换整个对象,或者通过exports
添加成员。 - 示例:
// module.js module.exports = { name: 'John Doe' }; // 或者 exports.name = 'John Doe';
2. 包 (Package)
2.1 包结构
package.json
:包含包的元数据,如名称、版本、主入口文件等。package-lock.json
:记录依赖项的具体版本信息。bin
:存放可执行文件。lib
:存放源代码。doc
:文档。test
:单元测试。
2.2 包描述文件 (package.json
)
- 必需字段:
name
(包名)、version
(版本号)、main
(主入口文件)。 - 其他字段:
description
(描述)、keywords
(关键词)、license
(许可证类型)。
2.3 开发自己的包
- 步骤:
- 创建包文件夹。
- 初始化
package.json
文件:npm init -y
。 - 编写代码。
- 创建 README 文件。
- 发布到 npm:首先注册账号,然后通过
npm login
登录,最后使用npm publish
发布。
2.4 发布和管理包
- 发布:使用
npm publish
发布包到 npm。 - 删除:使用
npm unpublish
删除包,注意只有在发布后 72 小时内可以删除,并且 24 小时内不能发布相同版本。
示例
以下是一个简单的包示例:
package.json
{
"name": "szh-utils",
"version": "1.0.1",
"main": "index.js",
"description": "我的第一个工具包",
"keywords": ["szh", "format", "escape"],
"license": "ISC"
}
index.js
const dateFormat = require('./dateFormat');
const escape = require('./htmlEscape');
module.exports = {
...dateFormat,
...escape
};
dateFormat.js
module.exports = {
format: function(date, fmt) {
// 格式化日期的逻辑
}
};
htmlEscape.js
module.exports = {
escape: function(str) {
// 转义 HTML 字符串的逻辑
},
unescape: function(str) {
// 反转义 HTML 字符串的逻辑
}
};
以上就是如何简单的创建一个 Node.js 包,并通过 require
引入模块,以及如何使用 exports
和 module.exports
来暴露模块成员。
3. NPM (Node Package Manager)
NPM 是 Node.js 的包管理器,它不仅帮助 Node.js 社区管理和分发第三方模块,还为开发者提供了一个强大的工具集来处理模块的安装、更新、版本控制等问题。借助 NPM,Node.js 和第三方模块之间形成了一个良好的生态系统。
NPM 命令
-
npm – 帮助说明:
- 使用
npm help
获取帮助文档。 - 使用
npm help <command>
获取特定命令的帮助文档。
- 使用
-
npm search 包名 – 搜索模块包:
- 例如:
npm search lodash
。
- 例如:
-
npm remove/r 包名 --删除包:
- 例如:
npm uninstall lodash
。
- 例如:
-
npm install/i 包名 --save --安装并添加到依赖中:
- 例如:
npm install lodash --save
,这会将 lodash 添加到package.json
的dependencies
中。
- 例如:
-
npm install --根据 package.json 的配置下载所需要的包:
- 例如:
npm install
,这会在当前目录安装package.json
中列出的所有依赖。
- 例如:
-
npm install -g --全局安装包 (不止在项目里用的):
- 例如:
npm install -g express
,这会全局安装 express,使得可以在任何地方使用express
命令。
- 例如:
-
cnpm (淘宝镜像):
- 由于网络原因,有时候使用 NPM 默认的镜像源可能会比较慢,可以使用淘宝提供的 NPM 镜像
cnpm
。 - 安装 cnpm:
npm install -g cnpm --registry=https://registry.npm.taobao.org/
- 使用 cnpm 安装模块:
cnpm install lodash
- 切换 NPM 的镜像源:
- 查看当前的镜像源:
npm config get registry
- 设置为淘宝镜像源:
npm config set registry=https://registry.npm.taobao.org/
- 查看当前的镜像源:
- 由于网络原因,有时候使用 NPM 默认的镜像源可能会比较慢,可以使用淘宝提供的 NPM 镜像
-
nrm (NPM Registry Manager):
- 安装 nrm:
npm install -g nrm
- 查看可用的镜像源:
nrm ls
- 切换镜像源:
nrm use taobao
- 安装 nrm:
i5ting_toc
i5ting_toc
是一个将 Markdown 文档转换成带有目录的 HTML 页面的小工具。
- 安装 i5ting_toc:
npm install -g i5ting_toc
- 使用 i5ting_toc:
i5ting_toc -f <markdown-file-path> -o <output-file-path>
-f
参数指定 Markdown 文件的路径。-o
参数指定输出 HTML 文件的路径。
4. Node 搜索包的流程
当在 Node.js 中使用 require()
函数引入模块时,Node.js 会按照以下顺序搜索模块:
-
检查当前目录下的
node_modules
文件夹:- 如果找到了模块,则直接使用该模块。
- 如果没有找到,则继续向上一级目录查找
node_modules
文件夹。
-
递归地向上查找:
- 继续在父目录中查找
node_modules
文件夹,直到达到磁盘根目录。
- 继续在父目录中查找
-
如果仍未找到模块:
- Node.js 会尝试从 NPM 的中央仓库下载模块并安装在当前目录的
node_modules
文件夹中。
- Node.js 会尝试从 NPM 的中央仓库下载模块并安装在当前目录的
-
如果还是找不到:
- 抛出错误,表示未找到所需的模块。
通过这种方式,Node.js 确保了模块可以在项目的任何层级被正确地找到和使用。