Node.js 介绍
<h2 id="1nodejs-介绍">1.Node.js 介绍</h2><p>Node.js 是一个基于 Chrome V8 JavaScript 引擎构建的开源、跨平台的 JavaScript 运行时环境,它允许开发者使用 JavaScript 编写服务器端代码,而不仅仅局限于浏览器端</p>
<h2 id="2事件驱动">2.事件驱动</h2>
<h3 id="nodejs-使用事件循环机制处理并发请求其实就是两套-api同步blocking和异步non-blocking">Node.js 使用事件循环机制处理并发请求,其实就是两套 API:同步(blocking)和异步(non-blocking)</h3>
<pre><code>const fs = require('fs');
// 同步(阻塞)——会卡住主线程,直到完成
const data = fs.readFileSync('file.txt', 'utf8');
console.log(data);
// 异步(非阻塞)——立即返回,通过回调/事件通知结果
fs.readFile('file.txt', 'utf8', (err, data) => {
console.log(data);
});
</code></pre>
<blockquote>
<p>异步版本不会等待操作完成,而是立即返回,等 I/O 结果准备好后,通过回调函数(或 Promise)由事件循环调度执行,从而实现不阻塞主线程的效果。</p>
</blockquote>
<h2 id="3单线程-vs-高并发">3.单线程 vs 高并发</h2>
<ul>
<li>JavaScript 执行是单线程的:所有 JavaScript 代码(包括你的业务逻辑、回调函数、Promise 等)都在同一个主线程上顺序执行</li>
<li>这个线程由 V8 引擎 + 事件循环(Event Loop) 驱动</li>
<li>因此,你写的 JS 代码永远不会并行执行(除非用 Worker Threads)</li>
<li>高并发不是靠 JS 多线程,而是靠“不等待”+“后台并行”</li>
</ul>
<blockquote>
<p>Node.js 的“单线程”仅指 JavaScript 代码的执行模型;底层 I/O 由 libuv 通过多线程或系统异步机制处理,二者分工明确,共同实现高并发<br>
“单线程 JavaScript 负责协调,多线程/异步系统负责干活” —— 分工合作,高效并发。</p>
</blockquote>
<h2 id="4设计理念">4.设计理念</h2>
<h3 id="nodejs-的理想应用场景是-io-密集型而非-cpu-密集型任务">Node.js 的理想应用场景是 I/O 密集型(而非 CPU 密集型)任务</h3>
<h3 id="它采用-单线程-javascript-执行模型--异步非阻塞-io-架构正是为了最大化-io-并发效率同时避免多线程编程的复杂性">它采用 单线程 JavaScript 执行模型 + 异步非阻塞 I/O 架构,正是为了最大化 I/O 并发效率,同时避免多线程编程的复杂性</h3>
<h3 id="在这种模型下">在这种模型下:</h3>
<ul>
<li>CPU 消耗应尽可能少(业务逻辑轻量);</li>
<li>主要耗时来自 I/O(如数据库查询、文件读写、网络请求);</li>
<li>这些 I/O 操作由底层 libuv 通过 操作系统异步机制(如 epoll)或 内部线程池 高效处理,不阻塞 JS 主线程;</li>
<li>因此,单线程也能支撑高并发</li>
</ul>
<blockquote>
<p>而当确实需要处理 CPU 密集型任务(如加密、图像处理、复杂计算)时,Node.js 提供了 Worker Threads 作为“逃生舱”——允许你将重计算任务移出主线程,避免阻塞事件循环<br>
如果某个 HTTP 请求(或其他事件回调)中直接执行了 CPU 密集型任务,并且没有使用 Worker Threads、子进程或外部服务来隔离它,那么这个请求会阻塞整个 Node.js 事件循环,导致所有其他请求(包括已到达的和新进来的)都无法被处理,直到该 CPU 任务完成</p>
</blockquote>
<h3 id="总之主线程只做调度和轻量逻辑io-交给底层自动异步cpu-重活甩给-worker-threads">总之:“主线程只做调度和轻量逻辑,I/O 交给底层(自动异步),CPU 重活甩给 Worker Threads。”</h3>
<h2 id="5常见的-cpu-密集型任务清单nodejs-场景">5.常见的 CPU 密集型任务清单(Node.js 场景)</h2>
<h3 id="加密哈希运算">加密/哈希运算</h3>
<ul>
<li>使用 crypto 模块进行高强度密码哈希(如 bcrypt、scrypt、PBKDF2)<pre><code>crypto.pbkdf2Sync(password, salt, 100000, 64, 'sha512'); // 同步版会阻塞
bcrypt.hashSync(password, 12); // 阻塞主线程
</code></pre>
</li>
<li>生成或验证 JWT</li>
</ul>
<h3 id="大数据处理与转换">大数据处理与转换</h3>
<ul>
<li>解析或序列化超大的 JSON 对象<pre><code>const data = JSON.parse(hugeJsonString); // 可能卡住几百毫秒甚至更久
const str = JSON.stringify(largeObject);
</code></pre>
</li>
<li>对大型数组/对象进行深度遍历、过滤、映射、排序</li>
<li>复杂算法计算:递归计算(如斐波那契、阶乘)等</li>
</ul>
<h3 id="图像音视频处理">图像/音视频处理</h3>
<h3 id="压缩解压缩大文件">压缩/解压缩大文件</h3>
<h3 id="基于现实">基于现实:</h3>
<ul>
<li>在绝大多数场景下,JWT 的解包/验证是轻量级操作,不会造成性能瓶颈,也不需要 Worker Threads</li>
<li>加密密码的时候,bcrypt.hash()是典型的 CPU 密集型操作,在常规用户注册/登录场景下,通常不会造成性能问题</li>
</ul>
<blockquote>
<p>不要为了“理论上可能的性能问题”过早优化,而要为“实际观测到的瓶颈”去优化</p>
</blockquote>
<h2 id="6nodejs-的版本">6.Node.js 的版本</h2>
<p>Node.js 采用 LTS(Long-Term Support,长期支持) + Current(当前版) 双轨发布模型:</p>
<table>
<thead>
<tr>
<th>类型</th>
<th>发布频率</th>
<th>支持周期</th>
<th>目标用户</th>
</tr>
</thead>
<tbody>
<tr>
<td>Current(奇数版本)</td>
<td>每 6 个月(每年 4 月、10 月)</td>
<td>仅到下一个奇数版发布(约 6 个月)</td>
<td>尝鲜者、库作者</td>
</tr>
<tr>
<td>LTS(偶数版本)</td>
<td>每年 10 月发布一个新 LTS</td>
<td>30 个月(分 Active / Maintenance 阶段)</td>
<td>企业、生产环境</td>
</tr>
</tbody>
</table>
<blockquote>
<p>生产环境强烈建议使用 LTS 版本!</p>
</blockquote>
<h3 id="安装node后在cmd下运行node--v-即可查看安装的nodejs版本">安装node后在cmd下运行node -v 即可查看安装的node.js版本</h3>
<p><img src="https://upload-images.jianshu.io/upload_images/16495584-6a0d04ff6077f849.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"></p>
<blockquote>
<p>如果安装成功却提示node不是内部或者外部的命令。则需要手动配置环境变量</p>
</blockquote>
<h3 id="关键演进脉络">关键演进脉络</h3>
<table>
<thead>
<tr>
<th>时期</th>
<th>重点方向</th>
</tr>
</thead>
<tbody>
<tr>
<td>v10–v12</td>
<td>ESM 支持、Worker Threads、现代 JS 对齐</td>
</tr>
<tr>
<td>v14–v16</td>
<td>Apple Silicon、诊断工具、安全加固</td>
</tr>
<tr>
<td>v18–v20</td>
<td>原生 fetch、Web 标准统一、性能提升</td>
</tr>
<tr>
<td>v22+</td>
<td>权限模型、启动优化、更贴近浏览器运行时</td>
</tr>
</tbody>
</table>
<h2 id="7配置环境变量">7.配置环境变量</h2>
<h3 id="为什么要配置环境变量">为什么要配置环境变量:</h3>
<p>在命令行(如 Windows 的 CMD 或 PowerShell)中执行命令(例如 node、npm、python)时,系统会按以下顺序查找对应的可执行文件(如 node.exe):</p>
<ul>
<li>当前工作目录(你打开终端时所在的文件夹)</li>
<li>系统 Path 环境变量中列出的所有目录<br>
如果这些地方都找不到 node.exe,就会提示:</li>
</ul>
<pre><code>'node' 不是内部或外部命令,也不是可运行的程序或批处理文件。
</code></pre>
<h3 id="配置环境变量的目的">配置环境变量的目的:</h3>
<ul>
<li>告诉操作系统:“当你找不到某个命令时,请去我指定的这些路径里找一找。”</li>
<li>这样我们就可以在任意目录下直接输入 node 来运行 Node.js,而不需要每次都写完整路径(如 C:\Program Files\nodejs\node.exe)</li>
</ul>
<h3 id="nodejs-安装时通常已自动配置">Node.js 安装时通常已自动配置</h3>
<blockquote>
<p>从 Node.js 官网(https://nodejs.org)下载的 Windows 安装包(.msi)默认会自动将安装路径添加到系统的 Path 环境变量中</p>
</blockquote>
<h3 id="如何手动配置环境变量">如何手动配置环境变量</h3>
<ul>
<li>右键“此电脑”或“我的电脑” → 属性</li>
<li>点击 “高级系统设置”</li>
<li>在“系统属性”窗口中,点击 “环境变量”</li>
<li>在 “系统变量” 区域,找到并选中 Path,点击 “编辑”</li>
<li>点击 “新建”,然后输入 Node.js 的安装路径(通常是):</li>
<li>点击“确定”保存所有窗口</li>
</ul>
<blockquote>
<p>注意,这点很重要:关闭并重新打开 CMD 或 PowerShell</p>
</blockquote>
<p><img src="https://upload-images.jianshu.io/upload_images/16495584-63f22661b69ba981.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><br>
<img src="https://upload-images.jianshu.io/upload_images/16495584-c0c94883f812b203.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><br>
<img src="https://upload-images.jianshu.io/upload_images/16495584-1a155769025aef9f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"></p>
<h2 id="8nvm-desktop推荐">8.NVM Desktop(推荐)</h2>
<h3 id="什么是-nvm-desktop">什么是 NVM Desktop?</h3>
<p>NVM Desktop(简称 nvmd)是一款 图形化 + 命令行结合的 Node.js 版本管理工具,专为 Windows 平台设计(也有跨平台计划),其核心目标是:</p>
<blockquote>
<p>“让不同项目自动使用各自所需的 Node.js 版本,无需手动切换。”<br>
它不是传统 nvm(Node Version Manager)的图形界面,而是一个全新架构的替代方案。</p>
</blockquote>
<h3 id="核心原理无侵入式命令代理">核心原理:无侵入式命令代理</h3>
<ul>
<li>nvmd 通过一个轻量级命令行工具 nvmd-command 实现版本管理。</li>
<li>它不修改系统的 PATH 环境变量,而是采用 “代理拦截”机制:
<ul>
<li>当你在终端中输入 node、npm、npx、yarn 等命令时,</li>
<li>nvmd 会实时拦截这些调用,并根据当前目录下的配置文件,动态选择对应的 Node.js 版本执行。</li>
</ul>
</li>
<li>整个过程对用户透明,无需 nvm use xxx。<br>
✅ 优势:</li>
<li>无需重启终端</li>
<li>多项目并行开发时自动切换版本</li>
<li>不污染全局环境</li>
</ul>
<h3 id="如何为项目指定-nodejs-版本">如何为项目指定 Node.js 版本?</h3>
<ul>
<li>在项目根目录创建配置文件,文件名为 .nvmdrc</li>
<li>文件内容只需一行:目标 Node.js 版本号<pre><code>20.12.0
</code></pre>
</li>
<li>效果
<ul>
<li>只要你在该目录(或子目录)下打开终端,</li>
<li>所有 node、npm 等命令都会自动使用 .nvmdrc 指定的版本。</li>
<li>切换到其他项目目录,自动切换到对应版本</li>
</ul>
</li>
</ul>
<h3 id="与传统-nvm-的对比">与传统 NVM 的对比</h3>
<table>
<thead>
<tr>
<th>特性</th>
<th>传统 NVM(如 nvm-windows)</th>
<th>NVM Desktop(nvmd)</th>
</tr>
</thead>
<tbody>
<tr>
<td>切换方式</td>
<td>手动执行 nvm use 20.12.0</td>
<td>自动识别 .nvmdrc</td>
</tr>
<tr>
<td>环境变量</td>
<td>修改全局 PATH</td>
<td>不修改 PATH,代理拦截</td>
</tr>
<tr>
<td>多项目支持</td>
<td>需频繁手动切换</td>
<td>开箱即用,自动隔离</td>
</tr>
<tr>
<td>终端重启</td>
<td>切换后需新开终端(部分场景)</td>
<td>无需重启,即时生效</td>
</tr>
<tr>
<td>配置方式</td>
<td>全局命令</td>
<td>项目级配置文件(.nvmdrc)</td>
</tr>
<tr>
<td>设计理念</td>
<td>“版本切换”</td>
<td>“版本匹配”</td>
</tr>
</tbody>
</table>
<blockquote>
<p>NVM 是“你告诉它用哪个版本”<br>
nvmd 是“它自己知道该用哪个版本”</p>
</blockquote>
<h3 id="下载安装">下载安装</h3>
<ul>
<li>官网:https://github.com/nvmd-org/nvmd (或搜索 “NVM Desktop”)</li>
<li>安装后自动注册代理(首次运行可能需要管理员权限)</li>
<li>验证安装:</li>
</ul>
<pre><code>nvmd --version
</code></pre>
<h3 id="注意事项">注意事项</h3>
<ul>
<li>如果已有 nvm、fnm、volta 等工具,建议卸载或禁用,避免冲突</li>
<li>.nvmdrc 文件应加入项目 Git 仓库,确保团队成员使用相同 Node 版本</li>
</ul><br><br>
来源:https://www.cnblogs.com/OrochiZ-/p/11648653.html
頁:
[1]