Nodejs的http模块、模块化和包

黑马程序员Node.js全套入门教程,nodejs最新教程含es6模块化+npm+express+webpack+promise等_Nodejs实战案例详解_哔哩哔哩_bilibili本套课程作为框架前置课,重点为学生铺垫 npm、包、模块化、身份认证、CORS 跨域等主要知识点,为学习后面的 Vue 课程夯实基础。同时,本课程涵盖了 MySQL 数据库、API 接口项目开发等后端内容,拓宽了学生的知识面,为前端学生构建了前后端完整的知识体系,助力学生更好地发展。https://www.bilibili.com/video/BV1a34y167AZ?p=37&spm_id_from=333.1007.top_right_bar_window_history.content.click三. http模块

http模块用来创建web服务器,对外提供网络资源。

  • Node.js中无需IIS和Apache等disanfangweb服务器软件,可以直接通过http模块手写一个服务器软件。
  • 服务器的相关概念:IP地址、域名和域名服务器、端口号

1. 创建web服务器的基本步骤

  • req请求对象:在request事件处理函数中,访问与客户端相关的数据或属性。
  • res响应对象:在request事件处理函数中,访问与服务器相关的数据或属性。
  • 在终端退出服务器:control+C
//1、导入http模块
const http=require('http');
//2、创建web服务器实例
const server=http.createServer();
//3、为服务器实例绑定request事件,即可监听客户端发送过来的网络请求
server.on('request',function(req,res){
    console.log("Someone visit our web server.");
    //req是请求对象,它包含了与客户端相关的数据和属性
    //  req.url是客户端请求的URL地址
    const url=req.url;
    //  req.method是客户端的method请求类型
    const method=req.method;
    const str=`Your request url is ${url},and request method is ${method}`;
    //  为了防止中文乱码问题,需要设置响应头 Content-Type的值为text/html; charset=utf-8
    res.setHeader('Content-Type','text/html; charset=utf-8');
    
    //res是响应对象,用于访问与服务器相关的数据或属性
    //  调用res.end()方法,向客户端响应一些内容
    res.end(str);
});
//4、启动服务器
server.listen(8080,function(){
    console.log("server running at http:127.0.0.1:8080")
});

2. 解决中文乱码问题

问题:调用res.end()方法向客户端发送中文内容时会出现乱码问题。

解决方法:手动设置内容的编码格式

//  为了防止中文乱码问题,需要设置响应头 Content-Type的值为text/html; charset=utf-8
    res.setHeader('Content-Type','text/html; charset=utf-8');

3. 根据不同的url相应不同的html内容

const http=require('http');
const server=http.createServer();
server.on('request',(req,res)=>{
    console.log("Someone visit our web server.");
    const url=req.url;//1、获取请求的url地址
    let content='<h1>404 Not found!</h1>';//2、设置默认的响应内容为404 Not found
    if(url==='/'||url==='/index.html'){//3、判断用户请求的是否为/或/index.html页面
        content='<h1>首页</h1>';
    }else if(url==='/about.html'){//4、判断用户请求的是否为/或/about.html页面
        content='<h1>关于页面</h1>';
    }
    res.setHeader('Content-Type','text/html; charset=utf-8');//5、设置Content-Type响应头,防止中文乱码
    res.end(content);//6、使用res.end()把内容响应给客户端
});
server.listen(80,()=>{
    console.log("server running at http:127.0.0.1:80");
});

4. 实现html页面的web服务器

把文件的实际存放路径,作为每个资源的请求url地址

服务器充当的角色就是一个字符串的搬运工

const http=require('http');
const fs=require('fs');
const path=require('path');
const server=http.createServer();
server.on('request',(req,res)=>{ 
    //1、将资源的请求url地址映射为文件的存放路径   http://127.0.0.1/clock/index.html
    const url=req.url;//获取客户端请求的url地址  /clock/index.html
    //const fpath=path.join(__dirname,'./file',url);//把请求的url地址映射为本地文件的存放路径
    //1.1 优化资源的请求路径
    let fpath='';
    if(url==='/'){ // http://127.0.0.1/
        fpath=path.join(__dirname,'./file/clock/index.html');
    } else {   //http://127.0.0.1/index.html
        fpath=path.join(__dirname,'./file/clock',url);
    }
    //2、读取文件内容并相应给客户端
    fs.readFile(fpath,'utf8',(err,dataStr)=>{
        if(err) return console.log("404 not found.");
        res.end(dataStr);
    });
});
server.listen(80,()=>{
    console.log("server running at http:127.0.0.1:80");
});

四. 模块化

模块化是指解决问题时,自顶向下逐层把系统划分成若干模块的过程。模块是系统中可组合、分解和更换的单元。

  • 编程中的模块化:遵守固定的规则(模块化规范),把一个大文件拆成独立并相互依赖的多个小模块,提高代码的复用性、维护性,可以实现按需加载。
  • Node.js中模块的分类(按来源分):内置模块、自定义模块、第三方模块。

