Node 基础学习

一、包管理工具

1.1 npm

常用命令

# 全局安装
npm install -g [package-name]

# 当前项目依赖安装, 加 -D 是开发时依赖
npm install [package-name]

# 安装指定版本包, version 代表版本号
npm install [package-name]@[version]

# 列举当前目录下的安装包
npm list

# 查看包信息
npm info [package-name]

# 检查当前项目的包是否已过时
npm outdated

# 查看本地全局环境的包是否已过时
npm outdated -g --depth=0

# 收藏/取消收藏
npm stat/unstar [package-name]

# 查看收藏列表
npm stars

# 登录 npm,没有的在 npm 注册一个就行了
npm login

# 查看包的文档
npm home [package-name]

# 查看包的代码仓库
npm repo [package-name]

# 快速给包提 issues
npm bugs [package-name]

# 查看当前源地址
npm config get registry

# 切换npm源
npm config set registry=<url>

# 临时使用
npm --registry https://registry.npm.taobao.org install express

包后面符号说明

// ^ 表示 npm i 将会安装 md5 2.*.* 最新版本
{ "md5": "^2.1.0" }

// ~ 表示 npm i 将会安装 md5 2.1.* 最新版本
{ "md5": "~2.1.0" }

// * 表示 npm i 将会安装 md5 最新版本
{ "md5": "*" }

1.2 nrm

npm 的镜像源管理工具,有时候国外资源太慢,使用这个就可以快速的在 npm 源间切换

# 设置淘宝镜像源
npm config set registry http://registry.npm.taobao.org

# 查看镜像源
npm get registry

nrm 常用命令

# 全局安装
npm i -g nrm

# 查看可选的源,带 * 是当前使用的源
nrm ls

# 切换源,假设切换taobao
nrm use taobao

中国NPM镜像cnpm

同步频率为10分钟,保证与官方服务同步
npm install -g cnpm --registry=https://registry.npmmirror.com

1.3 yarn

npm install -g yarn

对比npm:

  1. 速度快:yarn 缓存了每个下载过的包,所以再次使用时无需重复下载。同时利用并行下载以最大化资源利用率,因此安装速度更快
  2. 安全:在执行代码之前,yarn 会通过算法校验每个安装包的完整性
# 全局安装
yarn add -g [package]

# 当前项目依赖安装, 加 -D 是开发时依赖
yarn add [package]

# 安装指定版本包, version 代表版本号
yarn add [package]@[version]

# 列举当前目录下的安装包
yarn list

# 查看包信息
yarn info [package]

# 升级包
yarn upgrade [package]@[version]

# 移除依赖包
yarn remove [package]

二、内置模块

2.1 http 模块

2.1.1 创建简单服务器

// 1. 导入http模块
const http = require('http')

// 2. 创建服务器
const server = http.createServer((req, res) => {
  // 写入请求头,以 html utf-8 格式解析
  res.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'})
  
  res.write(`
    <html>
      <div>欢迎来到Node世界!</div>
    </html>
  `)
  res.end()
})

// 3. 监听端口
server.listen(3001, () => {
  // 服务器启动后
  console.log('server start')
})

2.1.2 CORS

// 设置 access-control-allow-origin 头,允许所有源访问
res.writeHead(200, {
  'Content-Type': 'text/html; charset=utf-8',
  'access-control-allow-origin': '*' 
})

2.2 旧版 url 模块用法

网址模块

2.2.1 url.parse

url.parse(urlString[, parseQueryString[, slashesDenoteHost]]) 接受网址字符串,解析并返回网址对象

  • urlString<string>要解析的 URL 字符串。
  • parseQueryString <boolean> 如果为 true,则 query 属性将始终设置为 querystring 模块的 parse() 方法返回的对象。 如果为 false,则返回的网址对象上的 query 属性将是未解析、未解码的字符串。 默认值: false。
  • slashesDenoteHost <boolean> 如果为 true,则文字串 // 之后和下一个 / 之前的第一个令牌将被解释为 host。 例如,给定 //foo/bar,结果将是 {host: ‘foo’, pathname: ‘/bar’} 而不是 {pathname: ‘//foo/bar’}。 默认值: false。
const http = require('url')
const urlObj = url.parse('http://localhost:3001/list?a=1', true)
console.log(urlObj)
/* {
  protocol: null,
  slashes: null,
  auth: null,
  host: null,
  port: null,
  hostname: null,
  hash: null,
  search: '?a=1',
  query: [Object: null prototype] { a: '1' },
  pathname: '/list',
  path: '/list?a=1',
  href: '/list?a=1'
} */

