01、NodeJS学习笔记,第一节:Node.js初识与内置模块

一、初识Node.js与内置模块

xml 复制代码
##网址   https://nodejs.org

##npm包  https://www.npmjs.com/       (搜索)
         https://registry.npmjs.org/  (下载)

1、初识Node.js

xml 复制代码
##思考:为什么JavaScript可以在浏览器中被执行
   因为浏览器中有JavaScript解析引擎。(js==>js核心语法+webAPI)
                                 (webAPI===>DOM API+BOM API+AJAX等)

##不同浏览器的JavaScritpt解析引擎:
   chrome  == > V8
   FireFox == > OdinMonkey
   Safri   == > JSCore
   IE      == > Chakra
   其中Chrome浏览器的V8解析引擎性能最好


##为什么JavaScript可以操作DOM和BOM
  浏览器内置了DOM、BOM、Canvas、XMLHttpRequest、JS内置对象等 
xml 复制代码
##什么是Node.js

Node.js是一个基于Chrome V8引擎的JavaScript运行环境

注意:
·浏览器是JavaScript的前端运行环境,
·Node.js是JavaScript的后端运行环境
·Node.js中无法调用DOM和BOM等浏览器内置函数    
xml 复制代码
##Node.js可以做什么

Node.js 作为一个JavaScript 的运行环境,仅仅提供了基础的功能和 AP!。然而,基于 Node.js 提供
的这些基础能,很多强大的工具和框架如雨后春笋,层出不穷,所以学会了 Node.js ,可以让前端程序员胜
任更多的工作和岗位:

① 基于 Express 框架(http://www.expressjs.com.cn/),可以快速构建 Web 应用
② 基于 Electron 框架(https://electronjs.org/),可以构建跨平台的桌面应用
③ 基于 restify 框架(http://restify.com/),可以快速构建 API接囗项目
④ 读写和操作数据库、创建实用的命令行工具辅助前端开发...

2、Node.js安装

xml 复制代码
##安装包下载:
https://nodejs.org/zh-cn
(LTS是长期稳定版本  、  Current是新特性尝鲜版)

##查看Node.js版本
node -v

//TODO 设置 node_cache   node_global等路径

3、初步使用

xml 复制代码
##如何在Node.js中执行js代码

> 打开终端
> 输入要node执行的js文件路径

如: node d:/hello.js

4、内置模块

4.1、fs文件系统模块

xml 复制代码
fs 模块是 Node.js 官方提供的、用来操作文件的模块。
它提供了一系列的方法和属性,用来满足用户对文件的操作需求。
xml 复制代码
##导入模块

const fs = require('fs');  ##这样node.js会自动查找和下载对应的模块
xml 复制代码
##语法:

fs.readFile(path  [,options],  callback)  读取指定文件中的内容
	#[,options]表示options是可选参数
	#path     文件路径
    #options  编码格式 默认utf8
    #callback 回调函数

fs.writeFile(file,data [,options],callback) 向指定的文件中写入内容 【新写入的内容会覆盖旧内容】
    # file 文件路径  (注意,该方法只能创建文件,不能创建目录)
    # data 待写入的内容
    # options 编码格式  默认utf8
    # callback 回调函数
javascript 复制代码
//导入fs模块
const fs = require('fs');

//读取文件
fs.readFile("../01、初识NodeJS/hello.js", 'utf8', function (err, fileContent) {
  //1、文件读取成功err为null 
  //2、文件读取失败err为错误对象,fileContent为undefined
  if (err != null) {
    console.log("文件读取失败" + err.message);
  } else {
    console.log("文件内容为" + fileContent);
  }
});
javascript 复制代码
fs.writeFile("../01、初识NodeJS2/hellotoo.js", "这就是我想写入的内容", "utf8", function (err) {

  //路径不会自动生成
  //文件会自动生成
  //写入成功err为null,写入失败err为失败对象
  if (err != null) {
    console.log("写入文件错误:" + err.message);
  } else {
    console.log("写入文件成功");
  }
});
xml 复制代码
##注意事项:

上面的./或../操作路径是以执行node命令时所处目录为相对路径的,所以当执行命令的路径不是当前js的
路径就会报错
xml 复制代码
##解决方案:
__dirname   表示当前文件所处的目录

##拓展
./  当前目录
../ 上一级目录
xml 复制代码
##练习:
//导入fs模块
const fs = require('fs');
console.log(__dirname);

//读取文件
fs.readFile(__dirname + "/../01、初识NodeJS/hello.js", 'utf8', function (err, fileContent) {
  //1、文件读取成功err为null 
  //2、文件读取失败err为错误对象,fileContent为undefined
  if (err != null) {
    console.log("文件读取失败" + err.message);
  } else {
    console.log("文件内容为" + fileContent);
  }
});

4.2、path路径模块

xml 复制代码
path 模块是 Node.js 官方提供的、用来处理路径的模块。它提供了一系列的方法和属性,用来满足用户对路径的处理需求。
xml 复制代码
##导入模块

const path = require('path'); 
xml 复制代码
##语法:

path.join([..paths]) 方法,拼接多个路径
  # ..paths 任意多个路径片段
  # ../是有抵消前面路径的作用
  # 返回 拼接好后的路径


path.basename(path[,ext]) 方法,获取路径中的文件名
  # path 文件路径
  # ext 文件扩展名 (会删除掉文件名的后缀)
  # 返回 路径中的最后一部分

path.extname(path)  方法,获取路径中的拓展名
  # path 文件路径
  # 返回拓展名
javascript 复制代码
##练习:
const path = require('path');
const fs = require('fs');

const pathStr = path.join("/a", "/b/c", "../d", "/e");
console.log(pathStr); //输出结果为 /a/b/d/e


//读取文件
fs.readFile(path.join(__dirname, "/..", "/01、初识NodeJS", "/hello.js"), 'utf8', function (err, fileContent) {
  //1、文件读取成功err为null 
  //2、文件读取失败err为错误对象,fileContent为undefined
  if (err != null) {
    console.log("文件读取失败" + err.message);
  } else {
    console.log("文件内容为" + fileContent);
  }
});


let pathStr = "/a/b/c/hello.txt";
const fileName1 = path.basename(pathStr);
console.log(fileName1); //输出hello.txt

const fileName2 = path.basename(pathStr, ".txt");
console.log(fileName2); //输出hello

let extName = path.extname(pathStr);
console.log(extName); //输出.txt

4.3、fs和path综合案例

xml 复制代码
##需求:
将素材.html内容中的  style写入index.css文件,script写入index.js文件,html写入index.html文件。然后运行

素材如下:

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>index首页</title>
  <style>
    html,
    body {
      margin: 0;
      padding: 0;
      height: 100%;
      background-image: linear-gradient(to bottom right, red, gold);
    }

    .box {
      width: 400px;
      height: 250px;
      background-color: rgba(255, 255, 255, 0.6);
      border-radius: 6px;
      position: absolute;
      left: 50%;
      top: 40%;
      transform: translate(-50%, -50%);
      box-shadow: 1px 1px 10px #fff;
      text-shadow: 0px 1px 30px white;

      display: flex;
      justify-content: space-around;
      align-items: center;
      font-size: 70px;
      user-select: none;
      padding: 0 20px;

      /* 盒子投影 */
      -webkit-box-reflect: below 0px -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0%, transparent), to(rgba(250, 250, 250, .2)));
    }
  </style>
</head>

<body>
  <div class="box">
    <div id="HH">00</div>
    <div>:</div>
    <div id="mm">00</div>
    <div>:</div>
    <div id="ss">00</div>
  </div>

  <script>
    window.onload = function () {
      // 定时器,每隔 1 秒执行 1 次
      setInterval(() => {
        var dt = new Date()
        var HH = dt.getHours()
        var mm = dt.getMinutes()
        var ss = dt.getSeconds()

        // 为页面上的元素赋值
        document.querySelector('#HH').innerHTML = padZero(HH)
        document.querySelector('#mm').innerHTML = padZero(mm)
        document.querySelector('#ss').innerHTML = padZero(ss)
      }, 1000)
    }

    // 补零函数
    function padZero(n) {
      return n > 9 ? n : '0' + n
    }
  </script>
</body>

</html>

代码如下:

js 复制代码
const fs = require("fs");
const path = require("path");

//正则表达式 最外层前后//表示这是个正则表达式 /s表示空字符 /S表示非空字符 *表示1次或多次
const regStyle = /<style>[\s\S]*<\/style>/;
const regJs = /<script>[\s\S]*<\/script>/;

fs.readFile(path.join(__dirname, "./source/素材.html"), "utf8", function (err, content) {
  if (err) {
    console.log("读取文件失败" + err.message);
    return;
  }
  //处理style
  dealStyle(content);
  //处理script
  dealScript(content);
  //处理html
  dealHtml(content);
});

//处理style
function dealStyle(htmlContent) {
  let styleContent = regStyle.exec(htmlContent);
  styleContent = styleContent[0].replace("<style>", "").replace("</style>", "");
  fs.writeFile(path.join(__dirname, "./source/index.css"), styleContent, "utf8", function (err) {
    if (err) {
      console.log("写入css内容出错" + err.message);
      return;
    }
    console.log("写入css内容成功.");
  });
};

//处理script
function dealScript(htmlContent) {
  let scriptContent = regJs.exec(htmlContent);
  scriptContent = scriptContent[0].replace("<script>", "").replace("</script>", "");
  fs.writeFile(path.join(__dirname, "./source/index.js"), scriptContent, "utf8", function (err) {
    if (err) {
      console.log("写入js内容出错" + err.message);
      return;
    }
    console.log("写入js内容成功.");
  });
}

//处理html
function dealHtml(htmlContent) {
  //替换style//替换js
  htmlContent = htmlContent.replace(regStyle, '<link rel="stylesheet" href="./index.css">').replace(regJs, '<script src="./index.js"></script>');
  fs.writeFile(path.join(__dirname, "./source/index.html"), htmlContent, "utf8", function (err) {
    if (err) {
      console.log("写入html内容出错" + err.message);
      return;
    }
    console.log("写入html成功");
  });
}

4.4、http模块

xml 复制代码
http 模块是 Node。js 官方提供的、用来创建 web 服务器的模块。通过 http 模块提供的 http.createServer()方法,就能方便的把一台普通的电脑,
变成一台 Web 服务器,从而对外提供 Web 资源服务。

服务器和普通电脑的区别在于,服务器上安装了 web 服务器软件,例如:IIS、Apache 等。通过安装这些服务器软就能把一台普通的电脑变成一台 web 服务器。

在 Node.js 中,我们不需要使用 IIS、Apache 等这些第三方 web 服务器软件。因为我们可以基于 Node.js 提供的http 模块,通过几行简单的代码,
就能轻松的手写一个服务器软件,从而对外提供 web 服务。
xml 复制代码
##语法
const http = require("http");

//创建web服务器实力
const server = http.createServer();

//绑定request事件
server.on('request',(req,res)=>{

})

//启动和监听服务
server.listen('80',()=>{

})
xml 复制代码
#req请求对象

只要服务器接收到了客户端请求,就会调用server.on()为服务器绑定的request时间处理函数

如果想在时间处理函数中访问与客户端相关的【数据】或【属性】,可以使用
req.url  //获取请求路径 
req.method //获取请求方式
xml 复制代码
#res响应对象

res.setHeader('Content-Type','text/html; charser=utf-8');  //防止中文乱码

res.end()  //向客户端发送指定内容,并结束这次请求的处理过程

示例1:

javascript 复制代码
const http = require('http');

//创建一个服务器
const server = http.createServer();

//绑定request事件
server.on('request', (req, res) => {
  let url = req.url;
  let method = req.method;

  //想要使用${}的时候 前后必须用``包住,不能使用""
  let resStr = `我返回的内容:URL请求地址:${url},请求方式:${method}`;
  res.setHeader("Content-Type", "text/html; charset=utf-8");
  res.end(resStr);
});

//启动服务并绑定80端口
server.listen(80, () => {
  console.log("this server is running.  url=>http://127.0.0.1:80");
})

示例2:

js 复制代码
const http = require('http');

//创建服务
const server = http.createServer();

//绑定request事件
server.on('request', (req, res) => {
  let url = req.url;

  let content = "";
  if (url === "/" || url === "/index" || url === "/index.html") {
    content = `<h1>首页</h1>`;
  } else if (url === "/about" || url === "/about.html") {
    content = `<h1>相关页面</h1>`;
  } else {
    content = `<h1>404</h1>`;
  }

  // //设置头部信息
  res.setHeader('Content-Type', "text/html; charset=utf-8");
  // //向客户端发送指定内容,并结束这次请求的处理过程
  res.end(content);
});

//监听80端口
server.listen(8081, () => {
  console.log("this server is running on port 80,  url: http://127.0.0.1:8081");
});

4.5、http综合案例

xml 复制代码
通过http实现 fs和path综合案例中的 clock
javascript 复制代码
const http = require("http");
const fs = require("fs");
const path = require("path");

const server = http.createServer();

server.on('request', (req, res) => {
  let url = req.url;
  let sourcePath = path.join(__dirname, "../03、path模块/source", url);
  fs.readFile(sourcePath, "utf-8", (err, content) => {
    if (err) {
      console.log("文件读取失败" + sourcePath);
      return;
    }
    res.end(content);
  });
});

server.listen(80, function () {
  console.log("server online, port:80,  url:http:127.0.0.1");
})

二、模块化、NPM与包

1、什么是模块化

xml 复制代码
模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程。对于整个系统来说,
模块是可组合、分解相更换的单元。

> 提高了代码的复用性
> 提高了代码的可维护性
> 可以实现按需加载

2、模块化规范

2.1、模块的分类

xml 复制代码
Nodejs 中根据模块来源的不同,将模块分为了3大类,分别是:
》内置模块(内置模块是由 Node.js 官方提供的,例如 fs、path、http等)
》自定义模块(用户创建的每个.js 文件,都是自定义模块)
》第三方模块(由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下载)

2.2、加载模块

xml 复制代码
使用require()方法,可以加载内置模块、自定义模块、第三方模块。

注意:自定义模块加载需要路径,如const custom = require("./custom.js");
## .js 后缀可以省略掉,node会自动加载


使用 require()方法加载其它模块时,会自动执行被加载模块中的代码。
(可以做个测试:  custom.js 自定义模块里  只有 console.log("xxxx");的内容,然后直接引入,
  node执行看下)

2.3、模块作用域

xml 复制代码
和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,
这种模块级别的访问限制,叫做模块作用域。

##有利于防止全局变量被污染

2.4、向外共享模块作用域中的成员

module对象

xml 复制代码
在每个 js 自定义模块中都有一个 module 对象,它里面存储了和当前模块有关的信息

module.exports对象

xml 复制代码
在自定义模块中,可以使用 module.exports 对象,将模块内的成员共享出去,供外界使用.
外界用 require() 方法导入自定义模块时,得到的就是 module.exports 所指向的对象。

测试:

xml 复制代码
## 自定义模块

//外部文件导入此模块的时候自动执行
console.log("这是一个自定义模块");

//通过在module.export对象上挂载属性对外暴露属性
module.exports.username = 'lee';

//通过在module.export对象上挂载方法对外暴露方法
module.exports.sayHi = function () {
  console.log("hi.");
}

let age = 18;
module.exports.myAge = age;

//如果module.exports指向一个对象,那个这个对象会把上面挂载的内容冲掉
// module.exports = {
//   nickName: "ren",
//   sayHello: function () {
//     console.log(this.sayHello);
//   }
// }
javascript 复制代码
const csm = require("./source/myCustom");

console.log(csm);
console.log(csm.myAge);
console.log(csm.username);

csm.sayHi();

exports对象

xml 复制代码
由于 module.exports 单词写起来比较复杂,为了简化向外共享成员的代码,Node 提供了 exports 对象。
默认情况下,exports 和 module.exports 指向同一个对象。

## 最终共享的结果,还是以 module.exports 指向的对象为准。

## 尽量不要在同一个模块同时使用exports和module.exports

2.5、谨记

xml 复制代码
时刻谨记,require()模块时,得到的永远是module.exports 指向的对象

2.6、Node.js中的模块化规范

xml 复制代码
Node.js 遵循了 CommonJS 模块化规范,CommonJS 规定了模块的特性和各模块之间如何相互依赖

CommonJS 规定:
》 每个模块内部,module 变量代表当前模块。
》 module 变量是一个对象,它的 exports 属性(即 module.exports)是对外的接囗。
》 加载某个模块,其实是加载该模块的 module.exports 属性。require() 方法用于加载模块。

3、NPM与包与NRM

3.1、概念

xml 复制代码
1、什么是包
  node.js中的包即第三方模块
xml 复制代码
2、来源
不同于 Node.js 中的内置模块与自定义模块,包是由第三方个人或团队开发出来的,免费供所有人使用。
xml 复制代码
3、为什么需要包
由于 Node.js 的内置模块仅提供了一些底层的 API,导致在基于内置模块进行项目开发的时,效率很低.
包是基于内置模块封装出来的,提供了更高级、更方便的 API,极大的提高了开发效率。
包和内置模块之间的关系,类似于jQuery 和 浏览器内置 API 之间的关系,

3.2、下载

xml 复制代码
国外有一家 IT 公司,叫做 npm,Inc.这家公司旗下有一个非常著名的网站: https://www.npmjs.com/,它是全球最大的包共享平台,你可以从这个网站上搜索到任何你需要的包,只要你有足够的耐心!
xml 复制代码
npm,Inc.公司提供了一个地址为 的服务器,来对外共享所有的包,我们可以从这个服务器上下载自己所需要的包。
xml 复制代码
npm,Inc.公司提供了一个包管理工具,我们可以使用这个包管理工具,从 https://registry.npmjs.org/ 服务器把需要的包下载到本地使用。
这个包管理工具的名字叫做 Node Package Manager(简称 npm 包管理工具),
这个包管理工具随着 Node.js 的安装包一起被安装到了用户的电脑上。

可以在终端中执行 npm -v 命令,来査看自己电脑上所安装的 npm 包管理工具的版本号

3.3、npm

xml 复制代码
##安装包的命令

npm install 包的完整名称
简写:
npm i 包的完整名称

指定版本
npm i 包的完整名称@版本号
xml 复制代码
##步骤
1、使用 npm 包管理工具,在项目中安装格式化第三方模块  (如:时间的包 moment)
2、使用 require() 导入格式化时间的包
3、参考 第三方模块 的官方 API文档对时间进行格式化

示例:

xml 复制代码
1、安装moment
cd G:\LearnSpace\daily-code-package\NodeJS
npm i moment

(项目中会多三个文件:node_modules\pakage-lock.json\package.json)

2、创建time.js

const moment = require("moment");

let dt = moment().format("YYYY-MM-DD HH:mm:ss");
console.log(dt); //2024-12-18 10:10:23

let dt2 = moment().format("YYYY-MM-DD", "2024-12-12");
console.log(dt2); //2024-12-18

3、执行
node time.js

文件:

xml 复制代码
初次装包完成后,在项目文件夹下多一个叫做 node_modules 的文件夹和 package-lock.json和package.json的配置文件。

其中:
》 node_modules 文件夹用来存放所有已安装到项目中的包。
   require()导入第三方包时,就是从这个目录中查找并加载包.

》 package-lock.json 配置文件用来记录 node_modules 目录下的每一个包的下载信息,
   例如:包的名字、版本号、下载地址等
xml 复制代码
##注意:
不要手动修改node_modules或package-lock.json文件中的任何代码,npm包管理工具会自动维护它们

指定版本

xml 复制代码
默认情况下,使用 npm install 命令安装包的时候会自动安装最新版本的包。
如果需要安装指定版本的包,可以在包名之后,通过 @ 符号指定具体的版本,例如:

npm install moment@2.22.2

##注意:
切换版本的时候,不用卸载掉旧版本,直接安装新版本就会把旧版本覆盖掉

3.4、包版本规范

xml 复制代码
如:moment  2.22.2

第一位数字:大版本号
第二位数字:功能版本(新增功能或修改功能)
第三位数字:BUG修复版本

## 版本号提升的规则:
	只要前面的版本号增长了,则后面的版本号归零

3.5、包管理配置文件

xml 复制代码
npm规定,在项目根目录中,必须提供一个叫做 package.json 的包管理配置文件。用来记录与项目有关的一些配置信息。

例如:
》项目的名称、版本号、描述等
》项目中都用到了哪些包
》哪些包只在开发期间会用到
》那些包在开发和部署时都需要用到

快速创建package.json

xml 复制代码
npm 包管理工具提供了一个快捷命令,可以在执行命令时所处的目录中,快速创建 package.json 这个包管理配置文件:

npm init -y

##新建项目文件夹之后执行(只需执行一次)

##注意:
① 上述命令只能在英文的目录下成功运行!所以,项目文件夹的名称一定要使用英文命名,不要使用中文,不能出现空格。
② 运行 npm install 命令安装包的时候,npm 包管理工具会自动把包的名称和版本号,记录到 package.json 中。

dependencies节点

xml 复制代码
package.json 文件中,有一个 dependencies 节点,专门用来记录您使用 npm install命令安装了哪些包,

一次性安装所有包

xml 复制代码
当我们拿到一个剔除了 node_modules 的项目之后,需要先把所有的包下载到项目中,才能将项目运行起来。

npm install

可以运行 npm install 命令(或 npmi)一次性安装所有的依赖包:
//执行 npm install 命令时,npm 包管理工具会先渎取 package.json 中的 dependencies 节点,
//读取到记录的所有依赖包名称和版本号之包管理工具会把这些包一次性下载到项目中

卸载包

xml 复制代码
可以运行 npm uninstall 命令,来卸载指定的包:(同时package.json中dependencies中的对应包配置会被删除)

如:npm uninstall moment

devdependencies节点

xml 复制代码
如果某些包只在项目开发阶段会用到,在项目上线之后不会用到,则建议把这些包记录到 devDependencies 节点中。
与之对应的,如果某些包在开发和项目上线之后都需要用到,则建议把这些包记录到 dependencies 节点中。

// 安装指定的包,并记录到devDependencies 节点中
npm i 包名 -D
或
npm i -D 包名

//注意:上述命令是简写形式,等价于下面完的写法
npm install  包名  --save-dev
或
npm install  --save-dev 包名


【devdependencies中的包被称为 开发依赖包】
【dependencies中的包被称为  核心依赖包】

3.6、包下载速度慢的问题

xml 复制代码
在使用 npm 下包的时候,默认从国外的 https://registny.npmis.org/服务器进行下载,此时,网络数据的传输需要经过漫长的海底光缆,因此下包速度会很慢。

##官网
https://registry.npmjs.org/

## 淘宝NPM镜像服务器
https://registry.npmmirror.com/
https://registry.npm.taobao.org

##GitHub
https://npm.pkg.github.com/

##华为
https://mirrors.huaweicloud.com/repository/npm/

##腾讯
https://mirrors.cloud.tencent.com/npm/
xml 复制代码
##永久修改

//设置淘宝镜像
npm config set registry https://registry.npmmirror.com

//查看当前使用的镜像源
npm config get registry

nrm

xml 复制代码
为了更方便的切换下包的镜像源,我们可以安装 nrm 小工具,利用 nrm 提供的终端命令,快速查看和切换下包的镜像源。

# 通过 npm 包管理器,将 nrm 安装为全局可用的工具
	npm i nrm -g
# 查看所有可用的镜像源
	nrm ls
#将下包的镜像源切换为 taobao 镜像
	nrm use taobao

3.7、包的分类

xml 复制代码
## 开发依赖包
devdependencies中的包被称为 开发依赖包

## 核心依赖包
dependencies中的包被称为  核心依赖包

3.8、全局包

xml 复制代码
##全局包
在执行 npm install 命令时,如果提供了-g 参数,则会把包安装为全局包,

全局包会被默认安装到 C:\Users\${用户名}\AppData\Roaming\npm\node_modules目录下

//安装全局包
npm i 包名 -g

//卸载全局包
npm uninstall 包名 -g
xml 复制代码
##注意:
只有"工具性质"的包,才有全局安装的必要性。因为它们提供了好用的终端命令。

3.9、包结构

xml 复制代码
》 包必须以单独的目录而存在
》 包的顶级目录下要必须包含 package.json 这个包管理配置文件
》 package.json 中必须包含 name,version,main 这三个性,分别代表包的名字、版本号、包的入口。

##注意:
包的入口: require("xxx") 中xx指向的就是main属性所指向的文件

3.10、开发属于自己的包

xml 复制代码
1、新建一个包目录
如:myNode-tools

2、在目录下新建三个文件
   package.json //包管理配置文件
   index.js //main入口文件
   README.md //包说明文档
xml 复制代码
3、初始化package.json文件

{
  "name": "myNode-tools",
  "version": "1.0.0",
  "main": "index.js",
  "description": "提供了格式化时间功能",
  "keywords": [
    "dateFormat",
    "escape"
  ],
  "license": "ISC"
}
xml 复制代码
4、写index.js文件

function dateFormat(dateStr) {
  let dt = new Date(dateStr);

  let y = padZero(dt.getFullYear());
  let m = padZero(dt.getMonth());
  let d = padZero(dt.getDay());

  let h = padZero(dt.getHours());
  let mi = padZero(dt.getMinutes());
  let s = padZero(dt.getSeconds());

  return `${y}-${m}-${d} ${h}-${mi}-${s}`;
}

function padZero(num) {
  return num > 9 ? num : '0' + num;
}

//对外暴露方法
module.exports = {
  dateFormat
};
xml 复制代码
5、使用

//测试自定义组件
//const myNodeTools = require("./../myNode-tools/index");
const myNodeTools = require("./../myNode-tools"); //默认通过package.js的main 会找到index.js

let dt = myNodeTools.dateFormat(new Date());
console.log(dt);

优化--模块化拆分

xml 复制代码
##如果index.js中方法比较多,就需要把方法拆分出来放在多个文件中,进行模块化拆分

》将格式化时间的功能,拆分到src->dateFormat.js中
》将处理 xxx的功能,拆分到src->xxx.js中
》在 index.js 中,导入两个模块,得到需要向外共享的方法
  const date = require("./dateFormat");
  const xxx = require("./xxx");

》在 index.js 中,使用 module.exports 把对应的方法共享出去
  module.exports = {
    ...date,
    ...xxx
  }

//...对象 的写法是ES6中的写法,是将对象展开
xml 复制代码
6、编写README.md文档
...

3.11、发布npm包

xml 复制代码
1、注册账号
》 访问 https://www.npmjs.com/ 网站,点击 sign up 按钮,进入注册用户界面
》 填写账号相关的信息:Full Name、PublicEmail、Username、Password
》 点击 Create an Account 按钮,注册账号
》 登录邮箱,点击验证,进行账号激活
xml 复制代码
2、登录账号(终端中登录)
npm login
输入账号
输入密码
输入邮箱

#注意:
要先将 npm的地址 设置为官方的地址
npm config set https://registry.npmjs.org/
或
nrm use npm
xml 复制代码
3、发包
将终端切换到【包的根目录】之后,运行 npm publish 命令,即可将包发布到 npm 上(注意:包名不能雷同)
xml 复制代码
4、删除已发布的包

运行 

npm unpublish 包名 --force 

命令,即可从 npm 删除已发布的包.

##注意:
① npm unpublish 命令只能删除 72 小时以内发布的包
② npm unpublish 删除的包,在 24 小时内不允许重复发布

3.12、好用的包总结

xml 复制代码
## i5ting_toc

	可以把md文件转成html文件
    i5ting_toc -f  md文件路径 -o    //-o是打开html文件

4、模块的加载机制

4.1 优先从缓存中加载

xml 复制代码
模块在第一次加载后会被缓存。
这意味着多次调用 require() 不会导致模块的代码被执行多次。

注意:不论是内置模块、用户自定义模块、还是第三方模块,它们都会优先从缓存中加载,从而提高模块的加载效率,

4.2 内置模块的加载机制

xml 复制代码
内置模块是由 Node.js 官方提供的模块,内置模块的加载优先级最高,

例如,require("fs")始终返回内置的 fs 模块,即使在 node modules 目录下有名字相同的包也叫做 fs。

4.3自定义模块的加载机制

xml 复制代码
使用 require() 加载自定义模块时,必须指定以/或/开头的路径标识符。   (自定义模块要指定路径)

在加载自定义模块时,如果没有指定./或..
这样的路径标识符,则 node 会把它当作内置模块或第三方模块进行加载。


同时,在使用require() 导入自定义模块时,如果省略了文件的扩展名,则 Node.js 会按顺序分别尝试加载以下的文件:

①按照确切的文件名进行加载
② 补全 js 扩展名进行加载
③ 补全 json 扩展名进行加载
④ 补全.node 扩展名进行加载
⑤ 加载失败,终端报错

4.4 第三方模块的加载机制

xml 复制代码
  如果传递给 require()的模块标识符不是一个内置模块,也没有以'/或.../"开头,则 Node.js 会从当前模块的
父目录开始,尝试从/node modules 文件夹中加载第三方模块。
  如果没有找到对应的第三方模块,则移动到再上一层父目录中,进行加载,直到文件系统的根目录.

例如,假设在'C:\Users\itheima\project\foo,js'文件里调用了 require(tools"),则 Node.js 会按以下顺序查找:

C:\Users\lee\project\node_modules\tools
C:\Users\lee\node_modules\tools
C:\Users\node_modules\tools
C:\node_modulesltools

4.5 目录作为模块

xml 复制代码
当把目录作为模块标识符,传递给require0进行加载的时候,有三种加载方式:

》在被加载的目录下查找一个叫做 package.json 的文件,并寻找 main 属性,作为 require()  加载的入口

》如果目录里没有 package,json 文件,或者 main 入口不存在或无法解析,则 Node.js 将会试图加载目录下的 indexjs 文件。

》如果以上两步都失败了,则 Node.js 会在终端打印错误消息,报告模块的缺失:rror: Cannot find module'xxx
相关推荐
OpenTiny社区1 小时前
Node.js 技术原理分析系列 4—— 使用 Chrome DevTools 分析 Node.js 性能问题
前端·开源·node.js·opentiny
huangfuyk1 小时前
使用Node.js从零搭建DeepSeek本地部署(Express框架、Ollama)
node.js·express·ollama·deepseek
flashier2 小时前
C语言 进阶指针学习笔记
c语言·笔记·学习
大白的编程日记.2 小时前
【Linux学习笔记】Linux基本指令分析和权限的概念
linux·笔记·学习
螺旋式上升abc2 小时前
GO语言学习笔记
笔记·学习·golang
W起名有点难3 小时前
前端学习——CSS
前端·css·学习
Moonnnn.4 小时前
51单片机——汇编工程建立、仿真、调试全过程
汇编·笔记·嵌入式硬件·学习·51单片机
EnigmaCoder4 小时前
蓝桥杯刷题周计划(第二周)
学习·算法·蓝桥杯
火龙谷5 小时前
hadoop第3课(hdfs shell常用命令)
hadoop·hdfs·npm
华洛5 小时前
老板要求接入DeepSeek,哪家提供的服务强?
前端·javascript·node.js