NodeJs 概述
Node.js 诞生于2009年,Node.js采用C++语言编写而成,是 一个Javascript的运行环境。Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境 ,让JavaScript的运行脱离浏览器端,可以使用JavaScript语言书写服务器端代码。
nodejs = ECMAScript + 各种基于ES的模块(net,http,FileSystem)
- server 服务端开发(通过网络提供各种数据)
- 工具:vue-cli,create-react-app
- 桌面端(electorn, nw):vscode
那么js可以简单理解为
JavaScript = ECMAScript + DOM + BOM。
特点
- 单线程
- 非阻塞 I/O
- 访问文件
- 网络请求
- 数据库查询
- 键盘/鼠标交互
- 事件驱动
common.js 规范
-
CommonJS就是为JS的表现来制定规范,因为js没有模块的功能所以CommonJS应运而生,它希望js可以在任何地方运行,不只是浏览器中。
1、创建自定义模块
-
引入一个文件 形式模块
home.js执行文件
//通过require来引入 require("./aModule"); //注意一定要有"./",文件后缀可加可不加。amodule.js文件
console.log("我是amodule模块111"); -
引入文件夹形式模块
- home.js执行文件
require("./aModuledir"); //必须加"./" aModuleDir里的index.js文件,会自动查找文件夹下的index.js文件执行
console.log("我是aModule模块文件夹");- 当然也可以配置默认启动文件,在文件夹内新建package.json来指定执行文件
{ "name":"aModule", "version":"1.0.0", "main":"test.js" }
-
-
自定义模块的按需导出
通过module.exports 导出;
module.exports = { a:"我是a的值", b(){ console.log("我是导出的b函数"); } }引入导出文件
let mymodule = require("bModule"); console.log(mymodule.a); mymodule.b();或者 通过 exports来导出
exports.fn = function(){ console.log("我是fn函数"); }导入文件
let myfn = require("bModule").fn; myfn(); // 或者 通过解构赋值 let { fn } = require("bModule"); fn(); -
模块加载的优先级 ,先文件再目录;
2、内置模块;
nodejs内置模块有:Buffer,C/C++Addons,Child Processes,Cluster,Console,Cr
ypto,Debugger,DNS,Domain,Errors,Events,File System,
Globals,HTTP,HTTPS,Modules,Net,OS,Path,Process,P unycode,Query Strings,Readline,REPL,Stream,String De coder,Timers,TLS/SSL,TTY,UDP/Datagram,URL, Utilities,V8,VM,ZLIB;内置模块不需要安装,外置模块需要安装;
3、第三方模块
第三方模块使用npm工具包下载,会放在node_module里面
http模块创建服务
ECMAScript运行在服务器端,就可以提供服务。这个时候需要http 内置模块,来进行http的服务器开发。
//引入http模块
let http = require("http");
//创建一个服务器
let server = http.createServer((req,res)=>{
console.log("hello");
res.end("hello world");
})
//设置端口号
server.listen(3000);
-
http.createServer(callback)
callback --> 回调函数,当有客户端请求发送,并被当前server监听到了, 则会执行该函数。
callback--> 两个参数 request ,response
-
具体看第三点 服务器响应和客户端的请求
-
request: http.ClientRequest 类,request 类存储当前请求的客户端信息和方法
-
response: http.ServerResponse 类,response 类提供服务器响应相关的信息和方法
- response.write() 回应客户端发送数据
- response.end()告诉客户端,已经读写完毕。必须
-
-
server.listen(3000,callback)
第一个参数是:端口号,默认8080
callback--> 启动服务时候运行的函数
fs模块加载静态文件
-
fs是文件操作模块,所有文件操作都是有同步和异步之分,特点是同步会加上 "Sync" 如:异步读取文件 "readFile",同步读取文件 "readFileSync";
-
读取到文件内容不一定是字符串,可能是图片视频等,那么它将他都转为buffer 二进制形式
-
文件操作方法
-
文件读取:
- 异步读取,容易造成回调地狱
let fs = require("fs"); fs.readFile("1.txt",(err,data)=>{ if(err){ return console.log(err); } console.log(data.toString()); })- 同步读取文件,
let fs = require("fs"); let res = fs.readFileSync("1.txt"); console.log(res.toString()); -
文件写入:
let fs = require("fs"); //flag配置 "a":追加写入,"w":写入,"r":读取 fs.writeFile("2.txt","我是要写入的内容",{flag:"w"},err=>{ if(err){ return console.log(err); } console.log("写入成功"); }) -
文件删除
fs.unlink("2.txt",err=>{ if(err){ return console.log(err); } console.log("删除成功"); }) -
复制文件
- 先读取文件再写入文件
function mycopy(src,dest){ fs.writeFileSync(dest,fs.readFileSync(src)); } mycopy("1.txt","4.txt"); -
修改文件名,目录也可以通过rename来操作
fs.rename("1.txt","5.txt",function (err) { if(err){ console.log(err); }else{ console.log("修改成功"); } }); -
判断文件是否存在
fs.exists("4.txt",function (exists) { console.log(exists); })
-
-
目录操作方法
// 创建目录 fs.mkdir("11",err=>{ if(err){ return console.log(err); } console.log("创建成功"); }) 修改目录名称 fs.rename("11", "22", err => { if (err) { return console.log(err); } console.log("修改成功"); }) 读取目录; fs.readdir("22",(err,data)=>{ if(err){ return console.log(err); } console.log(data); }) 删除目录(空文件夹/目录) fs.rmdir("11",err=>{ if(err){ return console.log(err); } console.log("删除成功"); }) 判断文件或者目录是否存在 fs.exists("index.html",exists=>{ console.log(exists); }) 获取文件或者目录的详细信息; fs.stat("index.html",(err,stat)=>{ if(err){ return console.log(err); } // console.log(stat); // 判断文件是否是文件 // let res = stat.isFile(); // 是否是一个文件夹; let res = stat.isDirectory(); console.log(res); }) // 删除非空文件夹; // 先把目录里的文件删除-->删除空目录; // 22 function removeDir(path){ let data = fs.readdirSync(path); // ["33","1.txt","2.html"]; for(let i=0;i<data.length;i++){ // 是文件或者是目录; --->?文件 直接删除?目录继续查找; let url = path + "/" + data[i]; let stat = fs.statSync(url); if(stat.isDirectory()){ //目录 继续查找; removeDir(url); }else{ // 文件 删除 fs.unlinkSync(url); } } // 删除空目录 fs.rmdirSync(path); } removeDir("22");
服务器响应和客户端的请求
response
客户端访问的地址(url)与后端的文件不是一对一关系,它们只是一种虚拟映射关系,这个关系是我们后端程序根据实际情况去返回的。
例如我这里的情况,在客户端无论地址写后面写什么都是虚拟地址,返回的相应都是./template/index.html 这个服务器端的这个实际地址的数据。
而客户端根据不同地址返回不同网页这个动作,其实是需要在服务器端设置。做一个一一对应。例如:
http://localhost:3000/index.html 客户端发起这个请求,那么后端设置 path/index.html
http://localhost:3000/part1.html 客户端发起这个请求,那么后端设置 path/part1.html
...
这样才能根据客户端虚拟地址的不同返回不同的页面,不然就只能是同一个页面
const http = require('http');
//引入fs 模块
const fs = require('fs');
let server = http.createServer((req,res)=>{
const content = fs.readFileSync('./template/index.html')
res.write(content);
res.end();
})
server.listen(3000,()=>{
console.log('服务启动成功, 地址:http://localhost:3000');
});
request
我们页面发起请求的时候有有地址请求,还有就是对静态文件的请求。例如css 文件等。那么request 参数里面有个一个url的属性可以读取客户端发过来的请求。
例如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Title</title>
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<h1>Hello world!!</h1>
</body>
</html>
//css
body{
background-color: antiquewhite;
}
//服务端
const http = require('http');
//引入fs 模块
const fs = require('fs');
let server = http.createServer((req,res)=>{
let url = req.url;
console.log(url);
const content = fs.readFileSync('./template/index.html')
res.write(content);
res.end();
})
server.listen(3000,()=>{
console.log('服务启动成功, 地址:http://localhost:3000');
});
当我们这样发起请求时候会返回这两个结果。
/
/css/index.css
但是我们 const content = fs.readFileSync('./template/index.html')这里已经写死,无论什么请求都返回这个文件。所以css在这里并没有起作用。于是我们可以猜想,可以使用switch case 语法解决。
这样修改后就能显示正确的样式
let url = req.url;
let content = ''
console.log(url);
switch (url) {
case "/":
content = fs.readFileSync('./template/index.html')
break;
case "/css/index.css":
content = fs.readFileSync('./template/css/index.css');
break;
}
前后端静态资源交互
上面的例子可以处理简单的请求,但是实际中,一个网页有多图片、文件等静态资源。不可能一一对应。所以我们可以和后端制定统一的规则读取静态文件。例如约定以/public开头的请求就是要读取静态文件。实际的静态文件存储在服务器的static
当然我们的静态页面可以放进我们的static文件里面。那么访问静态的页面的时候,我们需要把地址修改成
if(url.startsWith('/public'))
{
url = url.replace(/^\/public/g,'\\static');
//console.log('static',__dirname + url);
content = fs.readFileSync(__dirname + url);
res.write(content);
}
请求头设置header
每次交换的数据(请求、响应),我们称为:报文
每一个报文数据包含:行、头、正文 ['行', '头', '正文']
正常用户看到的是正文,但是服务器给我们发送信息除了正文,还有行信息和头信息
-
行信息
-
头信息
一般用于额外的数据处理。客户端请求带过去服务器端的信息,还有就是服务器端带过来的信息。因为信息以二进制方式传递,那么我们在发送信息的时候要设置头信息,告诉浏览器这是个什么文件,让浏览器引擎解析。
例如这段代码,如果不设置
res.setHeader('Content-Type','text/html;charset=utf-8');浏览器将会把中文解析为乱码。else { res.setHeader('Content-Type','text/html;charset=utf-8'); res.write('欢迎来到我的nodeJs'); }当然头信息还有很多,我们以后会慢慢补充。
相关工具包
yarn、cnpm、nvm、nrm工具介绍
-
npm
-
NPM(Node Package Manager) 官网的地址是 npm官网
- npm常用指令;
- npm init:引导创建一个package.json文件
- npm help(npm -h) :查看npm帮助信息
- npm version (npm -v) : 查看npm版本;
- npm search:查找
- npm install (npm i):安装 默认在当前目录,如果没有node_modules 会创建文件夹;
- npm install module_name -S 或者--save 即 npm install module_name --save 写入dependencies
- npm install module_name -D 或者 —save-dev 即 npm install module_name --save-dev 写入devDependencies
- npm install module_name -g 全局安装(命令行使用)
- 指定版本安装模块 npm i module_name @1.0 通过 "@"符号指定;
- npm update(npm -up):更新
- npm remove 或者 npm uninstall:删除
- npm root 查看当前包安装的路径 或者通过 npm root -g 来查看全局安装路径;
- npm常用指令;
-
-
nrm
管理源的工具。管理下载地址的,能测试延迟等功能
-
cnpm
切换下载镜像地址的,cnpm会更快一点,但是会有延迟性
-
yarn 包管理工具
yarn 和npm 差不多现在,yarn 是解决npm 旧版本问题的
npm install -g yarn
-
nvm
-
nvm 是 mac 环境下管理 nodejs 的工具。在 windows 环境下推荐使用 nvmw 或者 nvm-windows;
- Nvm-windows 下载地址 github.com/coreybutler… 下载 nvm-setup.zip
-
安装 NVM
- 在安装 nvm 之前需要一个 c++编译器,在 mac 上可以安装 Xcode 命令工具(已经安装可以忽略)
xcode-select --install- 使用 curl 安装
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash- 或者使用 wget 来安装
wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash -
NVM github 的地址可以查看最新版本
-
NVM 常用指令;
nvm --version查看版本nvm install stable //安装最新稳定版nodejsnvm install 8.11.1 //安装指定版本nvm install 8.11 //安装 8.11.x系列最新版本nvm ls-remote //列出远程服务器上所有可用的版本nvm use 8.11.1 //切换到8.11.1版本nvm use 8.11 //切换到8.11.x最新版本nvm use node //切换到最新版本nvm alias default node //设置默认版本为最新版本nvm ls //列出所有已经安装的版本
-