2.2.2 url.format

url.format(urlObject) 返回从 urlObject 派生的格式化网址字符串

const url = require('url')
url.format({
  protocol: 'https',
  hostname: 'example.com',
  pathname: '/some/path',
  query: {
    page: 1,
    format: 'json'
  }
})

// => 'https://example.com/some/path?page=1&format=json'

2.2.3 url.resolve

url.resolve(from, to) 解析相对于基本 URL 的目标 URL

  • from <string> 如果 to 是相对的 URL,则使用的基本的 URL
  • to <string> 要解析的目标 URL
// 注意加 / 跟不加 / 的区别
const url = require('url')
url.resolve('/one/two/three', 'four')         // '/one/two/four'
url.resolve('/one/two/three/', 'four')        // '/one/two/three/four'
url.resolve('http://example.com/', '/one')    // 'http://example.com/one'
url.resolve('http://example.com/one', '/two') // 'http://example.com/two'

2.3 新版 URL 类

new URL(input[, base])

  • input <string> 要解析的绝对或相对的输入网址。 如果 input 是相对的,则需要 base。 如果 input 是绝对的,则忽略 base。 如果 input 不是字符串,则先转换成字符串。
  • base <string> 如果 input 不是绝对的,则为要解析的基本网址。 如果 base 不是字符串,则先转换成字符串。
const myURL = new URL('/foo', 'https://example.org/');
// https://example.org/foo

详细参考

2.4 querystring 模块

2.4.1 querystring.escape

针对网址查询字符串的特定要求优化的方式对给定的 str 执行网址百分比编码

const querystring = require('querystring')

const str = 'id=北京'
console.log(querystring.escape(str)) // id%3D%E5%8C%97%E4%BA%AC

2.4.2 querystring.unescape

执行网址百分比编码字符的解码

const querystring = require('querystring')

const str = 'id%3D%E5%8C%97%E4%BA%AC'
console.log(querystring.unescape(str)) // id=北京

2.4.3 querystring.parse

将网址查询字符串 (str) 解析为键值对的集合

const querystring = require('querystring')

const str = 'foo=bar&abc=xyz'
console.log(querystring.parse(str)) // { foo: 'bar', abc: 'xyz' }

2.4.4 querystring.stringify

const querystring = require('querystring')
querystring.stringify({ foo: 'bar', baz: ['qux', 'quux'], corge: '' })
// 返回 'foo=bar&baz=qux&baz=quux&corge='

2.5 events 模块

const EventEmitter = require('events')
const myEmitter = new EventEmitter()

myEmitter.on('event', res => {
  console.log(res)
})

setTimeout(() => {
  myEmitter.off('event')
}, 1000)

myEmitter.emit('event', 'res')

2.6 fs 模块

2.6.1 fs.mkdir

创建文件夹

const fs = require('fs')

fs.mkdir('./img', err => {
  // 文件夹新建成功回调
  if (err && err.code === 'EEXIST') {
    console.log('该目录已创建')
  }
})

2.6.2 fs.mkdirSync

fs.mkdir 的同步版本,返回 undefined 或创建的第一个目录路径(如果 recursive 为 true)
const dirPath = fs.mkdirSync('./img', { recursive: true })

2.6.3 fs.rename

const fs = require('fs')

// 把 img 文件夹改为 img2
fs.rename('./img', './img2', err => {
  if (err && err.code === 'ENOENT') {
    console.log('该目录不存在')
  }
})

2.6.4 fs.renameSync

fs.rename 的同步版本,返回 undefined

2.6.5 fs.rmdir

删除文件夹

const fs = require('fs')

// 删除目录
fs.rmdir('./img', err => {
  if (err && err.code === 'ENOENT') {
    console.log('该目录不存在')
  }
})

2.6.6 fs.rmdirSync

fs.rmdir 的同步版本,返回 undefined

2.6.7 fs.readdir

const fs = require('fs')

// 读目录
fs.readdir('./img', (err, files) => {
  // files 是当前文件夹下的文件名数组
  !err && console.log(files)
})

2.6.8 fs.readdirSync

fs.readdir 的同步版本,返回: <string[]> | <Buffer[]> | <fs.Dirent[]>

const fs = require('fs')

const files = fs.readdirSync('./img')
console.log(files)

