day3.模块化

  1. 模块化的好处

    1.1什么是模块化?

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

    编程领域的模块化思想:

    ​ 编程领域中的模块化,就是遵守固定的规则,把一个大文件拆成独立并相互依赖的多个小模块

    把代码进行模块化拆分的好处:

    • 提高了代码复用性
    • 提高了代码的可维护性
    • 可以实现按需加载
    1.2模块化的规范

    模块化规范就是对代码进行模块化拆分与组合事,需要遵守的那些规则

    列如:

    • 使用什么样的语法格式来引用模块
    • 在模块中使用什么样的语法格斯向外暴露成员

    模块化规范的好处:大家都遵守同样的莫夸化规范你写代码,降低了沟通的成本,极大方便了各模块之间的相互调用。

  2. Node.js中模块的三大分类

    Node.js中根据模块的来源不同,将模块分为了三大类,分别是:

    • 内置模块(由node.js官方提供的,例如fspath、http等)
    • 自定义模块(用户创建的.js的文件)
    • 第三方模块(由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用时需要提前下载)
    2.1加载模块

    使用require()方法,可以加载需要的内置模块、用户自定义模块、第三方模块进行调用。

    // 1.加载内置的fs模块
    const fs = require( 'fs ')
    // 2.加载用户的自定义模块
    const custom = require( './ custom.js ')
    // 3.加载第三方模块
    const moment = require( ' moment ' )
    

    注:

    • 使用require()方法加载其他模块时,会执行被加载模块中的代码。
    • 在使用require()方法,可以不加后缀名
    2.2模块作用域

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

    好处:

    • 防止全局变量的污染
    2.3向外共享模块作用域中成员
    1. module对象:

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

在这里插入图片描述

  1. module.exports对象
    const newObj ={
        name:"lisi",
        getName:function(){
            console.log("lisi")
        }
    }
    
    module.exports= newObj;
    

注意:

  • 使用require()方法导入模块时,导入的结果,以最后module.exports指向的对象为准
3.exports对象

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

module.exports.name = "zhangsan";
exports = {
    age:18,
    name:'lisi'
}
// 输出结果:{ name: 'zhangsan' }

注意:

  • 为了防止混乱,建议大家不要在同一个模块中同时使用exports和module.exports

  • 时刻记住,使用require()模块时,导入的永远是module.exporsts指向的对象