1. 加载模块:require()

使用require()方法加载其它模块时,会执行被加载模块中的代码。

使用require()家在用户自定义模块期间,可以省略.js的后缀名。

//加载用户自定义模块
const m1=require('./file/2.js');//也可以省略.js后缀名

2. 向外共享模块作用域中的成员

模块作用域:防止了全局变量污染的问题

(1)module对象,存储了和当前模块有关的信息。

  • module.exports对象,在自定义模块中可以使用它,将模块内的成员共享出去,供外界使用。
  • 外界使用require()方法导入自定义模块时,得到的就是module.exports所指的对象。
//在外界使用require导入一个自定义模块的时候,得到的成员就是那个模块中module.exports所指向的对象
const m=require('./file/2.js');
console.log(m);
//2.js 文件
//在一个自定义模块中,默认情况下module.exports={}
const age=20;
//向module.exports上挂载username属性,也可以写为exports.username="zs";
module.exports.username="zs";
//向module.exports上挂载sayHello方法
module.exports.sayHello=function(){
	console.log('大家好,我是'+username);
}
//module.exports.age=age;

(2)exports对象,默认情况下和module.exports指向同一个对象,最终共享的结果以module.exports指向的对象为准。

  • 用来简化向外共享成员的代码。
  • 注意:require()模块时,得到的永远是module.exports所指的对象。
  • 注意:为了防止混乱,不要在同一个模块中同时使用exports和module.exports。

3. CommonJS模块化规范

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

4. 模块的加载机制

  • 优先从缓存中加载
    • 模块在第一次加载后会被缓存,多次调用require()不会导致模块的代码被执行多次。
    • 可以提高模块的加载效率。
  • 内置模块的加载机制
    • 内置模块的加载优先级最高
  • 自定义模块的加载机制
    • 使用require()加载自定义模块时,必须指定以./或../开头的路径标识符。否则node会把它当做内置模块或第三方模块加载。
    • 使用require()加载自定义模块时,若省略了文件扩展名,node会依次尝试加载:(1)按确切文件名进行加载(2)补全.js扩展名进行加载(3)补全.json扩展名进行加载
  • 第三方模块的加载机制
    • 使用require()加载模块时,若模块不是内置模块,且没有以./或../开头,则node会从当前模块父目录开始尝试从/node_modules文件夹中加载第三方模块。
    • 若没有找到对应的第三方模块,则移动到上一层父目录中进行加载,指导文件系统的根目录。
  • 目录作为模块时有三种加载方式
    • (1)在被加载的目录下找一个叫package.json的文件,并寻找main属性,作为require()加载的入口。
    • (2)若目录中没有package.json文件,或main入口不存在或无法解析,node会试图加载目录下的index.js文件。
    • (3)若以上两步都失败,node会在终端打印错误消息,报告模块缺失。

五. npm与包

包===第三方模块

  • 包共享平台(搜索):npm
  • 包共享服务器(下载):https://registry.npmjs.org/
  • 包管理工具(下载包):终端中输入 npm -v
    • 安装包: npm install 包完整的名称
    • 安装包(简写形式): npm i 包完整的名称
    • 安装指定版本的包: npm i 包完整的名称@版本号
  • 包的语义化版本规范:点分十进制,共三位数组
    • 第一位数字:大版本
    • 第二位数字:功能版本
    • 第三个数字:Bug修复版本
  • 解决包下载慢的问题:淘宝npm镜像服务器
    • 查看当前的下包镜像源:npm config get registry
    • 切换npm的下包镜像源方式1:npm config set registry=https://registry.npm.taobao.org/
    • 切换npm的下包镜像源方式2:(1)安装nrm工具: npm i nrm -g(2)查看所有可用镜像源:nrm ls(3)将下包镜像源切换为淘宝镜像:nrm use taobao
  • 初次装包后项目文件夹下多了node_modules文件夹和package-lock.json配置文件。
    • node_modules文件夹:存放所有已安装到项目的包。require()导入第三方包时,就是从这个目录中查找并加载包。
    • package-lock.json配置文件:记录node_modules目录下每一个包的下载信息,例如包的名字、版本号、下载地址等。
  • 包管理配置文件:package.json,放在项目的根目录中,记录与项目有关的配置信息。
    • 多人协作问题:第三方包体积过大,不方便共享项目源代码。package.json记录安装了那些包,从而方便剔除。
      • 项目开发中,一定要把node_modules文件夹添加到.gitignore忽略文件中。
      • 当拿到一个剔除了node_modules的项目之后,需要先把所有的包下载到项目中。
        • 一次性安装所有包:npm install
        • 一次性安装所有包(简写形式):npm i
        • 卸载包: npm uninstall 包完整的名称
          • 执行成功后,会把卸载的包自动从package.json的dependencies中移除。
    • 快速创建package.json文件: npm init -y
      • 只需要在项目刚建立时,在项目的根目录中执行一次,目录和项目名称必须不包含中文和空格。
    • dependencies节点:专门用来记录使用npm install命令装了哪些包,这些包项目开发和上线阶段都会用到。
    • devDependencies节点:记录只会在项目开发阶段用到,项目上线之后不会用到的包。
      • 将包记录到devDependencies节点:npm install 包名 --save-dev
      • 将包记录到devDependencies节点(简写形式):npm i 包名 -D
  • 包的分类:(1)项目包(开发依赖包、核心依赖包)、(2)全局包(npm install 时提供了-g参数,卸载时也要提供-g参数。只有工具性质的包才需全局安装。)
  • 规范的包结构:
    • 包必须以单独的目录存在
    • 包的顶级目录下必须包含package.json
    • package.json中必须包含name、version、main三个属性,分别代表包的名字、版本号、包的入口