2.6.9 fs.writeFile

fs.writeFile(file, data[, options], callback) 写文件,内容会覆盖

  • file <string> | <Buffer> | <URL> | <integer> 文件名或文件描述符
  • data <string> | <Buffer> | <TypedArray> | <DataView> | <Object>
  • options <Object> | <string>
    encoding <string> | <null>默认值: ‘utf8’
    mode <integer> 默认值: 0o666
    flag <string> 请参阅对文件系统 flags 的支持。 默认值: ‘w’。
    signal <AbortSignal> 允许中止正在进行的写入文件
  • callback <Function>err <Error> | <AggregateError>
const fs = require('fs')

// 在 img/a.txt 下写入 Hello World!
fs.writeFile('./img/a.txt', 'Hello World!', err => {
  // 写入成功回调
})

2.6.10 fs.appendFile

异步地将数据追加到文件,如果该文件尚不存在,则创建该文件

const fs = require('fs')

fs.appendFile('./img/a.txt', `\n你好,世界!`, err => {})

2.6.11 fs.readFile

异步地读取文件的全部内容

const fs = require('fs')

fs.readFile('./img/a.txt', 'utf-8', (err, data) => {
  !err && console.log(data)
})

2.6.12 fs.unlink

删除文件

const fs = require('fs')

fs.unlink('./img/a.txt', err => {})

2.6.13 fs.stat

判断是文件还是文件夹

const fs = require('fs')

const paths = ['./fs-file.js', './img2']

paths.forEach(path => {
  fs.stat(path, (err, stats) => {
    console.log(stats.isFile()) // 是文件返回 true,不是返回 false
    console.log(stats.isDirectory()) // 是文件夹返回 true,不是返回 false
  })
})

2.6.14 promises 写法

由于Node环境执行的JS是服务端代码,所以绝大部分反复执行的必须用异步代码,不然同步代码在执行期间会导致服务器停止响应,因为JS只有一个执行线程

const fs = require('fs').promises

fs.readFile('./img/a.txt', 'utf-8').then(data => {
  console.log(data)
})

2.6.15 fs.createReadStream

创建一个可读的流

const fs = require('fs')

const rs = fs.createReadStream('a.txt', 'utf-8')

// 读取文件发生错误事件
rs.on('error', err => {
  console.log('发生异常:', err)
})

// 已打开要读取的文件事件
rs.on('open', fd => {
  console.log('文件已打开:', fd)
})

// 文件已经就位,可用于读取事件
rs.on('ready', () => {
  console.log('文件已准备好..')
})
  
// 文件读取中事件,注意 data 事件可能调用多次,每次传递的 chunk 是流的一部分
rs.on('data', chunk => {
  console.log('data:')
  console.log(chunk)
})
 
// 文件读取完成事件
rs.on('end', () => {
  console.log('读取已完成..')
})

// 文件已关闭事件
rs.on('close', () => {
  console.log('文件已关闭!')
})

2.6.16 fs.createWriteStream

创建一个可读写流

const fs = require('fs')

const ws = fs.createWriteStream('./img/b.txt', 'utf-8')

ws.write('1111')
ws.write('2222')
ws.write('你好!')
ws.end()

创建读写管道

const fs = require('fs')

const rs = fs.createReadStream('a.txt', 'utf-8')
const ws = fs.createWriteStream('b.txt', 'utf-8')

// 相当于 b 复制 a
rs.pipe(ws)

2.6.17 fs.existsSync

fs.existsSync(path) 如果路径存在则返回 true,否则返回 false

const fs = require('fs')

const isPath = fs.existsSync('/static/index.html')

2.7 zlib 模块

const http = require('http')
const fs = require('fs')
const zlib = require('zlib')

const gzip = zlib.createGzip()

http.createServer((req, res) => {
  const rs = fs.createReadStream('./index.js')
  res.writeHead(200, {
    'Content-Type': 'application/x-javascript; charset=utf-8',
    'Content-Encoding': 'gzip'
  })
  rs.pipe(gzip).pipe(res)
}).listen(5000, () => {
  console.log('server start')
})

2.8 crypto 模块

加密

const crypto = require('crypto')

const hash = crypto.createHash('md5')

// 加密
hash.update('Hollo World!')
console.log(hash.digest('hex')) // b9713ba17d1a2d5b9f4a8a6ed50c4c77

2.9 path 模块

2.9.1 path.extname

