Node.js入门必看

什么是 Node.js

  • Node.js 是 JavaScript 的运行环境
  • Node.js 是除了浏览器之外,可以运行 JavaScript 的环境
  • Node.js 既不是一门新的语言,也不是 JavaScript 框架

浏览器的组成

  • 外壳
    • 内核

浏览器内核的组成

  • 浏览器内核
    • 渲染引擎
      • HTML
      • CSS
    • JS 引擎
      • JS

主流浏览器内核

浏览器 渲染引擎 JS 引擎
IE -> Edge Trident -> EdgeHTML Chakra
Chrome Webkit -> Blink V8
Safari Webkit SquirrelFish
Firefox Gecko SpiderMonkey
Opera Presto -> Blink Carakan

JavaScript 运行环境

  • Chrome 浏览器
    • V8 - JS
  • Node.js
    • V8 - JS

软件架构

  • 框架(framework)
  • 编程语言(language)
  • 运行环境(runtime)
  • 操作系统(OS)
软件架构 WEB 应用 WEB 应用
框架 Vue Express
编程语言 JS JS
运行环境 Browser Node.js
操作系统 OS OS

将 JS 比喻成飞机

软件架构 WEB 应用 WEB 应用
框架 C 919 J 15
编程语言 飞机 飞机
运行环境 陆地机场 航母甲板
操作系统 OS OS

Node.js 能做什么

JS 的作用

  • 浏览器(JS)——负责前端的功能
    • 响应浏览器事件
    • 数据验证
    • DOM操作
  • Node.js(JS)——负责后端的功能
    • Node.js 适合用于开发前端方向的各种工具
      • 各种前端工程化的工具
    • Node.js 适合开发服务端的应用层(BFF)
      • 为网站、APP、小程序等提供数据服务
    • Node.js 可以用来做桌面应用开发
      • 各种跨平台的桌面应用
      • 例如:vscode、typora、insomnia

Node.js APIs

  • JS@web
    • ECMAScript
      • 常量、变量、元素符、流程控制语句、内置对象(String、Array …)
    • Web APIs
      • DOM
        • document、element …
      • BOM
        • window、location、history …
  • [email protected]
    • ECMASript
      • 常量、变量、元素符、流程控制语句、内置对象(String、Array …)
    • Node APIs
      • fs、path、os、http …

使用 Node.js

通过 Node.js 运行 JS 代码

  • Node.js 有两种模式运行 JS
    • 脚本模式
      • node path/filenam.js (回车)
    • 交互模式(REPL)
      • node (回车) 进入交互模式
      • JS 代码 (回车) 运行代码
      • .exit 或 按两次 ctrl+c 退出交互模式
* 交互模式
  * 使用 tab 键自动补全(例如:输入 console.l 然后按tab键)
  * 探索 JS 对象 (例如:Math. 然后按两次 tab 键)
  * 点命令(例如:输入 .help 然后回车)

Node.js 的全局对象

Node.js 下的全局对象是 global;
浏览器端的 JS 中,全局对象是 window

Node.js 下的全局对象是 global

  • 交互模式下,声明的变量和函数都属于 global
    • 例如 var a = 1; global.a可以访问到
  • 脚本模式下,生命的变量和函数都不属于global
    • 例如:var a = 1; global.a 访问不到

Node.js 的全局函数

  • JS 语言提供的全局函数,在 Node.js 下依然可用
    • parseInt / parseFloat / isNaN / isFinite / eval…
    • 一次性定时器(setTimeout / clearTimeout)
    • 周期性定时器(setInterval / clearInterval)
  • Node.js 环境也提供了一些全局函数
    • 立即执行定时器(setImmediate / clearImmediate)
    • 进程立即执行定时器(process.nextTick)
var num = 3.14
console.log(parseInt(num))

var timer = setTimeout(() => {
    
    
    console.log(1)
}, 2000)

// 清除一次性定时任务
// clearTimeout(timer)

// 在实践队列开始之前,立即执行
setImmediate(() => {
    
    
    console.log(2)
})

// 在主进程结束后立即执行
process.nextTick(() => {
    
    
    console.log(7)
})

Node.js 模块

模块(包)是 Node.js 中具有特定功能的对象

  • 模块(包)是 Node.js 应用程序的基本组成部分
  • 大部分前端工程化的工具,是以模块的形式存在的

