1、前言
每天一个知识点~
今天先学点不一样的,一套详细太极拳的动作图,先收藏为敬!
不过现在很流行的是八段锦,据说打完一套下来对身体倍儿棒~不知道以后是否有缘得到拳谱
闲话少说,今天开始学习基本的 Node 脚本编写和运行,主要包括以下内容
- node 环境搭建,以及可能遇到的问题
- nvm 控制 node 版本
- 基本的 node 脚本编写和运行
- 使用 nodemon 监测应用文件变化自动重启服务
- commonJS 规范及 node 中如何组织代码
2、安装
进入 Node 官网选择左侧的最新的 LTS 版本,点击下载
- LTS,long time support,长期维护版本,即稳定版
- Current,则是最新版本,包含 Node.js 的最新特性
2.1 安装包点击无响应
此类问题基本都是安全限制导致,具体解决办法可参考安装包点击不响应
2.2 如何检查安装成功
Node.js 安装完后是没有桌面快捷方式访问,那么如何检查自己的计算机是否成功安装呢?
-
打开命令行工具(CMD 或 PowerShell)
- 如何打开 CMD 或 PowerShell,搜索栏或任意文件夹目录栏下,输入 cmd | powershell,回车即可打开
- 推荐使用 PowerShell,功能更强大,复制粘贴等更强大
- 管理员模式运行:搜索栏输入
powershell
,在结果中找到Window PowerShell
,右键选择以管理员身份运行
-
输入命令
node -v
或者node --version
回车 -
如果输出 node 的版本号,则安装成功
安装成功,接下来就可以愉快的开始 Hello W...(捂嘴)
2.3 版本控制
愉快的开始先放一放,我们先整一下 node 的版本控制
日常项目中,经常出现需要切换不同 node 版本的问题,归根结底,在于前端发展迅速,各种依赖更新迭代迅速,当然,一般情况下我们很少关注
但是呢,当你在项目安装依赖时发现报错,想起来排查默认 node 版本问题时,你会遗憾的发现,你可能根本不知道这个项目需要使用什么版本的 node,焦头烂额到处打听,哎~
在这里,我强烈的要求,一定要在 README 文件中写明
絮絮叨叨了一堆日常开发中的辛酸泪,差点忘了正题,如何控制 node.js 的版本切换?
进入 NVM 管理工具 官网,选择对应终端的安装包下载,傻瓜式的下一步、下一步安装完成即可
2.3.1 检查 nvm 安装成功
与 node 安装成功检查一样,PowerShell 中输入 nvm -v
即可完成检查
由于我们一般使用命令都是在 vscode 的终端下,我们也可以在终端中执行 nvm -v
芭比Q了,CMD 或 PowerShell 能正常输出版本号;终端中却提示无法识别
解决办法参考终端无法识别命令
2.3.1 nvm 常用命令
一些常用的 nvm 命令,辅助进行 node 版本管理
nvm list 与 nvm curren
nvm list
或 nvm ls
命令查看当前所有已安装的版本
同时也能看到当前使用的 node 版本;当然也可以通过 nvm current
来查看
nvm install 与 nvm uninstall
nvm install 18.16.0
用来安装指定版本的 node.js
可以不具体小版本号,会自动安装大版本下最新的小版本号
如 nvm install 8
会自动安装 8.18.0 版本的 node.js
安装的 node版本 可以通过 nvm uninstall 8.18.0
来卸载指定的版本
nvm use
nvm use 8.17.0
会切换到指定的版本;可以配合 nvm use
查看是否切换成功了
如果 use 的版本没有安装,会提示先安装
nvm alias
为 node 版本创建一个别名,如 nvm alias default 18.16.1
这是一个非常有用的功能,我们可以根据我们的项目使用的 node 版本来创建别名,嘿嘿,再也不用到处找人问项目使用的 node 版本了
其他
nvm 还有许多 node 版本管理相关的命令,如
nvm reinstall-packages
在切换Node.js版本后,重新安装已安装的全局npm包
nvm on
打开nvm自动切换
这里不一一列举,上述是我日常使用场景涉及的命令;后续使用到其他命令解决问题时再一一记录补充
3、从 Hello World 开始
不管什么语音,愉快的学习总是从 Hello World 开始~(刚刚不太愉快,被人捂嘴了-.-!)
-
1、打开 vscode 创建一个 test.js 文件,js 文件中只有一句代码
console.log('hello world!')
-
2、打开终端,进入你的 hello.js 文件所在的目录;比如你的 js 在项目的 learn-node 文件夹下,终端执行
cd learn-node
-
3、终端运行
node hello.js
命令,不出意外你的终端上就能看到打印hello world!
-
4、做大做强,我要加点内容;在 js 中加一句
console.log('我要学好 node.js,加油,奥利给~')
-
5、终端并没有鸟我~
-
6、需要再次执行命令
node hello.js
(可以按键盘上箭头
快速找到上一条命令),就能看到咱们的努力宣言了
可以看到,我在保存文件更改后,终端并没有给出我想要的输出,在这个热更新泛滥的年代,肯定是不能接受这种手动再次执行命令的操作的,nodemon 登场
3.1、nodemon 实现 Web 应用代码热更新
工欲善其事必先利其器
nodemon 是一个基于 Node.js 开发的工具,能够自动监控 Node.js 应用的服务更改,并在更改后重启 Node.js 应用程序
3.1.1、安装
终端运行以下命令(node 中内置了 npm,可以放心使用)
npm install -g nodemon
这里的 -g 指的是全局安装,这样一次安装后所有项目都能使用了
3.1.2、监听文件变化
将运行命令 node hello.js
换成 nodemon hello.js
你就会发现你对 hello.js 改动保存后就会热更新到终端了
PS: 如果遇到 nodemon 在终端无法识别问题,解决办法参考终端无法识别命令
3.1.3、监听整个应用
脚手架部署的项目很多都默认支持热更新;那如果我们自己写的项目,如利用 koa 启动的项目,一般启动命令是 node app.js;只要将命令修改为 nodemon -L app.js 就可以实现热更新了(-L
是 --legacy-watch
的简写,代表以轮询的方式启动监听代码的变化,这在部署后保证监听是非常有用的)
TODO: 整理热更新相关知识
nodemon 除了可以通过终端执行,监听单个文件;还可以监听整个应用
nodemon app.js
通过监听你的 node 应用的入口文件,达到监听整个应用的目的
依次有 4 条提示,分别为
- nodemon 版本
- 任何时候都可以通过
rs
命令手动重启(命令可自定义) - [重要] 默认监测所有文件和目录
- [重要] 默认监视扩展名 js,mjs,json
nodemon 形式启动 node 应用,默认会监听所有目录的文件(拓展名为 js、mjs、json)变化,只要任意的上述拓展名文件发生变化,就会重启应用;
那么当我们有诸如 json 配置等其他文件,我们不希望他被监测,就像 git ignore 那样?
3.1.4 配置
nodemon 具有非常丰富的配置方式来达到上述目的
- package.json 配置
- nodemon.json 配置
- 启动命令添加参数
三种配置的覆盖优先级: nodemon.json > package.json > 命令参数
最佳实践:推荐以 package.json 的形式配置,没有额外的配置文件,且不会将启动命令变得冗长
常用配置及说明,更多配置可以前往 nodemon 官网 查阅
json
{
// 设置重启命令,默认是 rs
"restartable": "rs",
// 配置忽略监视的路径,默认忽略的是 .git,node_modules,bower--components,.sass-cache
"ignore": [
".git",
"node_modules/**/node_modules"
],
// 重启时是否输出详细信息,默认 false
"verbose": true, \
// 设置执行的命令(默认是 node xxx.js),如 nodemon script.py 将会以 python xxx.js 来启动
"execMap": {
js: "node",
ts: "ts-node",
pl: "perl",
py: "python"
}
// 监视文件或文件夹的路径数组
"watch": [
"src/",
"test/index.js"
],
// 环境变量,用来管理 process.env
"env": {
"NODE_ENV": "development"
},
// 设置延迟时间
"delay": "1000",
// 监听文件拓展名,默认 js,mjs,json
"ext": "ts js json"
}
1、package.json 配置
通过 package.json 的 nodemonConfig 选项配置;配置的内容就是上述配置项
2、nodemon.json 配置
添加 nodemon.json 文件,文件的内容就是上述配置项
package.json 的 script 启动命令关联配置文件
json
// package.json
"script": {
"start": "nodemon --config nodemon.json"
}
此时 npm start
就等价于 nodemon --config nodemon.json
3、命令参数
直接终端执行命令 nodemon --config nodemon.json
,更多命令参数配置可以通过 nodemon --help option
查看,更推荐配置文件的方式