path.extname(path) 返回 path 的扩展名,即 path 的最后一部分中从最后一次出现的 .(句点)字符到字符串的结尾

path.extname('index.html')
// 返回: '.html'

path.extname('index.coffee.md')
// 返回: '.md'

path.extname('index.')
// 返回: '.'

path.extname('index')
// 返回: ''

path.extname('.index')
// 返回: ''

path.extname('.index.md')
// 返回: '.md'

2.9.2 path.parse

path.parse(path) 返回一个对象,其属性表示 path 的重要元素

path.parse('/home/user/dir/file.txt')
// 返回:
// { root: '/',
//   dir: '/home/user/dir',
//   base: 'file.txt',
//   ext: '.txt',
//   name: 'file' }

2.9.3 path.format

path.format(pathObject) 从对象返回路径字符串。 这与 path.parse() 相反

path.format({
  root: '/ignored',
  dir: '/home/user/dir',
  base: 'file.txt'
})
// 返回: '/home/user/dir/file.txt'

2.9.4 path.join

path.join([…paths]) 使用特定于平台的分隔符作为定界符将所有给定的 path 片段连接在一起,然后规范化生成的路径

path.join('/foo', 'bar', 'baz/asdf')
// 返回: '/foo/bar/baz/asdf'

2.9.5 path.resolve

path.resolve([…paths]) 将路径或路径片段的序列解析为绝对路径

path.resolve('/foo/bar', './baz')
// 返回: '/foo/bar/baz'

path.resolve('/foo/bar', '/tmp/file/')
// 返回: '/tmp/file'

三、路由

3.1 路由基础

const http = require('http')
const fs = require('fs')

const server = http.createServer()

server.on('request', (req, res) => {
  const url = new URL(req.url, 'http://127.0.0.1')
  const pathname = url.pathname
  switch (pathname) {
    case '/':
    case '/home':
      res.writeHead(200, {
        'Content-Type': 'text/html; charset=utf-8',
      })
      res.write(fs.readFileSync('index.html', 'utf-8'))
      break;
    case '/about':
      res.writeHead(200, {
        'Content-Type': 'text/html; charset=utf-8',
      })

      res.write(fs.readFileSync('about.html', 'utf-8'))
    default:
      res.writeHead(404, {
        'Content-Type': 'text/html; charset=utf-8',
      })
      res.write(fs.readFileSync('404.html'))
  }
  res.end()
})

server.listen(3000, () => {
  console.log('server start')
})
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一条 Node.js 的学习路线,供你参考: 1. 开始学习 JavaScript。掌握基本语法和特性,包括变量、数据类型、条件语句、循环语句、函数、对象、数组等。可以通过 W3School 或者 MDN 等网站进行学习。 2. 掌握 Node.js 的基本概念和基础知识。了解 Node.js 的历史、特点、应用场景等,同时学习 Node.js 的模块系统、事件循环、异步编程等基本概念。 3. 学习 Node.js 的核心模块。Node.js 提供了众多内置的模块,如文件系统、HTTP、网络、流等,需要掌握这些模块的使用方法。 4. 掌握 Node.js 的第三方模块。Node.js 生态系统非常丰富,有很多优秀的第三方模块,如 Express、Koa、Socket.io 等,需要学习这些模块的使用方法。 5. 学习数据库操作。Node.js 可以连接多种类型的数据库,如 MySQL、MongoDB、Redis 等,需要掌握数据库的基本操作和连接方法。 6. 学习 Web 开发。使用 Node.js 可以轻松创建 Web 应用程序,需要学习 HTML、CSS、JavaScript 等前端技术,以及 Express、Koa 等 Web 框架的使用方法。 7. 学习安全性。在开发 Web 应用程序时需要注意安全性,如 XSS、CSRF、SQL 注入等,需要掌握一些基本的安全知识和防御方法。 8. 学习性能优化。Node.js 应用程序需要考虑性能问题,如优化代码、减少请求响应时间、减少资源消耗等,需要学习一些性能优化技巧和工具。 9. 学习测试和调试。在开发 Node.js 应用程序时需要进行测试和调试,需要学习一些测试框架和工具,如 Mocha、Chai、SuperTest 等。 10. 学习部署和维护。Node.js 应用程序需要部署到生产环境中,并进行维护和监控,需要学习一些部署和维护技巧和工具,如 PM2、Nginx、Logrotate 等。 以上是 Node.js 的学习路线,需要不断实践和总结,才能掌握 Node.js 的核心技术和应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值