Node.js 模块的划分方式

  • Node.js 模块
    • 内置模块
      • 官方提供的,跟随 Node.js 一起安装
      • http://nodejs.cn/api/
    • 自定义模块
      • 工程师自己写的
    • 第三方模块
      • 社区维护的,需要单独下载才能使用
      • https://www.npmjs.com/

Web 端 与 Node.js 端的类比

  • Web 端
    • 宿主对象
      • document、window …
    • 自定义对象
      • 工程师自己写的
    • 第三方库
      • jQuery、Bootstrap …
  • Node.js 模块
    • 内置模块
      • fs、path、os、http …
    • 自定义模块
      • 工程师自己写的
    • 第三方模块
      • Less、Babel、Express …

内置模块也叫核心模块,跟随 Node.js 一起安装

核心模块 —— console

  • 控制台中输出的内容,通过不同的颜色标识不同的变量类型
  • 控制台中可以一次输出多个变量,多个变量之间,用逗号间隔
  • 官方文档:http://nodejs.cn/api/console.html
console.log("1")
console.log(1)

var obj = {
    
    
    name: 'Tom',
    age: 18
}
console.log(obj)
console.table(obj)

// 计时函数
console.time('for') // 计时开始
for (let i = 0; i < 1000000; i++) {
    
    

}
console.timeEnd('for') // 计时结束

console.time('while')
var i = 0
while (i < 1000000) {
    
    
    i++;
}
console.timeEnd('while')

核心模块 —— process

  • process 提供了有关当前 Node.js 进程的信息
  • process 是全局变量,使用时无需 require 引入
  • 官方文档:http://nodejs.cn/api/process.html
// process 是全局变量,使用时,无需引入
// const process = require('process')

// console.log(process)

// 输出 node 版本
console.log(process.version)

// 输出操作系统架构
console.log(process.arch)

// 输出操作系统平台
console.log(process.platform)

// 输出当前工作目录 cwd = current working directory
console.log(process.cwd())

// 环境变量
console.log(process.env)
// 自定义环境变量
process.env.NODE_ENV = 'develop'
console.log(process.env)

// 获取进程的编号
console.log(process.pid)

// 杀死进程  process.kill(进程编号)

核心模块 —— path

  • path 模块提供了有关路径操作的函数
    • 当前目录 ./
    • 上一级目录 ../
  • 使用之前,需要通过 require 引入
  • 官方文档:http://nodejs.cn/api/path.html
// 引入 path 模块
const path = require('path')

// 获取当前文件所在的路径
console.log(process.cwd())

// dir = directory 目录
console.log(__dirname) // 获取当前文件所在的路径

// D:\cliu\Desktop\node\03.core_module\path.js
console.log(__filename) // 获取当前文件的完整路径

// 获取文件的扩展名 ext = extension 
console.log(path.extname(__filename))

// 获取路径中的目录部分
console.log(path.dirname(__filename))

// 获取路径中的文件名
console.log(path.basename(__filename))

const t = path.join(__dirname, '..')
console.log(t)
// 将多个路径合并起来
const a = path.join('D:/', 'a', 'b', 'c.png')
console.log(a)

核心模块 —— fs

  • fs (file system) 提供了稳健操作的 API
    • 文件操作
    • 目录操作
  • 使用之前,需要通过 require 引入
  • 官方文档:http://nodejs.cn/api/fs.html

写文件_清空写入

// 文件的写操作
const fs = require('fs')

// 清空写入
// fs.writeFile('文件路径', '写入内容', 回调函数)
fs.writeFile('./1.txt', '曾经有一首歌,她感动了我', (err) => {
    
    
    if (err) throw err
    console.log('写入成功')
})

写文件_追加写入

const fs = require('fs')

// 追加写入
// 语法: fs.appendWrite('文件路径','写入内容', 回调函数)
fs.appendFile(__dirname+'/2.txt', '曾经有一首歌,她是这样唱的\n', (err) => {
    
    
    if (err) throw err
    console.log('追加写入成功') 
})

读文件

const fs = require('fs')
const path = require('path')

// 读文件
// 指定目标文件所在的路径
// var filename = __dirname + '/1.txt'
var filename = path.join(__dirname, '1.txt')

// 语法:fs.readFile('文件路径', 回调函数)
fs.readFile(filename, (err, data) => {
    
    
    if (err) throw err
    // data 是二进制数据,默认输出时,以十六进制的方式展示
    console.log(data.toString())
})

删文件

const fs = require('fs')