4、组织代码
计算机科学有一个永恒的问题,就是如何写出人能看懂的代码
良好的代码组织,能让人快速上手,读懂代码;关于代码组织,自 JavaScript 诞生以来,就一直在探索,也就是我们所说的模块化
TODO: 整理模块化发展历史
4.1 commonJS
Node.js 默认使用的是 commonJS 规范
- 一个文件就是一个 module;模块内的代码仅作用于当前文件,不会污染全局变量
- 同步加载模块,服务端直接读取本地磁盘非常快
注意:
commonJS 不适用于浏览器(虽然可以用工具转化,但 commonJS 模块存储在服务端,且是阻塞式加载,很容易造成阻塞一直等待;再者浏览器也有已经了自己的 ES Module)
模块可以加载多次,但只有第一次加载会运行,后续加载都是读取缓存
[重要] 导出的是值拷贝,不受外部修改影响(这与 ES6 Module 不同)
[重要] node.js 只是默认采用 commonJS,它也支持 ES Module;如何在 node 中使用 import
4.2 模块的导入导出
通过 exports 或 module.exports 的导出模块;通过 require 来导入模块
假设,同一目录下有 log.js、error.js、test.js 三个文件
log.js 模块文件
js
// module.exports 形式导出
const name = 'log';
module.exports = {
name,
printName: (str) => {
console.log(`${str}${name}`)
}
}
error.js 模块文件
js
// exports 形式导出
const name = 'error';
exports.name = name;
exports.printName = (str) => {
console.log(`${str}${name}`)
}
test.js 模块文件
require 形式导入模块,可以省略 .js 文件后缀;如果使用的 import 配合 .mjs 则不能省略文件后缀
js
const log = require('./log')
const { name, printName } = require('./error')
console.log(log.name); // log
log.printName('模块名: '); // 模块名: log
console.log(name); // error
printName('模块名: '); // 模块名: error
执行结果,符合预期

总结:
- 注意,不能将对象赋值给 exports,如果需要,请使用 module.exports
- 上述两种方式导出,对应的 require 导入的模块是始终是一个对象,因为 require 本质访问的是 module.exports;想要使用模块里的某个方法或属性,只能通过解构或对象属性的方式调用
- 当然,我们也可以直接 module.exports = '1' 导出一个变量或方法,这时 require 的就是变量或方法,可以直接使用
结束语
工作的本质,不是一味的奉献,而是每个人都用自己的方式赢得了尊重
下一次,leader 跟你画饼谈奉献时,你可以用这句话回敬它。虽然但是,但那种紧张的情况下能想起这句话,实在是需要一定的想象力