什么是模块?在Node.js中,每一个文件都被视为一个模块来处理

Node.js模块化

模块化简介

什么是模块?

在Node.js中,每一个文件都被视为一个模块来处理

什么是模块化?

  1. 项目是由很多个模块文件组成的,每个模块承担不同的职责,使用标准语法导出和导入模块进行使用。这样的代码组织结构就叫做模块化

好处:提高代码复用性,按需加载,独立作用域

Node.js内置的模块,称之为 内置模块

程序员自己编写的js文件,称之为自定义模块

CommonJS 标准

什么是CommonJS标准?

  • CommonJS 是一个JavaScript 创建模块化代码的规范,是由Node.js作者制定的
  • 目的: 规定如何定义模块以及如何通过这些模块共享代码

基于CommonJS标准下,模块的基本结构如下

  1. 定义模块:每个文件都被视为一个独立的模块。你可以在这个文件中定义变量、函数等js代码,并且不会暴露到全局作用域中

    const baseURL = 'http://hmajax.itheima.net'
    function sum(num1,num2) {
    return num1 + num2
    }

  2. 导出模块 :如果希望从一个模块中导出一些值,可以使用 module.exports 例如:

    const baseURL = 'http://hmajax.itheima.net'
    function sum(num1,num2) {
    return num1 + num2
    }

    /* 将模块中的私有变量导出供外部使用
    module.exports = {
    对外属性名: 模块内私有变量
    }
    */
    module.exports = {
    url: baseURL,
    getSum:sum
    }

  3. 导入模块 :要使用其他模块导出的内容,需要使用 require 函数来加载它们。例如:

    /*
    加载并使用common.js模块
    const 变量名 = require('模块名或路径')
    */
    const common = require('./common.js');

模块名或路径:

内置模块 :Node.js 提供了一些内置模块,可以直接通过 require 来使用,无需带路径,直接写名字(例如:fs,path,http)const fs = require('fs')

**自定义模块:**导入自定义模块的时候,需要带上模块文件路径(例如:./common.js)

const common = require('./common.js');

模块缓存 :当一个模块第一次被加载时,它会被执行并且结果会被缓存。后续对同一模块的所有 require 调用都会返回缓存的结果,而不会再次执行该模块。

演示代码:

复制代码
/**
 * 目标:基于 CommonJS 标准语法,封装属性和方法并导出
 */
const baseURL = 'http://hmajax.itheima.net'
function sum(num1,num2) {
  return num1 + num2
}

// 导出
module.exports = {
  url: baseURL,
  getSum: sum
}

/**
 * 目标:基于 CommonJS 标准语法,导入工具属性和方法使用
 */
// 导入
const obj = require('./common.js')
console.log(obj)
console.log(obj.getSum(1,2))

node index.js

ECMAScript标准

  • CommonJS 规范是 Node.js 环境中默认的
  • 随着 ECMAScript 标准的发展,在2015年正式发布的 ES6中引入了原生的模块系统
    • 导入模块使用 import xx from '模块路径' 方式 (CommonJS使用的是require()方式)
    • 导出模块使用 export default{ } 或者export (CommonJS使用module.exports ={} )

注意:Node.js 默认支持 CommonJS 标准语法

如需使用 ECMAScript 标准语法,在运行模块所在文件夹新建 package.json 文件,并设置 { "type" : "module" }

默认导出和导入

默认导出允许你从一个模块中导出一个默认值。每个模块只能有一个默认导出

复制代码
const baseURL = 'http://hmajax.itheima.net'
function sum(num1,num2) {
  return num1 + num2
}

// 导出
export default {
  url: baseURL,
  getSum: sum
}

import common from './common.js'

console.log(common.url)
console.log(common.getSum(100,200));

命名导出和导入

命名导出允许你从一个模块中导出多个值,如变量、常量、函数等,并且每个导出都有一个名字

复制代码
export const baseURL = 'http://hmajax.itheima.net'
export function sum(num1,num2) {
  return num1 + num2
}

// 要导入这些命名导出,你需要使用大括号 {} 来指定你想要导入的名称
import {baseURL,sum as getSum} from './common.js'

console.log(baseURL)
console.log(getSum(100,200));

混合使用

一个模块可以同时拥有命名导出默认导出。在这种情况下,你可以根据需要选择性地导入