// 语法: fs.unlink('文件路径', 回调函数)
fs.unlink(__dirname+'/1.txt', (err) => {
    
    
    if (err) throw err
    console.log('删除成功')
})

创建目录

const fs = require('fs')

// 创建目录
// 语法:fs.mkdir('目录路径', 回调函数)
fs.mkdir('./d1', (err) => {
    
    
    if (err) throw err
    console.log('创建成功')
})

删除目录

const fs = require('fs')

// 删除目录
// 语法: fs.rmdir('目录路径', 回调函数)
fs.rmdir('./d1', (err) => {
    
    
    if (err) throw err
    console.log('删除成功')
})

// 声明: rmdir 只能删除空目录
// 1. 先删除目录下的普通文件(清空目录)
// 2. 通过 rmdir 删除空目录

重命名目录

const fs = require('fs')

// 重命名目录
// 语法: fs.rename(旧名称, 新名称, 回调函数)
fs.rename(__dirname+'/d1', __dirname+'/d2', (err) => {
    
    
    if (err) throw err
    console.log('重命名成功')
})

读目录

const fs = require('fs')

// 读目录
// 语法:fs.readdir('目录路径', 回调函数)
fs.readdir(__dirname, (err, data) => {
    
    
    if (err) throw err
    // console.log(data)
    data.map((d) => {
    
    
        // console.log(d)
        fs.stat(__dirname+"/"+d, (err, stat) => {
    
    
            if (err) throw err
            if (stat.isDirectory()) {
    
    
                // 判断当前文件是否是目录
                console.log('目录:', d)
            } else if (stat.isFile()) {
    
    
                // 判断当前文件是否是普通文件
                console.log('文件:', d)
            }
        })
    })
})

同步函数(synchronization)

  • 同步异步
    • 文件函数
      • 同步
        • writeFileSync
        • readFileSync
        • appendFileSync
      • 异步
        • writeFile
        • readFile
        • appendFile
    • 目录函数
      • 同步
        • mkdirSync
        • rmdirSync
        • readdirSync
      • 异步
        • mkdir
        • rmdir
        • readdir
  • 同步函数
    • 在主程序中自上而下运行
    • 例如:去火车站排队买票
  • 异步函数
    • 通过回调函数在事件队列中运行
    • 例如:委托黄牛买票,票买好后通知我(无需等待,可以做其他事)

fs 事件——文件的复制与压缩

const fs = require('fs')
const path = require('path')

// 把 src/style.css 复制到 dist/ 目录下
const dist = path.join(__dirname, 'dist')

