• Node.js的模块


    环境

    • Ubuntu 22.04
    • Node.js 16.15.1
    • VSCode 1.69.2

    模块

    在Node.js的代码中,可以引用其它模块,用法如下:

    const xxx = require('xxx');
    
    • 1

    Node.js的模块,可分为:

    • 内置模块
    • 自定义模块
    • 第三方模块

    内置模块

    例如Node.js内置的 http 模块。

    自定义模块

    使用 require() 方法加载模块时,得到的是其 module.exports 所指向的对象。

    创建文件 0727_5.js

    var f = function() {
        console.log('hello')
    }
    
    // module.exports.username = 'Tom';
    // module.exports.password = 'xyz';
    // module.exports.f = f
    
    module.exports = {
        name: 'Jerry',
        password: 'abc',
        f
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    module.exports 指向一个JavaScript对象(如果换成被注释的代码,效果也一样)。

    创建文件 0727_6.js

    const xxx = require('./0727_5.js');
    
    console.log(xxx);
    
    xxx.f();
    
    • 1
    • 2
    • 3
    • 4
    • 5

    运行程序:

    ➜  temp0727 node 0727_6.js
    { name: 'Jerry', password: 'abc', f: [Function: f] }
    hello
    
    • 1
    • 2
    • 3

    注意:使用 require() 方法加载模块时,会执行被加载模块的代码。例如:如果在 0727_5.js 中添加一行代码:

    console.log('good');
    
    • 1

    再次运行程序:

    ➜  temp0727 node 0727_6.js
    good
    { name: 'Jerry', password: 'abc', f: [Function: f] }
    hello
    
    • 1
    • 2
    • 3
    • 4

    可见,在 require('./0727_5.js') 处,会执行 0727_5.js 的代码。

    由于 module.exports 写起来比较复杂,Node提供了 exports 对象。默认情况下, exportsmodule.exports 指向同一个对象。但是要注意,这跟Java里面“ AB 两个对象可以指向同一个实例,也可以指向不同实例”类似,最终 require() 方法获取的是 module.exports 指向的对象。

    比如:

    创建文件 0727_8.js

    const xxx = require('./0727_7.js');
    
    console.log(xxx);
    
    • 1
    • 2
    • 3

    其中 0727_7.js 内容为:

    exports.username = 'Tom';
    
    module.exports.password = 'xyz';
    
    • 1
    • 2
    • 3

    则运行程序,结果为:

    ➜  temp0727 node 0727_8.js
    { username: 'Tom', password: 'xyz' }
    
    • 1
    • 2

    0727_7.js 内容为:

    module.exports = {
        height: 180,
        weight: 70
    }
    
    exports.age = 20;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    则运行程序,结果为:

    ➜  temp0727 node 0727_8.js
    { height: 180, weight: 70 }
    
    • 1
    • 2

    注意: exports.age = 20 并没有起作用,因为 module.exports 已经指向别处了。

    第三方模块

    Node.js 中的第三方模块又叫做包。

    包是基于内置模块封装出来的,提供了更高级、更方便的 API,极大的提高了开发效率。包和内置模块之间的关系,类似于jQuery和浏览器内置 API之间的关系。

    Node.js的包管理工具叫做 npmNode Package Manager ),npm会随着Node一起安装。

    ➜  ~ npm -v
    8.11.0
    
    • 1
    • 2

    安装包的命令如下:

    • npm i|install :项目包
    • npm i|install -g :全局包

    例如,在 temp0727 目录下安装 express 包:

    ➜  temp0727 npm i express
    
    added 57 packages, and audited 58 packages in 19s
    
    7 packages are looking for funding
      run `npm fund` for details
    
    found 0 vulnerabilities
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    安装完成之后,在当前目录下多了3个文件/文件夹:

    • node_modules :存放包的目录,在里面可以找到 express
    • package-lock.json :记录 node_modules 目录里的包信息;
    • package.json :包管理配置工具;

    我们来重点看一下 package.json ,它有点类似于Maven里的 pom.xml 配置文件。

    在用git管理项目源码时,一般我们不会把三方包也放进去,所以只需在 package.json 中记录需要哪些包,而协作者获取源码之后,只需在项目根目录下运行 npm i ,就会一次性安装 package.json 里记录的所有包。

    使用 npm list 命令可以看到当前项目安装了哪些包:

    ➜  temp0727 npm list
    temp0727@ /home/ding/temp/temp0727
    └── express@4.18.1
    
    • 1
    • 2
    • 3

    项目包和全局包

    前面提到了全局包。事实上只有工具性质的包,才有全局安装的必要性。因为它们一般提供了终端命令。判断某个包是否需要全局安装,可以参考官方( https://www.npmjs.com/ )提供的使用说明。

    例如,在该网站上搜索 express ,文档里提到的安装方法为:

    npm install express
    
    • 1

    因为它不是工具性质的包,所以不应该使用全局安装。

    搜索 i5ting_toc ,文档里提到的安装方法为:

    npm install -g i5ting_toc
    
    • 1

    i5ting_toc 是一个工具,能把MarkDown文档转换为HTML文档,显然应该全局安装。

    全局安装 i5ting_toc

    ➜  temp0727 npm i -g i5ting_toc
    npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.
    
    added 17 packages, and audited 18 packages in 6s
    
    5 vulnerabilities (2 high, 3 critical)
    
    To address all issues (including breaking changes), run:
      npm audit fix --force
    
    Run `npm audit` for details.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    注意给出的提示信息, --global 已经过时,应该用 --location=global

    安装之后就可以使用 i5ting_toc 工具了:

    ➜  temp0727 which i5ting_toc
    /home/ding/Downloads/node-v16.15.1-linux-x64/bin/i5ting_toc
    
    • 1
    • 2

    我们先来创建一个MarkDown文档 test.md
    在这里插入图片描述

    用如下命令将其转换为HTML文档:

    ➜  temp0727 i5ting_toc -f test.md -o
    pwd=/home/ding/temp/temp0727
    source_file_name=/home/ding/temp/temp0727/test.md
    dest_file_path=/home/ding/temp/temp0727/preview/test.html
    
    • 1
    • 2
    • 3
    • 4

    转换后效果如下:

    在这里插入图片描述

    模块加载机制

    不论是内置模块、用户自定义模块、还是第三方模块,在第一次加载后都会被缓存,所以多次调用 require() 方法不会导致模块的代码被执行多次。

    内置模块的加载优先级最高。

    加载模块文件时,可以省略其扩展名,其加载顺序为:

    • 按照确切的文件名进行加载
    • 补全 .js 扩展名进行加载
    • 补全 .json 扩展名进行加载
    • 补全 .node 扩展名进行加载

    使用 require() 加载自定义模块时,必须指定以 ./../ 开头的路径标识符。对于第三方模块的加载机制,Node.js会从当前目录开始,尝试从 /node_modules 文件夹中加载第三方模块。如果没有找到,则移动到上一层目录中加载,直到文件系统的根目录。

    如果加载的是一个目录,则会在该目录下查找 package.json 文件,并寻找 main 属性,作为加载的入口。如果目录里没有 package.json 文件,或者 main 入口不存在或无法解析,则Node.js会试图加载目录下的 index.js 文件。

    参考

    • https://www.npmjs.com/
  • 相关阅读:
    从0到1,手把手带你开发截图工具ScreenCap------001实现基本的截图功能
    hive的安装配置及使用
    乾坤js隔离
    Nginx Rewrite
    分布式id生成方案有哪些
    字节架构师: Kafka 的消费者客户端详解
    @Transactional注解介绍
    【数据结构-树】红黑树
    ssm+vue的4S店预约保养管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。
    ubuntu安装mysql8.0.35过程和报错处理
  • 原文地址:https://blog.csdn.net/duke_ding2/article/details/126015283