复制代码
export const baseURL = 'http://hmajax.itheima.net'
export default function sum(num1,num2) {
  return num1 + num2
}


import sum, {baseURL} from './common.js'
console.log(baseURL)
console.log(sum(100,200));

模块化总结

  1. Node.js 模块化:把每个文件当做一个模块,独立作用域,按需加载,使用特定标准语法导出和导入使用

CommonJS 标准:一般应用在 Node.js 项目环境中

ECMAScript 标准:一般应用在前端工程化项目中,比如vue项目

包的概念

包的存放地址: npmjs.com

什么是Node.js中的包

在 Node.js 中,"包"是一个可以被重复使用的代码集合,它包含了一组相关的文件,旨在提供一组特定的功能。

**大白话:**包是一个文件夹,里面存放了一堆文件供使用,用package.json描述这个包的作用

Node.js 的包是通过 npm(Node Package Manager)进行管理和分发的

npm init -y 可以创建一个 package.json文件 (如果已经有package.json则跳过此)

注意 -y 就是所有选项用默认值,所在文件夹不要有中文/特殊符号,建议英文和数字组成,因为 npm 包名限制建议用英文和数字或者下划线中划线

创建包演示

**需求:**封装一个工具库模块,功能包含

  1. 封装获取数组结果和 getArraySum函数 -> arr.js
  2. 封装字符串验证方法 checkUserName和checkPassWord 用来检验用户名和密码是否合法 -> str.js
  3. 形成一个软件包,并在 index.js 中统一导出后被外部导入使用

结构如下:

步骤:

  1. 创建文件夹utils,在里面使用 npm init -y 生成package.json文件
  2. 创建/utils/lib文件夹,下面创建 arr.js和str.js两个文件,分别写入功能函数后使用module.exports导出
  3. 在utils中创建index.js文件,分别使用 require导入 arr.js和str.js两个模块
  4. 使用npm init -y生成package.json文件
  5. 在use.js中使用 require('./utils')导入包,调用包中函数进行测试
  6. 在cmd中使用 node use.js执行后观察结果

utils/lib 相关代码在素材里准备好了,只需要自己在 utils/index.js 统一出口进行导出

复制代码
/**
 * 目标:封装数组常用的方法
 */
// 数组求和函数
function getArraySum(arr){
  let sum = 0 
  arr.forEach(item=>{
    sum+=item
  })
  return sum
}

module.exports = {
  getArraySum
}

/**
 * 目标:封装校验用户名和密码长度的函数
 * 要求:用户名最少 8 位,密码最少为 6 位
 */
function checkUserName(username) {
  const reg = /^[a-zA-Z0-9]{8,}$/
  return reg.test(username)
}

function checkPassWord(password) {
  const reg = /^[a-zA-Z0-9]{6,}$/
  return reg.test(password)
}

module.exports = {
  checkUser: checkUserName,
  checkPwd: checkPassWord
}

/**
 * 本文件是,utils 工具包的唯一出口
 * 作用:把所有工具模块方法集中起来,统一向外暴露
 */
const { getArraySum } = require('./lib/arr.js')
const { checkUser, checkPwd } = require('./lib/str.js')

// 统一导出所有函数
module.exports = {
  getArraySum,
  checkUser,
  checkPwd
}

在use.js中使用utils 导入软件包文件夹使用(注意:这次导入的是包文件夹,不是模块文件)

复制代码
/**
 * 目标:导入 utils 软件包,使用里面封装的工具函数
 */
const obj = require('./utils')
console.log(obj)
const result = obj.getArraySum([10, 20, 30])
console.log(result)

Node.js包的分类

项目包:编写项目需求和业务逻辑的文件夹(通常在搞前端基建的时候才用的多)

软件包:封装工具和方法进行使用的文件夹(一般使用 npm 管理)

  • 本地软件包:作用在当前项目,封装的属性/方法,供项目调用编写业务需求,通过 npm i 包名安装
  • 全局软件包:作用在所有项目,一般封装的命令/工具,支撑项目运行 ,通过 npm i 包名 -g安装

npm软件包管理器

npm 简介链接: 软件包管理器,用于下载和管理 Node.js 环境中的软件包

npm 管理包

如果我们要自己创建一个包,则可以使用 npm 初始化package.json,这个文件可以用来描述这个包的信息