2.4Node.js中的模块化规范

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

  1. CommonJS规定的内容

    CommonJS规定:

    1. 每个模块内部,module变量代表当前模块。
    2. module变量是一个对象,它的exports属性(即module.exports)是对外的接口
    3. 加载某个模块,其实是加载该模块的module.exports属性。require()方法用于加载模块
  2. npm与包

    1. 什么是包?

      Node.js中的第三方模块又叫做包。不同于Node.js中的内置模块与自定义模块,包是由第三方个人或团队开发出来的,免费供所有人使用

      Tip:Node.js中的包都是免费且开源的,不需要付费即可下载使用

    2. 为什么需要包?

      由于Node.js的内置模块仅提供了一些底层的API,导致在基于内置模块进行项目开发时的效率很低,包是基于内置模块封装出来的,提供了更高级、更方便的API,极大地提高了开发效率。包和内置模块之前的关系,类似于JQuery和浏览器内置API之间的关系

    3. 哪里下载包?

      npm,lnc.公司旗下的包共享平台,它还提供了一个地址为https://registry.npmjs.org/的服务器,来共享所有的包,我们可以从这个服务器下载自己所需要的包

      tips:

      1. 从https://www.npmjs.com/网站搜索自己所需要的包
      2. 从https://registry.npmjs.org/下载自己的包
    4. 如何下载包?

      npm,lnc.公司提供了一个包管理工具,我们可以使用这个包管理工具,从https://registry.npmjs.org/服务器把需要的包下载到本地使用。

      这个包管理工具的名字叫做Node Package Manager (简称npm包管理工具),这个包管理工具随着Node,js的安装包一起被安装到了用户的电脑上。

    5. 在项目中安装包的命令
      npm install 完整的包名称
      

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

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

      package-lockjson配置文件用来记录node modules目录下的每一个包的下载信息,例如包的名字、版本号、下载地址等。

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

      npm install moment @2.29.2
      

      注:不要手动修改node_modules或package-lock.json 文件中的代码,npm包管理工具跟自动维护它们

    6. 包管理配置文件

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

      例如:

      • 包的名称、版本号、描述等
      • 项目中用到了那些包
      • 哪些包只在开发期间会用到
      • 哪些包在开发和部署时都会用到
    7. 多人协助开发问题

      第三方包的体积过大,不方便团队成员之间共享项目源代码,只需要上传源代码。

      在项目根目录中,创建一个叫做package.json 的配置文件,即可用来记录项目中安装了哪些包。从而方便剔除node_modules目录之后,在团队成员之间共享项目的源代码。

      注意:今后在项目开发中,一定要把 node_modules文件夹,添加到.gitignore忽略文件中。

      新建项目文件夹之后,快速创建package.json:

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

      npm init -y 
      

      注意:

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

      一次性安装剔除了node_module中的所有包:

      npm install
      

      执行npm install 命令时,npm包管理工具会先读取package.json中的devDependencies结点,读取到记录的所有依赖包名称和版本号之后,npm包管理工具会把这些包一次性下载到项目中

    8. devDependencies结点与dependencies结点

      package.json中,有一个dependencies结点,专门用来记录您使用的npm install 命令安装了哪些包

      如果某些包旨在项目开发接单才会用到,项目上线之后不会用到,则建议吧这些包记录到devDependencies节点中。

      与之对应的额,如果某些包在开发和项目上线之后都需要用到,则建议把这些包记录到dependencies结点

      //安装指定的包,并记录到devDependencies结点中
      npm i/install 包名 -D
      //等价于下面完整写法:
      npm install 包名 --save-dev
      
    9. 解决下载包速度慢的问题

      淘宝npm镜像服务器:淘宝在国内搭建了一个服务器,专门把国外官方服务器上的包同步到国内的服务器,然后在国内提供下包的服务。从而极大的提高了下包的速度。

      切换npm的下包镜像源:

      #查看当前的下包镜像源
      npm config get registry
      #将下包的镜像源切换为淘宝镜像源
      npm config set registry=https://registry.npm.taobao.org/
      #检查镜像源是否下载成功
      npm config get registry
      

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

      如何安装nrm工具:

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

      注:npm uninstall 命令执行成功后,会把卸载的包,自动从package.json中的dependencies中移除

  3. 规范的包结构

    开发自己的包

    1. 初始化package.json
      {
          "name": "module-tools",
          "version": "1.0.0",
          "main": "index.js",
          "description": "提供了格式化时间,HTMLEscape相关的功能",
          "keywords": [
              "module-tools",
              "dateFormat",
              "escape"
          ],
          "license": "ISC"
      }
      
    2. 在index.js中定义自己的方法
      // 这是包的入口文件
      function dateFormat(dateStr) {
          const dt = new Date(dateStr);
      
          const y = dt.getFullYear();
          const m = FixZero(dt.getMonth() + 1);
          const d = FixZero(dt.getDate());
      
          const hh = FixZero(dt.getHours());
          const mm = FixZero(dt.getMinutes());
          const ss = FixZero(dt.getSeconds());
      
          return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
      }
      // 补零函数
      function FixZero(n) {
          return n > 9 ? n : '0' + n;
      }
      // 向外暴露需要的成员
      module.exports = {
          dateFormat
      }
      
    3. 将不同的功能进行模块化拆分
      // 这是包的入口文件
      
      const dateFormat =  require("../module_tools/src/dateFormat")
      const escape = require("../module_tools/src/htmlEscape")
      
      // 向外暴露需要的成员
      module.exports = {
          ...dateFormat,...escape
      }
      
    4. 编辑包的说明文档

      包根目录中的README.md文件,是包的使用说明文档。通过它,我们可以事先把包的使用说明,以markdown的格式写出来,方便用户参考。

      README文件中具体写什么内容,没有强制性的要求;只要能够清晰地把包的作用、用法、注意事项等描述清楚即可。例如上述例子包涵:

      • 安装方式
      • 导入方式
      • 格式化时间//函数的使用方式
      • 转义HTML中的特殊字符
      • 还原HTML中的特殊字符
      • 开源协议
    5. 发布包

      1.注册npm账号
      ①访问https://www.npmjs.com/网站,点击 sign up按钮,进入注册用户界面

      ​ ②填写账号相关的信息:Full Name、Public Email、Username、Password

      ​ ③点击Create an Account按钮,注册账号

      ​ ④登录邮箱,点击验证链接,进行账号的验证

      2.登录到本地npm

      npm login
      

      3.把包发布到npm 上

      npm publish
      

      ​ 将终端切换到包的根目录之后,运行npm publish 命令,即可将包发布到npm上(注:包名不能雷同)

      4.删除已发布的包

      npm unpublish 包名 --force
      

      ​ 运行npm unpublish 包名 --force命令,即可从npm删除已发布的包

      注:

      • npm unpublish 命令只能删除72小时以内发布的包
      • 通过npm unpublish 删除的包,在24小时以内不允许再重复发布
      • 发布包的时候要慎重,尽量不要往npm上发布没有意义的包
  4. 模块的加载机制

    6.1优先从缓存中加载

    ​ 模块第一次加载后,会被缓存。因此多次调用require()不会导致模块的代码被执行多次。

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

    6.2内置模块的加载机制

    ​ 内置模块是由Node.js官方提供给的模块,内置模块的加载优先级最高

    6.3自定义模块的加载机制

    ​ 使用require()加载自定义模块时,必须指定以**./或者…/开头的路径标识符。在加载自定义模块时,如果没有指定./或者…/这样的路径标识符,则Node会把它当做内置模块第三方模块**进行加载。

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

    1. 按照确切的文件名进行加载
    2. 补全.js 扩展名进行加载
    3. 补全.json扩展名进行加载
    4. 补全.node扩展名进行
    5. 加载加载失败,终端报错
    6.4第三方模块的加载机制

    ​ 如果传递给require()的模块的标识符不是一个内置模块,也没有以“./”或“…/”开头,则Node.js会从当前模块的父目录开始尝试,从/node_modules文件夹加载第三方模块

    如果没有找到对应的第三方模块,则一定到再上一层父目录中,进行查找,直至找到文件系统的根目录。

    6.5目录(文件夹)作为模块

    当把目录(文件夹)作为模块标识符,传递给require()进行加载的时候,有三种加载方式:

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

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

加载加载失败,终端报错

6.4第三方模块的加载机制

​ 如果传递给require()的模块的标识符不是一个内置模块,也没有以“./”或“…/”开头,则Node.js会从当前模块的父目录开始尝试,从/node_modules文件夹加载第三方模块

如果没有找到对应的第三方模块,则一定到再上一层父目录中,进行查找,直至找到文件系统的根目录。

6.5目录(文件夹)作为模块

当把目录(文件夹)作为模块标识符,传递给require()进行加载的时候,有三种加载方式:

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

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

③如果以上两步都失败了,则 Node.js 会在终端打印错误消息,报告模块的缺失: Error: Cannot find module ‘XXX’

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值