fs.readFile('./src/style.css', (err, data) => {
    
    
    if (err) {
    
    
        throw err
    } else {
    
    
        console.log(data.toString())

        // 确保 dist 目录存在
        if (!fs.existsSync(dist)) {
    
    
            fs.mkdirSync(dist)
        }

        // 对文件进行压缩: 将无用的注释或空格去掉
        //                                                        /*  注释的内容  */
        var mydata = data.toString().replace(/\s+/g, '').replace(/\/\*{1,2}[\s\S]*\*\//g, '')

        // 将读到的内容,写入目标文件
        fs.writeFile(dist+'/style.min.css', mydata, (err) => {
    
    
            if (err) throw err
            console.log('成功')
        })
    }
})

文件流

缓冲 VS 流

  • 文件操作——缓冲方式

    • 源文件->内存缓冲->目标文件
  • 文件操作——流方式

    • A->B

为什么选择 “流”

  • 内存效率提高
    • 无需加载大量数据
    • 流把大数据切成小块,占用内存更少
  • 时间效率提高
    • 接获数据后立即开始处理
    • 无须等到内存缓冲填满
const fs = require('fs')

// 1. 创建读取流
var readStream = fs.createReadStream('./file2.txt')

// 2. 创建写入流
var writeStream = fs.createWriteStream('./file_stream.txt')

// 3. 把读取流通过管道传给写入流
readStream.pipe(writeStream)

内置模块——http

  • http 模块可以发布 web 服务
  • 使用之前,通过 require 引入
  • 官方文档:http://nodejs.cn/api/http.html
const http = require('http')

// 1. 创建服务器
/**
 * req = request 请求
 * res = response 响应
 */
const server = http.createServer((req, res) => {
    
    
    res.statusCode = 200
    res.setHeader('Content-Type', 'text/plain; charset=utf-8')
    res.end('你好:Node.js')
})

// 2. 发布 web 服务
const port = 3000
const host = 'localhost'
// 在浏览器中访问 http://localhost:3000 然后能看到效果
server.listen(port, host, () => {
    
    
    console.log(`服务器运行在 http://${
      
      host}:${
      
      port}`)
})

自定义模块

程序员自己写的 Node.js 模块

  • Node.js 中每个单独的 .js 文件,就是一个模块
  • 每个模块中都有一个 module 变量,其代表当前模块
  • module 的 exports 属性是对外的接口
    • 只有导出(module.exports)的属性或方法才能被外部调用
    • 未导出的内容是模块私有,不能被外部访问
// circle.js

// 当前模块的指代变量, module 标识当前模块
// console.log(module)

const PI = 3.14

/**
 * 计算圆的周长
 */
function perimeter(r) {
    
    
    return 2 * PI * r
}

/**
 * 计算圆的面积
 */
function area(r) {
    
    
    return PI * Math.pow(r, 2)
}

// 模块中的属性或方法,必须导出,然后才能被使用
module.exports = {
    
    
    perimeter,
    area
}

// app.js
// 引入文件模块
const circle = require('./circle')

const r = 10

console.log('周长:', circle.perimeter(r))
console.log('面积:', circle.area(r))

模块的加载逻辑

  • 按组织方式划分模块
    • 文件模块
      • 一个独立的 .js 文件
    • 目录模块
      • 将多个 .js 文件放在一个目录中
  • 目录模块的加载逻辑
    • 确定入口文件
    • 先引入入口文件
    • 然后在入口文件中引入其他文件
  • 组织方式
    • 文件模块
      • 以路径开头
        • require('./circle')
        • 引入自己定义的模块,后缀名 .js 可以省略
      • 不以路径开头
        • require('circle')
        • 引入官方的核心模块
    • 目录模块
      • 以路径开头
        • require('./dir01')
        • 找到指定路径下的 dir01 目录,然后引入入口文件
      • 不以路径开头
        • require('dir02')
        • 到当前目录下的 node_modules 目录中寻找 dir02;如果找不到会到上一级目录寻找,直到顶层目录。找到目录模块 dir02 后,引入 dir02 中的入口文件
      • 如何确定入口文件
        • 在目录中寻找 package.json文件,入口文件通过其 main 属性直到,如果找不到,则默认引入 index.js
        • package.json 是目录模块的描述文件

第三方模块

社区维护的 Node.js 模块

  • 前端工程化的大部分工具,都是第三方模块
  • 想要使用 Node.js 的第三方模块,需要通过单独安装
  • 第三方模块的集中管理网站:https://www.npmjs.com

npm 概述

npm (Node Package Manager) 是 Node.js 的包管理工具

  • 包就是一坨代码,就是 Node.js 的第三方模块
  • npm 是一个命令,跟随 Node.js 一起安装
  • npm 可以下载(安装)包和包的依赖

npm 的作用

  • 手动下载
    • 打开网站
    • 找到资源
    • 点击下载
  • npm 安装
    • npm install <package-name>

npm 镜像源

npm 管理的 Node.js 包的资源地址 npmjs.com

  • npm install <package-name>
    • https://www.npmjs.com/package/<package-name>
      • jQuery
      • Bootstrap
      • Vue

修改 npm 镜像源

  • 国外镜像
    • https://registry.npmjs.com
  • 国内镜像
    • https://registry.npm.taobao.org
npm config set registry https://registry.npm.taobao.org(回车)

npm config get registry(回车)

使用 npm 安装包

  • npm 安装包的方式

    • 全局安装
      • 多个项目都能用到(将包当做全局工具使用)
      • npm install <package-name> --global 或 npm i <package-name> -g
    • 项目安装
      • 只有当前项目用到
      • npm install <package-name> --save 或 npm i <package-name> -S
  • 安装步骤

    • 全局安装
      • 明确你的需求
      • 找到合适的包
      • 通过 npm 安装包
      • 使用包
    • 项目安装
      • 创建项目目录
      • 进入项目目录
      • 初始化项目
      • 在项目中安装包

–save 与 --save-dev

npm install --save-dev 或 npm i -D

npm 安装命令的参数

  • –save / -S
    • 安装的包,开发和上线都需要
  • –save-dev / -D
    • 安装的包,只在开发环境使用

猜你喜欢

转载自blog.csdn.net/CS_DGD/article/details/112446829