👈👈👈 欢迎点赞收藏关注哟
首先分享之前的所有文章 >>>> 😜😜😜
文章合集 : 🎁 juejin.cn/post/694164...
Github : 👉 github.com/black-ant
CASE 备份 : 👉 gitee.com/antblack/ca...
一. 前言
最近在研究新的东西,难免用到了一些前端的工具 ,所以这篇文章就产生了。
- 文章定位 : 这是一篇速通文 , 针对的是有其他程序领域的基础,但是没有接触或者接触得不深的伙伴。
- 文章内容 : 快速一览 Node.js 的种种特性和用法。
Node.js 是什么 ?
- 我们知道 JavaScript 是前端语言 , 它运行的介质通常在浏览器中 , 也就是客户端
- 而 Node.js 作用是让 JavaScript 运行在服务端的平台
- Node.js 不是一门独立的语言 ,也不算一个框架或者库
- 它
更像一套运行环境
,让 JS 脱离浏览器运行 ,并且可以和底层API发生交互
注意 :
- 自行安装 Node 环境 ,此处就不深入了
二. Node.js 基础
2.1 npm : Node 包管理器
❓ 首先第一个问题 ,Node.JS 的包是什么 ?
node.js 的包和模块属于抽象的关系 ,一个包中通常包含一些特定的功能 ,使用时可以直接引入包从而直接使用这些功能。
- 模块 : 文件和模块是一一对应的关系, 一个 node.js 文件就是一个模块
- 通过 require 来引入一个模块 :
require('http')
- 通过 require 来引入一个模块 :
- 包 : 包是模块更深一层的抽象,将某个独立的功能封装起来 ,进行发布
- 功能含义 :
引入某个包从而使用其中的模块
❓ 第二个问题 :npm 是怎么管理的
- npm(Node Package Manager)是 Node.js 默认的包管理工具
- 用于安装、卸载、更新和管理 Node.js 的第三方包
- npm 由 JavaScript 编写
就像大多数包管理工具一样 ,npm 同样区分 镜像库,私有库和公共注册表。基于不同的场景,可以将包上传到不同的环境中 。
以下是一些 npm 的常见命令 :
- 全局包 : 安装在系统范围内的 npm 包 ,可以在任何项目中使用这些包 ,不需要重新安装
- 项目包 : 只在该项目中使用,安装在项目 node_modules 目录中
java
// 安装包
- 基于名称安装 : npm install <package-name>
- 安装全局包 : npm install -g <package-name>
- 安装指定版本的包 : npm install <package-name>@<version>
// 卸载包
npm uninstall <package-name>
// 更新包
npm update <package-name>
- 强制重新安装 : npm update --force-reinstall <package-name>
// 查询包
- 查询指定名称的包 : npm info <package-name>
- 通过关键字查询 : npm search <keyword>
- 查询当前安装的包 : npm ls [<directory>]
- 查询包的版本号 :npm view <package-name> versions
// 运行
- 发布本地包 : npm publish <package-name>
- 运行项目脚本 :npm run <script-name>
- 初始化项目 : npm init
2.2 常规的 Node.js 的结构
java
project-root/
├── node_modules # node 项目依赖包
├── src/ # 源代码目录件
├── test/ # 测试目录
├── package.json # 项目配置文件
├── package-lock.json # 依赖项锁定文件
└── README.md # 项目说明文件
- node_modules : 通过 install 或者 add 的方式安装包时 ,会将包及依赖安装到该目录中
- package.json : 包描述文件,用来描述包的信息(名称,版本,依赖项)
- package-lock.json : 记录了项目安装时所使用的所有依赖包及其确切版本号
- 主要为了避免依赖冲突
其中值得关注的是 package.json 的写法
java
{
"name": "my-app", // Node 应用的名称
"version": "0.1.0", // 应用的版本
"author": "作者",
"keywords": "关键字",
"private": true, // 指示 JavaScript 类成员或模块的可见性
"main": "main.js", // 主要的入口函数
"dependencies": {
// 项目所需的第三方软件包
},
"scripts": {
// 可从命令行运行的脚本
},
"eslintConfig": {
// ESLint 配置规则和环境
},
"browserslist": {
// 用于告知要支持哪些浏览器(及其版本)
}
}
常见的就是上面的 ,详情可以看官方文档 @ dev.nodejs.cn/learn/the-p...
2.3 Node.js 的组成结构
这里也引发了对 Node.js 性能的思考,Node 和大多数语言一样 ,都是由高层向系统调用的过程 :
- 高级语言 (JavaScript/Java) 👉 C/C++ 系统语言 👉 硬件接口
- 最上层的是 Node 标准库 ,主要是辅助 JS 开发 ,通过标准库可以调用下层的 API
- 下层最主要的当然还是 V8 ,其次就是 IO 引擎
- V8 引擎 : Google 开发的开源 JavaScript 引擎,用于执行 JavaScript 代码
- 可以实现即时编译 ,垃圾回收等复杂功能
- Libux / Libeio / Libev : 3 种不同的异步IO库,其中 Libev 是另外两个的基础库
- IOCP : Windows 操作系统提供的异步 I/O 机制 ,
- V8 引擎 : Google 开发的开源 JavaScript 引擎,用于执行 JavaScript 代码
- 除了这些 ,node 另外一大领域就是各种生态组件
- 比如数据库方面的 Redis ,MySQL
- 或者用于构建 Web 服务的 Express
三. Node.js 的常见使用
我们基于一个简单的案例来了解 Node 的定位 :
3.1 入门级使用
java
// 通过 Node.js 程序运行一个脚本
node helloworld.js
// 通过 Node.js 程序运行一段代码
node -e "console.log('Hello World');"
// 进入命令行执行
> node
> console.log('Hello World');
你就说像不像安装 JDK
或者 Python环境
运行脚本的模式吧。
3.2 进阶 : Web 服务器
java
// S1 : 初始化一个 Npm 项目
npm init
// -- 本质上是为了生成一个 package.json (前提是已经安装好了Node环境)
{
"name": "node-demo",
"version": "1.0.0",
"description": "This is Hello World",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
// S2 : 创建一个 index.js (也就是上面说的 main 主函数)
// - 其实能看到,这些都是特性,需要一个入口来进入整个项目
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write('<head><meta charset="utf-8"/></head>');
res.write('<h1>这是一个Node 项目</h1>');
res.write('<div>开启的Node端口为 3000</div>');
res.end('<p>我仅仅返回了一段 HTML 代码,但是它在前端正常进行展示</p>');
}).listen(3000);
console.log("HTTP server is listening at port 3000.");
- 这里并没有需要我们在 package.json 中专门引入什么 ,意味着 Web 服务是其本身自带的特性
- 返回的直接是 HTML 代码,基于浏览器的特性,这里可以直接展示
至此 ,一个简简单单平平无奇的 Node 项目就搭建好了
3.3 初级选手 : 为 Node 引入依赖
我们为 Node 引入一些复杂的依赖包 ,从而实现更高级的功能 :
- 这里演示使用的是 chokidar ,这是一个文件系统工具 ,可以监听到系统文件的变动
node
// S1 : 在项目中进行安装
npm install chokidar
从这里可以看到这些信息 :
- 安装完成后 ,会自动在 package.json 中为我们添加 dependencies
- 在项目 node_modules 中会添加对应的依赖 (注意,这里能看出全局依赖并没有在这个文件夹下面)
- 引入的依赖其实也是一个 node 项目的传统结构
js
// S2 : 编译相关的代码
const chokidar = require('chokidar');
// 当前目录
chokidar.watch('.').on('all', (event, path) => {
console.log(event, path);
});
- 这里可以看到 ,数据就已经打印出来了,之前的操作历史清清楚楚
3.4 高级使用 :更加多姿多彩的用法
- 用法太多了,出于整个系列的目的性,这里只展示 electron 的使用
java
// S1 : 整体没有区别,引入一个 eletron 组件
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "应用描述",
"main": "main.js",
"scripts": {
"start": "electron .",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Ant-Black",
"license": "ISC",
"devDependencies": {
"electron": "^29.1.6"
}
}
// S2 : 构建 main.js 里面的代码
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
const path = require('path')
app.whenReady().then(() => {
// 创建一个 BrowserWindow 和 Login 页面绑定
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
nodeIntegration: true,
contextIsolation: false
},
})
win.webContents.openDevTools()
win.loadFile("login.html");
})
其实很简单不是。
四. Node.js 的基础原理
4.1 Node.js 在服务器里面的定位
当 Node.js 作为 Web 服务器的时候 ,它是和浏览器直接交互的。
我们来以 Java 这个典型的后端Web语言为例 :
- Java : 浏览器
→
HTTP 服务器(Tomcat)→
运行在服务器上面的 Java 应用 - Node : 浏览器
→
Node
因为一个典型的 Java 应用是不会直接对外暴露 Web 能力 ,其底层还是通过 Web 服务器进行端口的开放。
Node 就像一个结合体
,它既包含了 运行环境
,又在其上直接集成了 Web 服务器
.
4.2 Node.js 的一些特性点
- 单线程 + 异步 I/O 模型
- 事件驱动
虽然我前端不熟 ,但是技术方案这一块都是通用的,区别的无非就是实现而已。我来简单解读一下这些特性 :
单线程 + 异步 I/O 模型
这东西说白了就快,它减少了多线程 线程切换 损耗的资源,同时通过 事件队列
避免了线程的阻塞。
这一套使用最有名的应该是 Redis
, 高并发轻轻松松。
看到一张总结的很好的图片,这里引用一下 : 图片来源 @ Node.js开发指南
这里也简单展示下事件的使用:在很多高级组件里面能看到更加复杂的用法
java
// S1 : 准备了一个 EventEmitter 对象用于处理发送事件
var EventEmitter = require('events').EventEmitter;
var event = new EventEmitter();
// S2 : 做好事件的监听
event.on('hello_event', function() {
console.log('hello_event occured.');
});
// S3 : 发送一个事件
setTimeout(function() {
event.emit('hello_event');
}, 1000);
五. 经典案例 和 Demo
5.1 可以做什么
工具的最终目的还是面向业务和生产 , Node.js 主要可以实现以下场景 :
搭建网站 :
以 React 为例 ,React 在 Node.js 中部署完成后 ,可以通过指定端口进行访问。
其本质上还是在浏览器中访问 HTML 文件,与常规 Nginx 部署最大的区别在于一个是静态文件,一个是在 Node.js 服务器生成 HTML 后进行返回。
搭建 Web 后端应用
这就和常规的后端语言差不多了 ,也就是常规的 增删改查 ,例如访问 Redis ,访问 MongoDB 等等。
以及可以实现一些更复杂的功能,比如构建特定功能的应用 : Web Socket 服务器
搭建桌面端
这也是我学习这一块的主要原因 ,我们可以基于 Electron 构建一个桌面端 。
对比其他的桌面端语言,这种方式固然在性能和体积等访问有诸多不足,但是适用性和美观上还是很强的。
对于一些对性能要求不高的情况下 ,是一个不错的选择。
搭建功能性工具
剩下的一大场景就是对某个功能进行实现的工具, 这些工具不复杂,但是很实用。
例如 : JS 编译器 ,命令行工具 ,单元测试工具
总结
这一篇主要是对 Node 进行一个大概的了解。阅读的时候顺便记录了一下,可能会有遗漏的地方。
以一个后端老鸟的角度来说 ,Node 更像一个结合体 , 它本身像运行环境一样保证了 JS 代码的运行 , 又在其上层封装了一层 Web 的能力。
这和其本身的定位有一定关系,前端最重要的领域还是在网站,我使用它还是看中它门槛相对较低,界面美观。
如果是纯脚本实现复杂功能,我可能会选择 Python ,服务端会考虑使用 Java 。
侧重不同 ,所以确实没必要做的那么纯粹。
参考文档
Node.js开发指南