Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,Node.js 是 JavaScript 的后端运行环境,官方网站:https://nodejs.org/zh-cn/
Node.js为JavaScript提供了一些服务器级别的操作API,可以用来进行:文件读写、网络服务的构建、网络通信、构建http服务器等操作
前端工程化
打包工具 bundle,uglify等等都使用 node
web服务端应用
学习曲线平滑,效率高,其他后端语言可以实现的 node 都可以实现,有用丰富的工具和生态,与前端结合场景有优势,比如 ssr
跨端桌面应用
比如 electron,大型公司内的效率工具
node的运行结构如下:
它运行时有三个特点:异步IO,单线程,跨平台
当Node.js执行I/O操作时,会在响应返回后恢复操作,而不是阻塞线程并占用额外的内存等待
原因是 js 这个语言是单线程的,node底层是 JS线程+ uv线程 +V8任务线程池 + V8 Inspector线程。这样的好处是不用考虑多线程状态同步问题,同时还能比较有效的利用系统资源;确定点是阻塞会产生更多的负面影响
解决办法是使用多线程或者多进程工具
node 封装了大部分操作系统的api 提供我们调用,但是也有部分某些平台特有的 api,比如linux特有的,因为 nodejs 跨平台,js无需编译环境,所以开发成本低,整体学习成本低
为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统。模块是Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个 Node.js 文件就是一个模块。
Node.js 模块系统使用 CommonJS 规范,并且分为三大类:
node 的模块使用 require() 方法加载,模块在第一次加载后会被缓存,多次调用 require() 不会导致模块的代码被执行多次,不同的模块有不同的加载规则:
// 加载内置的模块
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 模块是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() 是向文件中写入内容的函数,它的三个参数是:
同样这个方法也有它的同步版本 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() 用于对一个文件进行改变,可以进行重命名也可以进行路径的移动,它的三个参数是:
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');
})
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 请求
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)
})
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点要求:
我们可以使用 npm login 登录到官方,当然你需要先注册一个账号,官网地址: https://www.npmjs.com/,之后运行 npm publish 命令将包推送到官方仓库
V8 Inspector:开箱即用,特性丰富强大,与前端开发一致、跨平台
用途: