NodeJS系列(1)- 安装配置 NVM + NodeJS

发布时间 2023-06-15 17:48:53作者: 垄山小站


NodeJS (或 Node.js) 是一个事件驱动 I/O 服务端 JavaScript 环境,基于 Google 的 V8 引擎,V8 引擎执行 Javascript 的速度非常快,性能非常好。简而言之,NodeJS 就是运行在服务端的 JavaScript。

NVM (Node Version Manage),即 NodeJS 的版本管理工具。不同项目依赖不同的 NodeJS 版本,使用 NVM 可以在多个 NodeJS 版本之间快速切换。

NodeJS: https://nodejs.org

 

1. 系统环境

    操作系统:Windows 10 (x64)
    NodeJS: 16.14.2 或 18.16.0

 

2. 使用 NVM 安装 NodeJS

    1) 安装 NVM

        下载 NVM 安装包 https://github.com/coreybutler/nvm-windows/releases,选择下载 nvm-setup.zip,双击 nvm-setup.exe 文件,进入安装过程,按默认选项即可。
    
        打开命令行窗口,运行 nvm -v,出现版本号即表示安装成功。

            C:\Users\admin>nvm -v

                1.1.11

        注:安装 NVM 前,建议先卸载电脑上现有的 NodeJS,避免冗余。

            安装程序会自动帮我们配置了环境变量 NVM_HOME 和 NVM_SYMLINK,并且配置了 Path 的值,免安装版的 NVM,需要手动配置环境变量。

            可以修改 NVM 根目录下的 setting.txt 文件,配置 NodeJS 下载代理镜像,解决在线安装 NodeJS 时速度慢的问题。

    2) 安装 NodeJS

        使用 nvm list available 命令,查看可安装的 NodeJS 版本。建议选择 LTS 中的版本进行安装(LTS,即Long Term Support,长期支持版本)。

            C:\Users\admin> nvm list available

            |   CURRENT    |     LTS      |  OLD STABLE  | OLD UNSTABLE |
            |--------------|--------------|--------------|--------------|
            |    20.3.0    |   18.16.0    |   0.12.18    |   0.11.16    |
            |    20.2.0    |   18.15.0    |   0.12.17    |   0.11.15    |
            |    20.1.0    |   18.14.2    |   0.12.16    |   0.11.14    |
            |    20.0.0    |   18.14.1    |   0.12.15    |   0.11.13    |
            |    19.9.0    |   18.14.0    |   0.12.14    |   0.11.12    |
            |    19.8.1    |   18.13.0    |   0.12.13    |   0.11.11    |
            |    19.8.0    |   18.12.1    |   0.12.12    |   0.11.10    |
            |    19.7.0    |   18.12.0    |   0.12.11    |    0.11.9    |
            |    19.6.1    |   16.20.0    |   0.12.10    |    0.11.8    |
            |    19.6.0    |   16.19.1    |    0.12.9    |    0.11.7    |
            |    19.5.0    |   16.19.0    |    0.12.8    |    0.11.6    |
            |    19.4.0    |   16.18.1    |    0.12.7    |    0.11.5    |
            |    19.3.0    |   16.18.0    |    0.12.6    |    0.11.4    |
            |    19.2.0    |   16.17.1    |    0.12.5    |    0.11.3    |
            |    19.1.0    |   16.17.0    |    0.12.4    |    0.11.2    |
            |    19.0.1    |   16.16.0    |    0.12.3    |    0.11.1    |
            |    19.0.0    |   16.15.1    |    0.12.2    |    0.11.0    |
            |   18.11.0    |   16.15.0    |    0.12.1    |    0.9.12    |
            |   18.10.0    |   16.14.2    |    0.12.0    |    0.9.11    |
            |    18.9.1    |   16.14.1    |   0.10.48    |    0.9.10    |

            This is a partial list. For a complete list, visit https://nodejs.org/en/download/releases


        使用 nvm install 命令,进行对应版本 NodeJS 的在线安装,这里安装 18.16.0 和 16.14.2,运行如下命令。

            C:\Users\admin> nvm install 18.16.0
            
                ...

            C:\Users\admin> nvm install 16.14.2

                ...

            C:\Users\admin> nvm list

                18.16.0
                16.14.2

            # 使用或切换版本
            C:\Users\admin> nvm use 16.14.2

                Now using node v16.14.2 (64-bit)

            C:\Users\admin> nvm list

                  18.16.0
                * 16.14.2 (Currently using 64-bit executable)
            
            C:\Users\admin> node -v

                v16.14.2

            C:\Users\admin> npm  -v

                8.5.0

            注:老版本的 NodeJS 不包含 npm,
            
                在线安装 nodeJS 如果遇到问题,也可以从 https://nodejs.org/en/download/releases 下载 NodeJS 离线安装包,解压后放入到 NVM 安装路径的根目录下,即可完成离线安装。

    3) NVM 常用命令

        nvm list:列出所有已经在 NVM 中安装的 NodeJS 版本,简写 nvm ls。
        nvm list available:查看可在线安装的 NodeJS 版本。
        nvm current:显示当前正在使用的 NodeJS 版本。
        nvm install xx.xx.xx:在线安装指定版本的 NodeJS,xx.xx.xx 为指定的版本号。
        nvm uninstall xx.xx.xx:卸载指定版本的 NodeJS,xx.xx.xx 为指定的版本号。
        nvm use xx.xx.xx:切换 NodeJS 版本,xx.xx.xx 为指定的版本号。
        nvm version:显示当前所使用的 NVM 的版本号。

 

