字节青训前端笔记 | Node入门

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,Node.js 是 JavaScript 的后端运行环境,官方网站:https://nodejs.org/zh-cn/

Node.js为JavaScript提供了一些服务器级别的操作API,可以用来进行:文件读写、网络服务的构建、网络通信、构建http服务器等操作

node 的应用场景

  • 前端工程化

    打包工具 bundle,uglify等等都使用 node

  • web服务端应用

    学习曲线平滑,效率高,其他后端语言可以实现的 node 都可以实现,有用丰富的工具和生态,与前端结合场景有优势,比如 ssr

  • 跨端桌面应用

    比如 electron,大型公司内的效率工具

node运行时

node的运行结构如下:

字节青训前端笔记 | Node入门_第1张图片

它运行时有三个特点:异步IO,单线程,跨平台

  • 异步IO

当Node.js执行I/O操作时,会在响应返回后恢复操作,而不是阻塞线程并占用额外的内存等待

  • 单线程

原因是 js 这个语言是单线程的,node底层是 JS线程+ uv线程 +V8任务线程池 + V8 Inspector线程。这样的好处是不用考虑多线程状态同步问题,同时还能比较有效的利用系统资源;确定点是阻塞会产生更多的负面影响

解决办法是使用多线程或者多进程工具

  • 跨平台

node 封装了大部分操作系统的api 提供我们调用,但是也有部分某些平台特有的 api,比如linux特有的,因为 nodejs 跨平台,js无需编译环境,所以开发成本低,整体学习成本低

node 的模块系统

为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统。模块是Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个 Node.js 文件就是一个模块。

Node.js 模块系统使用 CommonJS 规范,并且分为三大类:

  • 内置模块:由 node.js 官方提供的,例如 fs, path, http 等
  • 自定义模块:用户创建的每一个 .js 文件,都是自定义模块
  • 第三方模块:由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要下载。

模块导入

node 的模块使用 require() 方法加载,模块在第一次加载后会被缓存,多次调用 require() 不会导致模块的代码被执行多次,不同的模块有不同的加载规则:

  1. 内置模块是由Node.js 官方提供的模块,内置模块的加载优先级最高
  2. 使用 require() 加载自定义模块时,必须指定以 ./ 或 …/ 开头的路径标识符。如果省略了文件的扩展名,则Node.js 会按照 .js , .json , .node 分别尝试,如果没用符合要求的内容,则报错
  3. node 会从 /node_modules 文件夹中加载第三方模块
  4. 当把目录作为模块标识符时,会在被目录下查找一个叫做package.json的文件,并寻找 main属性,作为 require()加载的入口,如果没用则加载目录下的 index.js 文件,如果以上两步都失败了则报错
// 加载内置的模块
const  fs= require('fs')

// 加载用户的自定义模块
const  test = require('./test.js')

// 加载第三方模块
const  moment= require('moment')

模块的导出

而在自定义模块中,可以使用 module.exports 对象,将模块内的成员共享出去,供外界使用,使用 require() 方法导入模块时,导入的结果永远是module.exports 指向的对象。

//导出单个数据
module.exports.msg = 'test'
//导出一个对象
module.exports = {
	msg: 'test',
	say(){
		console.log('test')
	}
}

原生模块

fs 文件系统模块

fs 模块是Node.js 官方提供的,用来操作文件的模块。它提供了一系列的方法和属性,用来满足用户对文件的操作需求。

fs.readFile 用于读取指定文件的内容,他有三个参数:

1. 字符串,表示文件路径;
2. 可选参数,表示以什么编码格式来读取文件
3. 传入一个函数,表示文件读取完,通过回调函数拿到读取的结果 

fs.readFileSync() 则是上述方法的同步版本,就是方法必须执行完毕才会进行吓一语句,因为是同步的方法,所以它没用第三个也就是函数的参数作为回调,而是直接返回读取到的内容

// 导入 fs 模块,
const fs = require('fs');

