Node基础--day03

1. 浏览器端的 AMD 和 CMD 模块化规范 (了解)

浏览器端,不能使用 Common.js 规范,因为 Common.js 是同步加载的;
AMD/CMD 可以理解为,common.js 在浏览器端,的解决方案,是异步加载的;

  • AMD模块化规范代表:RequireJS框架
    对于依赖的模块,AMD 是提前执行;
    推崇依赖前置,先定义模块,再使用;
  • CMD模块化规范代表:SeaJS框架
    对于依赖的模块,CMD 是延迟执行;
    CMD 推崇,尽可能晚的,执行这个模块,类似懒加载;推崇依赖就近;
  • ES6模块化 (大趋势):ES6 在语言标准层面上(语法上),实现了模块化功能,而且实现得相当简单;完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器,通用的模块化解决方案;(vue Reat 前端框架会使用)

2. 模块成员的分类

Node.js 由三部分组成:ECMAScript 核心 + 全局成员 + 模块成员
模块成员,分三类: 核心模块、第三方模块、用户自定义模块

  • 核心模块
    随着Node.js的安装包,一同安装到,本地的模块;如:fs,path 等;
    核心模块使用:require(‘核心模块标识符’)
  • 第三方模块
    非官方提供的模块;必须去 NPM 网站上下载,才能使用;
    先从 npm 官网上,下载指定的,第三方模块;
    require(‘第三方模块标识符’) 导入模块;根据 第三方模块的 官方文档,尝试使用;
  • 用户自定义模块
    程序员自己,写的 Javascript 文件;
    使用:require(‘路径标识符’)

3. 包(Packages)的定义和使用

可看作是 模块、代码 和 其它资源 组合起来,形成的 独立作用域;是在模块的基础上,更深一步的抽象;
1) 规范的包结构

  1. 包都要以一个单独的目录而存在;目录名,必须是英文,不能是中文,或数字开头;
  2. package.json 必须在包的顶层目录下;
  3. package.json 文件必须符合 JSON 格式,并包含如下三个属性:
    • name: 包的名字
    • version: 包的版本号
    • main: 包的入口文件
  4. 二进制文件,应该在bin目录下;
  5. javaScript 代码,应该在lib目录下;
  6. 文档应该在doc目录下;
  7. 单元测试,应该在 test目录下;
  8. README.md 包的 使用说明文档;
  9. Node.js 对包的要求,并不严格,只要顶层目录下,有 package.json,并符合基本规范即可;

2) 包描述文件 package.json

name:包的名称,必须是唯一
description:包的简要说明
version:符合语义化版本识别规范的版本字符串
keywords:关键字数据,通常用于搜索
maintainers:维护者数组,每个元素要包含name、email、web可选字段
contributors:贡献者数组,格式与maintainers相同
bugs:提交bug的地址,可以是网址或者电子邮件地址
licenses:许可证数组,每个元素要包含type和url字段
repositories:仓库托管地址数组,每个元素要包含type、url和path字段
dependencies:包的依赖,一个关联数组,由包名称和版本号组成
devDependencies:开发依赖项,表示一个包在开发期间用到的依赖项

calc计算器模块的解构
Node基础--day03

4.1 npm 的两层含义

  • NPM:一个 第三方模块的,托管网站:https://www.npmjs.com/;
  • NPM (Node package manager):Node 的包管理工具,安装 Node 时,就已顺便安装了;

4.2 安装和卸载全局包

  • 全局包:安装到计算机全局环境中的包;可以安装在,任何目录下,直接通过命令行来访问;

  • 安装全局包: npm install 包名 -g ; -g 安装到 全局目录中;

  • 全局包安装目录:C:\Users\用户目录\AppData\Roaming\npm
    工具性质的包,适合安装到全局;

  • 卸载全局包:npm uninstall 包名 -g;uninstall 卸载;

      npm i i5ting_toc -g
      //要转换文件的文件夹 -> 终端 -> i5ting_toc -f .\node_day02.md
    

4.3 安装和卸载本地包

  • 本地包:跟着项目安装的包;安装到 node_modules 目录下;
  • 一个空项目,必须在当前项目,根目录中,先运行 npm init 或 npm init -y,初始化一个 package.json 配置文件,否则其它包,无法安装到本地项目中;
  • 安装本地包:npm i 包名 --save ;
  • package-lock.json 文件中,记录了曾经装过的,包的下载地址;
  • 卸载本地包:npm uninstall/remove 包名 -S/-D ;