3. 安装 cnpm(可选项)

    npm 默认的仓库地址为 http://registry.npmjs.org,可以使用如下命令查看当前 npm 仓库。

        C:\Users\admin> npm config get registry

            https://registry.npmjs.org/
       
    在国内访问国外的仓库,有时候访问速度比较慢,甚至无法访问。为了解决这个问题,可以使用如下 2 种方法中的 1 种。

    1) 安装 cnpm

        C:\Users\admin> npm install cnpm -g

        # 在国内可以使用如下命令
        C:\Users\admin> npm install cnpm -g --registry=https://registry.npmmirror.com

        直接使用 cpm 替代 npm,参数和 npm 命令一样,比如 npm install uniq --save 对应 cnpm 命令为cnpm install uniq --save

        注:https://registry.npmmirror.com 是 npm 的官方镜像站,也可以使用 https://registry.npm.taobao.org,下同。

    2) 替换 npm 的仓库地址

        C:\Users\admin> npm config set registry https://registry.npmmirror.com

        C:\Users\admin> npm config get registry

            https://registry.npmmirror.com

 

4. NodeJS 交互式解释器 (Read Eval Print Loop, REPL)

    NodeJS REPL 表示一个电脑的环境,类似 Windows 系统的终端或 Unix/Linux shell,可以在终端中输入命令,并接收系统的响应。

    Node 自带了交互式解释器,可以执行以下任务:

        读取 - 读取用户输入,解析输入的 Javascript 数据结构并存储在内存中。
        执行 - 执行输入的数据结构。
        打印 - 输出结果。
        循环 - 循环操作以上步骤直到用户两次按下 ctrl-c 按钮退出。

    Node 的交互式解释器可以很好的调试 Javascript 代码。

    1) 示例

        C:\Users\admin> node

       Welcome to Node.js v16.14.2.
        Type ".help" for more information.

        # 表达式运算
        > 1+1
        2
        > 2-1
        1
        > 2*3
        6
        > 5/2
        2.5

        # 使用变量
        > a=1
        1
        > var b=2
        undefined
        > a+b
        3
        > console.log(b)
        2
        undefined
        > console.log('hello world')
        hello world
        undefined

            注:没有使用 var 关键字变量会直接打印出来,使用 var 关键字的变量可以使用 console.log() 来输出变量。       

        # 多行表达式
        > var x=0
        undefined
        > for (i=0;i<5;i++){
        ... x++;
        ... console.log("x: " + x);
        ... }
        x: 1
        x: 2
        x: 3
        x: 4
        x: 5
        undefined

        # 下划线(_)变量,可以使用下划线(_)获取上一个表达式的运算结果
        > var a=3
        undefined
        > var b=8
        undefined
        > a+b
        11
        > console.log(_)
        11            


    2) REPL 命令

        ctrl + c - 退出当前终端
        ctrl + c 按下两次 - 退出 Node REPL
        ctrl + d - 退出 Node REPL
        向上/向下 键 - 查看输入的历史命令
        tab 键 - 列出当前命令
        .help - 列出使用命令
        .break - 退出多行表达式
        .clear - 退出多行表达式
        .save filename - 保存当前的 Node REPL 会话到指定文件
        .load filename - 载入当前 Node REPL 会话的文件内容

 