//异步读取文件
fs.readFile( 'a.txt' , 'utf8', (err, data)=>{
     //如果出错  则抛出错误
     if(err)  throw err
     console.log(data.toString());
})

fs.writeFile() 是向文件中写入内容的函数,它的三个参数是:

  1. 字符串,表示文件存放的路径;
  2. 可选参数,表示要写入的内容
  3. 回调函数

同样这个方法也有它的同步版本 fs.writeFileSync()

// 写入文件
fs.writeFile("a.txt","测试",(err)=>{
   // 如果写入成功 err 会打印 null,
    console.log(err);
})

与上面的函数用法相似,fs.appendFile() 用于在不改变原来内容的情况下追加内容,而 writeFile 则会覆盖原来的所有内容

fs.mkdir() 用于创建目录,第二个参数可选用于设置权限

fs.mkdir('./css',777,(err)=>{
    if(err) throw err;
    console.log("成功");
}

fs.stat() 用于检测是文件还是目录

fs.readdir() 读取目录中的所有文件,返回一个数组

fs.rmdir() 用于删除目录

fs.unlink() 用于删除文件

上述函数用法类似,都是传入一个路径和一共回调函数

fs.stat('./a.txt',(err, data)=>{
    console.log(`是文件:${data.isFile()}`);  //布尔值
    console.log(`是目录:${data.isDirectory()}`); //布尔值
})
fs.readdir('./html',(err,data)=>{
    if(err) throw err;
    console.log("读取目录成功",data);
})

fs.rename() 用于对一个文件进行改变,可以进行重命名也可以进行路径的移动,它的三个参数是:

  1. 字符串,表示文件存放的位置;
  2. 字符串,表示文件修改的位置和名字;
  3. 回调函数
fs.rename('./css/index.html','./css/index.css',(err)=>{
    if(err) throw err;
    console.log("重命名成功");
})
 
fs.rename('./html/hh.css','./css/www.css',(err)=>{
    if(err) throw err;
    console.log("移动文件并重命名成功");
})

fs.createReadStream() ,fs.createWriteStream() 分别用于打开读取和写入文件流,通常对大文件的拷贝,写入等,会采用文件流的方式进行操作

var readStream = fs.createReadStream('./a.txt');
// 读取
readStream.on('data',data=>{
     console.log(data)
})
// 取完完毕
readStream.on('end',()=>{
	 console.log('end')
})

var writeStream = fs.createWriteStream('./a.txt');
//写入
writeStream.write('test')
writeStream.end();
//写入完毕回调
writeStream.on('finish',()=>{
    console.log('end');
})

path 路径模块

node 可以通过 path 模块获取路径,并且通过函数将路径进行操作:

通过__dirname 可以获取当前文件所处的路径

path.resolve 把一个路径或路径片段的序列解析为一个绝对路径

path.relative 则是相对路径

path.join 则是可以拼接路径片段的序列

path.normalize 则可以格式化路径

 var absPath=path.resolve("foo/bar","tmp/file/","..","./js");
// foo/bar/tmp/js
 var relPath=path.relative("foo/bar/baz","foo/bar/tmp");
// ../tmp
 var joinPath=path.join("foo","/bar","../","tmp");
 // foo/tmp
var norPath=path.normalize("foo//bar/baz/..");
 // foo/bar

path.basename() 获取一个路径中的文件名称,你可以指定后缀然后只获取名字去掉后缀;path.extname() 则是获取文件拓展名;path.dirname 返回文件所处的文件夹

 var basePath=path.basename("foo/bar/tmp/img.png");
// img.png
 var basePath=path.basename("foo/bar/tmp/img.png","png");
// img
 var extPath=path.extname("img.png");
 // .png
 var dirPath=path.dirname("foo/bar/tmp");
 // foo/bar

http 模块

http 模块用于启动一个 http 服务器,可以通过它接收前端请求,操作服务器、返回需要的数据:

//加载 http 请求
var http = require("http");
// 创建http请求服务器
let server = http.createServer();
// 设置端口号。默认是80
server.listen("8080",function(){
});

如果服务器收到客服端请求,会调用 server.on() 为服务器绑定 request 事件处理函数。你可以获取一个 req 对象来获取这个请求的相关数据:
req.baseUrl:获取路由当前安装的URL路径

req.body / req.cookies:获得「请求主体」/ Cookies,//post请求参数获取

req.params:获取路由的parameters

req.path:获取请求路径

req.query:获取URL的查询参数串

req.url 是客户端请求的 URL地址

req.method 是客户端请求的 method 类型

server.on('request',(req)=>{
    // req 是请求对象
    const url = req.url
    console.log(str);
})

我们可以使用 res 响应对象返回我们的数据

server.on('request',(req, res)=>{
    const str = "test";
    //res.end() 方法,向客户端发送指定内容
    res.end(str)
})

第三方模块

NPM下载

node 通过了一个工具 npm ,我们可以使用它在下载其他发布的模块,我们下载的内容会保存在node_modules 文件夹下,require() 导入第三方包时,就是从这个目录中查找并加载包。npm 的常用命令如下:

npm init [-y] //用来初始化项目,并生成一个package.json文件
npm install //用于安装当前项目的所有依赖,指的是package.json文件中所记录的依赖项。
npm install pagckagename --save 或 -S //下载某个包,并把该包的信息记录到生产环境依赖中(dependencies)
npm install pagckagename --save-dev 或 -D //下载某个包,并把该包的信息记录到开发环境依赖中(devDependencies)。同样需要注意的是-D是大写的。
npm install pagckagename --global 或 -g //全局安装某个包,指安装到你的电脑本地,其他人不能使用
npm -v //查看当前电脑上安装的npm版本号
npm view pagckagename version //查看远程仓储上某个package的正式版本的、最新的版本号
npm view pagckagename versions //查看远程仓储上某个package的所有历史版本。包括alpha版、beta版等等
npm uninstall pagckagename  //卸载某个包,参数和上述install一致

我们可以使用 package.json 文件的 dependencies 节点(生产环境)和 devDependencies 节点(开发环境)来记录项目中安装了哪些包,其他用户使用 npm install 命令就可以依次安装 package.json 指定的包,

同时当我们使用 npm 下载的资源之后,我们会获得一个 package-lock.json 配置文件,用于记录 node_modules 目录下的每一个包的下载信息

发布包

我们可以将自己写的 node 模块整合成包发布到官方仓库提供其他用户使用,一个规范的包,它的组成结构,必须符合以下3点要求:

  1. 包不能重名
  2. 包的顶级目录下要必须包含package.json这个包管理配置文件
  3. package.json 中必须包含name,version,main这三个属性,分别代表包的名字、版本号、包的入口。package.json 文件的其他配置给出一个博客供大家参考:https://blog.csdn.net/song_6666/article/details/123739622

我们可以使用 npm login 登录到官方,当然你需要先注册一个账号,官网地址: https://www.npmjs.com/,之后运行 npm publish 命令将包推送到官方仓库

node 调试

V8 Inspector:开箱即用,特性丰富强大,与前端开发一致、跨平台

  • node --inspect
  • 打开 [http://localhost:9229/json] 进入devtoolsFrontendUrl后的url
  • 打开 chrome://inspect 然后点击Open dedicated DevTools for Node

用途:

  • 查看console.log内容
  • breakpoint
  • 高CPU、死循环:cpuprofile
  • 高内存占用:heapsnapshot
  • 性能分析

部署

  • 需要解决的问题
    • 守护进程:当进程退出时,重新垃圾
    • 多进程:cluster便捷的利用多进程
    • 记录进程状态,用于诊断
  • 容器环境
    • 通常有健康检查手段,只需考虑多核cpu利用率即可

你可能感兴趣的:(字节跳动青训营笔记,javascript,前端,json,node.js,后端)