初始化清单文件: npm init -y (得到 package.json 文件,有则跳过此命令)

注意 -y 就是所有选项用默认值,所在文件夹不要有中文/特殊符号,建议英文和数字组成,因为 npm 包名限制建议用英文和数字或者下划线中划线

npm下载包(必须掌握)

    1. 下载软件包命令:npm i 软件包名称
    1. 使用软件包

需求:使用 npm 下载 dayjs 软件包到本地项目文件夹中,引入到 index.js 中格式化日期打印,运行观察效果

npm i dayjs

如果在一个空文件夹中使用npm i之前,需要先npm init 初始一个package.json,否则下不成功

npm安装所有依赖

  1. 我们拿到了一个别人编写的项目,但是没有 node_modules,项目能否正确运行?

不能,因为缺少了项目需要的依赖软件包,比如要使用 dayjs 但是你项目里没有这个对应的源码,项目会报错的

  1. 为何没有给我 node_modules?

因为每个人在自己的本机使用 npm 下载,要比磁盘间传递要快(npm 有缓存在本机)

  1. 如何得到需要的所有依赖软件包呢?

直接在项目目录下,运行终端命令:npm i 即可安装 package.json 里记录的所有包和对应版本到本项目中的 node_modules

npm全局软件包-nodemon

  1. 软件包区别:
    • 本地软件包:当前项目内使用,封装属性和方法,存在于 node_modules
    • 全局软件包:本机所有项目使用,封装命令和工具,存在于系统设置的位置
  1. nodemon 作用:替代 node 命令,检测代码更改,自动重启程序
  1. 使用:
    1. 安装:npm i nodemon -g (-g 代表安装到全局环境中)
    1. 运行:nodemon 待执行的目标 js 文件
  1. 需求:使用 nodemon 命令来启动素材里准备好的项目,然后修改代码保存后,观察终端重启应用程序

Node.js 常用命令(包相关)

Express快速搭建 Web 服务

  1. Express定义链接: 基于 Node.js 平台,快速,开放,极简的 Web 开发框架

  1. 作用:使用 express 本地软件包,快速搭建 Web 服务(基于 http 模块)
  1. 功能:开发 Web 服务,提供数据接口,提供网页资源供浏览器使用
  1. 需求:基于 express 编写 Web 服务,对 get 请求方法和 / 路径监听,有人请求返回一段提示字符串
  1. 使用:
    1. 下载 express 本地软件包到项目中 npm i express
    1. 导入 express 创建 Web 服务对象 const express = require('express')
    1. 监听请求方法和请求路径,返回一段提示字符串
      1. const server = express() server.get() server.post()
    1. 对其他请求方法和请求路径,默认返回 404 提示server.all('*')
    1. 监听端口号,启动 Web 服务,在浏览器请求测试
  1. 代码如下:

    /**

    • 目标:基于 express 本地软件包,开发 Web 服务,返回资源给请求方
      */
      // 1. 下载 express 软件包
      // 2. 导入并创建 Web 服务对象
      const express = require('express')
      const server = express()

    // 3. 监听请求的方法和请求的资源路径
    server.get('/', (req, res) => {
    res.send('你好,欢迎使用 Express')
    })

    // 4. 监听任意请求的方法和请求的资源路径
    server.all('*', (req, res) => {
    res.status(404)
    res.send('你要访问的资源路径不存在')
    })

    // 5. 监听端口号,启动 Web 服务
    server.listen(3000, () => {
    console.log('Web 服务已启动')
    })

Express案例-获取省份列表接口

  1. 需求:基于 express,开发提供省份列表数据的接口
  1. 步骤:监听 get 请求方法的 /api/province 路径,并读取 province.json 里省份数据返回给请求方

  2. 核心代码:

    // 监听 get 请求方法,监听资源路径 /api/province,就读取 province.json 省份数据返回
    server.get('/api/province', (req, res) => {
    fs.readFile(path.join(__dirname, 'data/province.json'), (err, data) => {
    res.send(data.toString())
    })
    })