4.4 其它常用命令

  • –save 缩写 -S;npm 5.x 版本,可以不指定 --save 命令;
  • –save-dev 缩写 -D
  • install 缩写 i
  • dependencies 节点,表示项目上线部署时,需要的依赖项;
    devDependencies节点,表示项目在开发阶段,需要的依赖项,当项目部署上线了,devDependencies节点中的包,就不需要了;
  • npm i --production 只安装 dependencies 节点下的包,不安装 devDependencies 节点下的包;npm i 会安装所有的包,当项目要上线时,删除文件夹,运行 npm i --production
    发送自己的,项目文件给同事,先删除 node_modules文件夹,再发送;
    收到文件后,右键–>打开终端窗口–>npm i;当使用 npm i 快速装包时,npm 会检查 package.json 文件中,所有的依赖项,然后都安装到项目中;

4.5 解决 npm 下载慢问题

  • NPM 下载包时,连接的是,国外的服务器,网速不好,下载不了;
  • 此时,全局安装一个 cnpm 工具: npm i cnpm -g
  • 在装包时,只需把 npm 替换成 cnpm 即可;例如安装 jquery: cnpm i jquery -S
    安装 nrm 设置淘宝镜像,解决下载慢问题
1. npm i nrm -g
2. nrm ls
3. nrm use taobao    
npm config set registry https://registry.npm.taobao.org   //设置淘宝镜像

5. 使用 Node 构建 web 应用

  • PHP是后端,网站开发语言,PHP 开发出来的网站,可以通过 Apache 服务器托管,运行起来;
  • Node中,有没有类似于 Apache,这样的服务器呢?没有,要自己写;

1) B/S 交互模型:特指 浏览器(Browser)和 服务器(Server) 这种交互形式;
HTTP 协议通信模型:请求 - 处理 - 响应 的过程;

  • 请求:由客户端,发起请求;
  • 处理:服务器端,处理请求;
  • 响应:服务器端,把处理结果,发送给客户端;

静态资源:服务器端只需要读取,并直接发送给客户端,不需要进一步,处理的资源;
动态资源:服务器端没有现成的资源,需要服务器端,动态生成的资源;

2) 实现一个 类似于Apache的 静态资源服务器

  • 使用 http核心模块 http.createServer() 方法,创建最基本的 web 服务器;
  • 绑定监听事件 并指定 处理函数:
    server.on(‘request’, function(req, res) { 请求的处理函数 })
  • 启动服务器:
    server.listen(端口, IP地址, 启动成功的回调函数)
// 1. 导入 http 核心模块
const http = require('http')

// 2. http.createServer 创建一个 web 服务器对象;此时,并不能监听任何 客户端请求,也没有启动;
const server = http.createServer()

// 3. 为 server服务器,绑定 监听函数,通过 on方法,绑定 request请求事件,监听 客户端的请求;
server.on('request', function (req, res) {
  // reg 请求对象;res 响应对象
  /* 防止中文乱码,需要写在res.end之前;
     通过设置 响应报文头的 Content-Type,来指定,响应内容的编码类型,从而防止乱码;*/
  res.writeHeader(200, {
    'Content-Type': 'text/plain; charset=utf-8' //配置响应头
  }) 
  res.end('你好') //服务器返回中文,会有乱码问题;只要监听到有人请求服务器,就返回固定的内容:‘你好’;
})

// 4. server.listen 启动服务器
server.listen(3000, '127.0.0.1', function () {
  console.log('server running at http://127.0.0.1:3000')
})
//防止中文乱码2
server.on('request', function(req, res) {
    res.write('<head><meta charset="UTF-8"></head>')
    res.end('你好')
})

3) 根据不同的 URL,返回不同的内容

  • 使用 req.url 获取客户端,请求的URL地址;
  • 根据请求的不同路径,返回不同的内容;
const http = require('http')
const server = http.createServer()

server.on('request', function (req, res) {  
  // console.log(req.url) -->客户端请求的 URL地址
  const url = req.url
      
  // 防止中文乱码
  res.writeHeader(200, {
    'Content-Type': 'text/plain; charset=utf-8'
  })

  if (url === '/' || url === '/index.html') { '/'根目录?
    res.end('首页')
  } else if (url === '/movie.html') {
    res.end('电影')
  } else if (url === '/about.html') {
    res.end('关于')
  } else {
    res.end('请求内容不存在!')
  }
})

server.listen(3000, function () {
  console.log('server running at http://127.0.0.1:3000')
})

text/plain 和 text/html 的区别:
plain 表示普通的文本字符串; html 表示以 HTMl 标签的形式,去解析服务器的,返回内容;

// 防止中文乱码
res.writeHeader(200, {
  'Content-Type': 'text/plain; charset=utf-8'
})
res.end('<h3>首页</h3>') //返回 <h3>首页</h3> ,不解析; 
    
res.writeHeader(200, {
  'Content-Type': 'text/html; charset=utf-8'
})
res.end('<h3>首页</h3>') //返回解析过的‘首页’

