Node.js的定义
Node.js是一个开源、跨平台的跨平台的JavaScript运行环境,它基于的 Chrome V8 JavaScript 引擎构建,允许开发人员在浏览器之外运行JS代码,改变了Web开发中,JS只能在 “客户端” 运行的局面,让JS能够在服务器端进行编程。
为什么开发出Node.js以及Node.js的核心底层原理?
开发Node.js的目的是为了解决传统服务器的并发瓶颈。早期Web服务器采用多线程模型:每个请求独立分配一个独立线程处理。但是当并发请求量大时候,线程创建和切换的开销极大,导致服务器资源耗尽(即线程爆炸问题)。
为了解决高并发问题,Node.js被开发出来了。Node.js采用单线程事件循环 + 非阻塞I/O模型,一个线程可以同时处理数千个并发并发连接,大幅提升了吞吐量。
Node.js的设计:基于核心API(如fs.readFile、http等)均基于事件回调,强调开发者采用异步模式。
这里要了解这些核心API的用法方便日后的使用,建议查询官网,一篇文章难以讲述这些东西,跳转网址:点击这里,然后收藏该Node.js官网方便学习哟
之后,由于Web应用 开始向实时化发展(如在线协作等),且传统后端技术(PHP、Ruby)难以高效处理长连接和实时数据推送。Node.js进行了一些列的突破:内置了***、http模块,原生支持TCP、WebSocket等协议,简化实时通信实现。
核心特性
1.单线程与非阻塞I/O
- 传统服务器处理请求时通常为每个连接创建新线程,而Node.js采用单线程事件循环模型,通过**非阻塞I/O操作(如文件读写,网络请求)**避免线程阻塞,高效处理并发请求
- 例子:当Node.js处理一个数据库查询时,不会等待结果返回,而是继续处理其他请求,直到查询完成后通过回调函数处理结果。
2.跨平台
- 可运行于 Windows、macOS、Linux 等系统,支持通过 npm(Node Package Manager)管理海量第三方模块。
3.异步编程模型
- 依赖回调函数(Callback)、Promise、async/await 等方式处理异步操作,避免传统同步编程的阻塞问题。
Node.js模块化
Node.js 支持多种模块化规范,包括内置的***monJS模块、ES6模块(包含ECMAScript)、以及一些第三方模块。
模块化就是将代码分割成独立部分的开发模式,每个模块负责特定的功能。通过模块化,开发者可以提高代码的可读性、可维护性和复用性。
在Node.js中,每个文件都是独立的模块。模块之间的联系使用导入和导出的特定标准语法。
***monJs标准
标准语法:
- 导出:
module.exports = {} - 导入:
require('模块名或者路径')
特点:模块在首次加载执行并缓存,后续加载直接返回缓存结果
// 创建模块math.js
// 创建一个变量用const修饰,一个加法操作
const sum = (a, b) => a + b;
module.exports = {
// 对外属性名1:当前模块变量名
'Sum': sum,
// 对外属性名2:当前模块变量名
// ……
}
// 创建另一个模块app.js
// 导入另一个模块
const math = require('./math.js')
// 使用另一个模块的方法
console.log(math.Sum(1, 1));
// Node.js要在终端上执行指令哦:node app.js
ES6模块
标准语法:
- 导出:
export default {} - 导入:
import 变量名 from '模块名或路径'
注意:Node.js默认支持***monJs标准语法,如果要使用ECMAScript标准语法,在运行模块所在文件夹新建package.json,并设置{“type”:“module”}
特点:使用import和export关键字,静态导入(编译时候确定依赖)
// 创建math.js模块
// 导出单个成员
export const add = (a, b) => a + b;
// 导出默认值(只能有一个)
export default (r) => 3.14 * r * r;
// 创建app.js
//
import circleArea, { add } from './math.js';
console.log(add(2, 3)); // 5
console.log(circleArea(5)); // 78.5
***monJs和ES Modules的混合使用
Node.js允许两种模块共存,但需要注意:
// 在***monJS中引入ES模块
async function loadESModule() {
const esModule = await import('./es-module.mjs');
esModule.default(); // 调用默认导出
}
在ES模块中引入***monJS:
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const ***monjsModule = require('./***monjs-module.js');
注意:在使用路径导入的时候,但凡涉及到路径的问题,在前端建议用绝对路径(__dirname……)
***monJS和ES Modules的区别
npm——Node.js的标准管理包
npm起初是作为下载和管理Node.js包依赖方式,但其现在也已成为前端JavaScript中使用的工具
当一个项目需要安装对应的依赖时候,可以使用npm i 包的名字(记得在终端上下载);当你要运行一个具有package.json文件的项目时候,要在本地上运行项目,安装依赖时候只需要npm i 即可,它就会默认下载好这个项目所需要的依赖包
经常在下载依赖时候,会看到在安装指令后面添加的这些标志(图中加粗部分):
这是将包下载到对应的配置项当中,每个配置项的名字都承担着不同的功能,这样将包进行分类,也符合模块化开发的思想。
当你想要在自己创建的空文件夹当中获取package.json文件的话。需要使用命令npm init -y,这里获取package.json文件是为了记住当前项目下载了哪些依赖包。接下来,当我们需要某一功能的软件包时候,就需要使用下载的指令npm i 对应包名。被下载的东西会放到node_modules中(一个文件夹)。而我们npm下载过来的软件包对应的版本号记录会存放在package.json文件中,并且npm会自动生成一个package-lock.json文件(该文件作用是固化软件包版本。为什么要这么做?因为在开发项目过程中,若日后的项目需要修改功能,且用了最新的方法,那么有可能会导致项目出现一些差错,为了保证项目的稳定性,我们需要对项目所需要的依赖包进行一个固化,避免日后修改导致项目因为引入新的依赖包而产生未知的问题)
npm 下载的第三方包可以根据你的需要控制对应的版本,不必担心版本过高或者过低的问题。你可以使用对应的终端指令进行安装:npm install 包的名字@对应版本号
运行对应的package.json文件中的一些包时候,使用对应语法npm run 配置项名字,其中这个指令最常见的就是webpack的打包了。webpack这个东西可以说是前端工程化的重要一部分。这是必须要了解的内容,由于本篇幅讲解的是Node.js相关的东西,这里没有展开赘述,请诸君一定要学习这块知识。
上述内容是本人关于Node.js的一些理解,若是文中有其错谬之处,还望诸君不吝赐教,则某将不胜感激。