1. 格式化时间

# 在终端中下载包
npm i moment
//1、导入moment包
//注意:导包的名称就是安装包时的名称
const moment=require('moment');
//2、参考moment官方API文档,使用moment
const dt=moment().format('YYYY-MM-DD HH:mm:ss');
console.log(dt);

2. 开发属于自己的包

(1)新建文件夹作为包的根目录

(2)在文件夹中新建三个文件:

  • package.json(包管理配置文件)
  • index.js(包的入口文件)
  • README.md(包的说明文档):安装方式、导入方式、功能及使用方式、开源协议
//package.json文件
{
    "name":"songd-tools",
    "version":"1.0.0",
    "main":"index.js",
    "description": "提供了格式化时间,HTMLEscape的功能",
    "keywords": ["dateFormat","escape"],
    "license": "ISC"
}
//index.js文件
//这里是包的入口文件
const date=require('./src/dateFormat');
const escape=require('./src/htmlEscape');

//向外暴露需要的成员
module.exports={
    ...date,
    ...escape
} 
//README.md

## 安装
```
npm install songd-tools
```

## 导入
```js
const songd=require('songd-tools')
```

## 格式化时间
```js
//调用dateFormat对时间进行格式化
const dt=sdutil.dateFormat(new Date());
//结果 2022-04-01 17:48:20
console.log(dt);
```

## 转义HTML中的特殊字符
```js
//待转换的HTML字符串
const htmlStr='<h1 title="abc">这是h1标签<span>123&nbsp;</span></h1>';
//调用htmlEscape方法进行转换
const newStr=sdutil.htmlEscape(htmlStr);
//转换的结果 &amp;lt;h1 title=&amp;quot;abc&amp;quot;&amp;gt;这是h1标签&amp;lt;span&amp;gt;123&amp;amp;nbsp;&amp;lt;/span&amp;gt;&amp;lt;/h1&amp;gt;
console.log(newStr);
```

## 还原HTML中的特殊字符
```js
//待还原的HTML字符串
const str=sdutil.htmlUnEscape(newStr);
//还原的结果 <h1 title="abc">这是h1标签<span>123&nbsp;</span></h1>
console.log(str);
```

## 开源协议
ISC

(3)在文件夹中新建src文件夹,并创建两个文件

//dateFormat.js文件
//格式化时间的函数
function dateFormat(dtStr){
    const dt=new Date(dtStr);
    const y=dt.getFullYear();
    const m=padZero(dt.getMonth()+1);
    const d=padZero(dt.getDate());
 
    const hh=padZero(dt.getHours());
    const mm=padZero(dt.getMinutes());
    const ss=padZero(dt.getSeconds());
 
    return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
 }

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

//向外暴露需要的成员
module.exports={
    dateFormat
} 
//htmlEscape.js文件
//转译html的函数,把html字符转译成实体字符
function htmlEscape(htmlStr){
    return htmlStr.replace(/<|>|"|&/g,(match)=>{
        switch(match){
            case '<':
                return '&lt;'
            case '>':
                return '&gt;'
            case '"':
                return '&quot;'
            case "&":
                return '&amp;'
        }
    })
}

//还原html的函数
function htmlUnEscape(htmlStr){
    return htmlStr.replace(/&lt;|&gt;|&quot;|&amp;/g,(match)=>{
        switch(match){
            case '&lt;':
                return '<'
            case '&gt;':
                return '>'
            case '&quot;':
                return '"'
            case "&amp;":
                return '&'
        }
    })
}

//向外暴露需要的成员
module.exports={
    htmlEscape,
    htmlUnEscape
} 

3. 发布包

(1)登录npm账号

  • 把下包的服务器地址切换为npm官方服务器
  • 在终端执行npm login命令,依次输入用户名、密码、邮箱

(2)把包发布到npm上

  • 把终端切换到包的根目录
  • 运行npm publish命令(注意:包名不能雷同!)

(3)删除已发布的包

  • 运行 npm unpublish 包名 --force命令,即可从npm删除已发布的包
    • npm unpublish删除的包,在24小时以内不允许重复发布
    • npm unpublish命令只能删除72小时以内发布的包
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值