4) 根据不同的 URL,返回不同的 HTML页面
使用 fs模块 读取,URL 对应的 HTML,页面内容,并使用 res.end() 响应给客户端;

const fs = require('fs')
const path = require('path')
const http = require('http')
const server = http.createServer()

server.on('request', function (req, res) {
  const url = req.url
  if (url === '/' || url === '/index.html') {
    //返回首页页面: 使用 fs模块,读取 首页文件;把读取到的首页,通过 res.end 返回即可;
    //没有出现乱码,是因为 index.html中 <meta charset="UTF-8"> 防止了页面乱码;
    fs.readFile(path.join(__dirname, './views/index.html'), 'utf-8', (err, dataStr) => {
      if (err) return res.end('404. Not found.')
      res.end(dataStr)
    })
  } else if (url === '/movie.html') {
    // 返回电影页面
    fs.readFile(path.join(__dirname, './views/movie.html'), 'utf-8', (err, dataStr) => {
      if (err) return res.end('404. Not found.')
      res.end(dataStr)
    })
  } else if (url === '/about.html') {
    // 返回关于页面
    fs.readFile(path.join(__dirname, './views/about.html'), 'utf-8', (err, dataStr) => {
      if (err) return res.end('404. Not found.')
      res.end(dataStr)
    })
  }
})

server.listen(3000, () => {
  console.log('server running at http://127.0.0.1:3000')
})
//__dirname +'./views/movie.html' 不能加‘.’也不能少‘/’;path.join则无限制;
fs.readFile(path.join(__dirname, './views/about.html'), 'utf-8', (err, dataStr) => {
   res.end(dataStr)
})
// 以 utf-8 形式的字符串读取;如果省略掉,读取的内容,变成二进制的格式;
// res.end() 方法,接收两种类型的数据 String,二进制;
// 如果是string,先把字符串->二进制,再通过网络发送出去,客户端接收后,再转成字符串,所以'utf-8'可以省略

5) 处理并返回 css样式,和 Javascript文件

  • 如果客户端要拿到,页面引入的 css 或 js样式;必须在服务器端,监听这个请求地址;
  • 客户端所请求的,任何文件或资源;服务器端,必须要监听,并响应之后,客户端才能拿到;
const fs = require('fs')
const path = require('path')    
const http = require('http')
const server = http.createServer()

server.on('request', function (req, res) {
  let url = req.url
  if (url === '/css/1.css') {
    // 读取样式表
    fs.readFile(path.join(__dirname, '/css/1.css'), (err, buf) => {
      if (err) return res.end('404. Not found.')
      res.end(buf)
    })
  } else if (url === '/js/1.js') {
    // 读取 JS 文件
    fs.readFile(path.join(__dirname, '/css/1.js'), (err, buf) => {
      if (err) return res.end('404. Not found.')
      res.end(buf)
    })
  }
})

server.listen(3000, () => {
  console.log('server running at http://127.0.0.1:3000')
})
    
//项目最终优化
server.on('request', function (req, res) {
  let url = req.url //url地址是改变的,所以不能用const
  if (url === '/') url = '/views/index.html'
  fs.readFile(path.join(__dirname, url), (err, buf) => {
    if (err) return res.end('404. Not found.')
    res.end(buf)
  })
})

6) Node中 结合模板引擎 渲染动态页面

  • art-template 模板引擎;同时支持 Node.js 和 浏览器;
  • 安装模板引擎 npm init -y (项目名称 package name: test) npm i art-template
  • 导入模板引擎:const template = require(‘art-template’)
const template = require('art-template')
const path = require('path')
const http = require('http')
const server = http.createServer()

server.on('request', function (req, res) {
  const url = req.url
  if (url === '/') {
    // template('要渲染的 html页面路径',{要渲染的数据/没有要渲染的数据,指定一个空对象})
    // template 方法的返回值,就是渲染好的 html页面,直接通过 res.end 发送给客户端
    const htmlStr = template(path.join(__dirname, '/views/1.html'), { name: 'zs', age: 22, hobby: ['吃饭', '唱歌', '跳舞'] })
    res.end(htmlStr)
  }
})

server.listen(3000, function () {
  console.log('server running at http://127.0.0.1:3000')
})

html 内容

<h1>Node 服务器,结合 art-template 模板引擎,渲染的动态页面</h1>
<p>姓名:{{name}}</p>
<p>年龄:{{age}}</p>
<p>
    爱好: 
    {{each hobby}}          //{{开始循环 each 数组名称}} 
    <span>{{$value}}</span> //{{$value 循环的每一项数据}}
    {{/each}}               // {{结束循环 /each}}  爱好:吃饭 唱歌 跳舞
</p>    
上一篇:1024_day03_消息中间件RabbitMQ


下一篇:day03 【 流程控制语句】