5. NodeJS 脚本

    1) Hello World

        创建 D:\workshop\nodejs\hello.js 脚本文件,内容如下

            console.log("Hello World");

        运行

            D:\workshop\nodejs> node hello.js  

            或

            D:\workshop\nodejs> node hello

                Hello world!

    2) 简单 Web 服务器

        我们使用 require 指令来载入 http 模块,并使用 http.createServer() 方法创建一个简单 Web 服务器,使用 listen 方法绑定 8000 端口。 函数通过 request, response 参数来接收和响应数据。

        创建 D:\workshop\nodejs\server.js 文件,内容如下

            var http = require('http');

            http.createServer(function (request, response) {
                response.writeHead(200, {'Content-Type': 'text/plain'});
                response.end('Web: Hello World!');
            }).listen(8000);

            console.log('Server running at http://localhost:8000/');


        运行

            D:\workshop\nodejs> node server

                Server running at http://localhost:8000

        打开浏览器访问 http://localhost:8000,显示如下内容

            Web: Hello World!


6. NodeJS 模块系统

    模块是 NodeJS 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个 NodeJS 文件就是一个模块,这个文件可能是 JavaScript 代码、JSON 或者编译过的 C/C++ 扩展。

    NodeJS 提供了 exports 和 require 两个对象,其中 exports 是模块公开的接口,require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象。

    示例1
    
        修改 D:\workshop\nodejs\hello.js 文件,内容如下

            exports.test = function() {
                console.log('Hello World');
            }


        创建一个 D:\workshop\nodejs\main.js 文件,内容如下

            var hello = require('./hello');  // 导入 hello 模块
            console.log("typeof(hello): " + typeof(hello));
            hello.test();


        运行

            D:\workshop\nodejs> node main

                typeof(hello): object
                Hello world
    
    示例2

        创建 D:\workshop\nodejs\hello2.js 文件,内容如下

            module.exports.test = function() {
                console.log('Hello World 2');
            }        


        创建一个 D:\workshop\nodejs\main2.js 文件,内容如下

            var hello2 = require('./hello2');  // 导入 hello2 模块
            console.log("typeof(hello2): " + typeof(hello2));
            hello2.test();


        运行

            D:\workshop\nodejs> node main2

                typeof(hello2): object
                Hello world 2

    示例3

        创建 D:\workshop\nodejs\hello3.js 文件,内容如下

            module.exports = function() {
                console.log('Hello World 3');
            }        


        创建一个 D:\workshop\nodejs\main3.js 文件,内容如下

            var hello3 = require('./hello3');  // 导入 hello3 模块
            console.log("typeof(hello3): " + typeof(hello3));
            hello3();


        运行

            D:\workshop\nodejs> node main3

                typeof(hello3): function
                Hello world 3

    示例4
    
        修改 D:\workshop\nodejs\hello4.js 文件,内容如下

            exports = function() {
                console.log('Hello World 4');
            }


        创建一个 D:\workshop\nodejs\main4.js 文件,内容如下

            var hello4 = require('./hello4');  // 导入 hello4 模块
            console.log("typeof(hello4): " + typeof(hello4));
            hello4();


        运行

            D:\workshop\nodejs> node main4

                typeof(hello4): object
                D:\Workshop\dev-nodejs\main4.js:3
                hello4();
                ^

                TypeError: hello4 is not a function
                    at Object.<anonymous> (D:\Workshop\dev-nodejs\main4.js:3:1)
                    at Module._compile (node:internal/modules/cjs/loader:1103:14)
                    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1157:10)
                    at Module.load (node:internal/modules/cjs/loader:981:32)
                    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
                    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
                    at node:internal/main/run_main_module:17:47


    CommonJS 规范规定,每个模块内部,module 变量代表当前模块。这个变量是一个对象,它的 exports 属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的 module.exports 属性。并且 Node 为每个模块提供一个 exports 变量 (或引用),指向 module.exports。

    exports 和 module.exports 的区别:

        (1) exports 只能使用 . 语法来向外暴露内部变量,比如:expotrs.xxx = xxx;
        (2) module.exports 既可以通过.语法,也可以直接赋值一个对象。