浏览器的同源策略

  1. 同源策略:它限制一个源的文档或者加载的 JS 脚本,与另外一个源的资源进行交互,帮助我们阻隔恶意文档,减少被攻击的媒介
  1. 例如:被钓鱼网站收集信息,用 AJAX 发起恶意请求,传递转账信息到银行服务器(跨站伪造请求攻击)
  1. 源指的是:协议,域名,端口号的组成
  1. 同源:网页加载时所在源,和 AJAX 请求时的源(协议,域名,端口号)全部相同即为同源,所以刚刚的例子并不是同源访问,他们的域名是不同的
  1. 作用:浏览器的同源策略,保护浏览器中网站的安全,限制 AJAX 只能向同源 URL 发起请求

跨域问题

  1. 跨域:从一个源的文档/脚本,加载另一个源的资源产生了跨域
  1. 例如:网页文档打开时所在源和 AJAX 访问的源(协议,域名,端口)有一个不同,就发生了跨域访问
  1. 网页出现跨域访问时,会在浏览器控制里报错如下:

Access to XMLHttpRequest 意思为:XHR 链接出了问题,从一个源(http://localhost:5500 跨域访问 http://localhost:3000)

  1. 需求:在 LiveServer 的 Web 服务启动网页,用 AJAX 访问本机 Web 服务提供的省份列表接口,体验下跨域问题,index.html 代码如下:

    // 目标:请求本机 Web 服务提供的省份列表数据
    axios({
    url: 'http://localhost:3000/api/province',
    // method: 'get'
    }).then(res => {
    console.log(res)
    }).catch(err => {
    console.log(err)
    })

跨域问题-解决方案1-CORS

  1. 目标:前后端分离的项目,前端和后端不在一个源,还要保证数据通信
  1. 解决:采用 CORS (跨域资源共享),一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其他源(域、协议或端口),来访问加载服务器上的资源

  2. 思路:

    • 服务器端:设置 Access-Control-Allow-Origin 响应头字段为*,允许除了它自己以外的源来访问自己的资源
    • 前端:正常发起 AJAX 请求,无需额外操作
  1. 步骤:
    1. 下载 cors 本地软件包
    1. 导入 cors 函数
    1. 使用 server.use() 给 Web 服务添加插件功能
    1. 把 cors 函数调用传入给 Web 服务,启动测试
  1. 设置响应头代码

    // 2. 导入 cors 函数
    const cors = require('cors')
    // 3. 使用 server.use() 给 Web 服务添加插件功能
    server.use(cors())

静态资源访问

  1. 让后端 Web 服务,既可以提供数据接口,也可以返回静态资源(例如数据中的图片地址)
  1. 代码:express 设置暴露 public 文件夹作为静态资源目录,供浏览器直接访问,可以访问里面的 html 网页

    // 暴露指定的文件夹,让前端可以直接拼接路径和资源名字来访问
    server.use(express.static(path.join(__dirname, 'public')))

总结

  1. 模块化
    1. 模块 -> 一个文件就是一个模块
    2. 模块化 -> 各个模块职责明确,相互协作的一个过程
  1. 模块化标准
    1. Commonjs标准
      1. 导出标准 -> module.exports = {}
      2. 导入标准 -> require
    1. ES6模块化标准
      1. 导出标准 ->【默认导出标准】 export default{}
      2. 导入标准 -> import 变量名 from '模块路径'
相关推荐
孤独得猿1 小时前
[linux复习]——多线程
java·linux·jvm
小灿同学啊2 小时前
vmware虚拟机上Ubuntu或者其他系统无法联网的解决方法
linux·ubuntu
zmHelloWorld2 小时前
sublime text快捷键以及常见使用技巧
编辑器·sublime text
假如我年华正好2 小时前
【教程】MacBook 安装 VSCode 并连接远程服务器
linux·服务器·ide·vscode·ssh·macbook
1296004522 小时前
配置VScode时的一些注意点
ide·vscode·编辑器
wodeshijiexialey2 小时前
Linux系统(Ubuntu和树莓派)的远程操作练习
linux·运维·ubuntu
还没想好取啥名3 小时前
Linux网络编程(十六)——多线程服务器端的实现
linux·服务器·网络
龙哥·三年风水4 小时前
ubuntu18-nginx-二进制安装
linux·nginx·ubuntu
ToreanonyTang5 小时前
数据库中的数组: MySQL与StarRocks的数组操作解析
linux·运维·数据库·mysql
南棱笑笑生5 小时前
20250408在荣品的PRO-RK3566开发板使用Rockchip原厂的buildroot系统时拿掉经常出现的list-iodomain.sh警告信息
linux·运维·服务器