Node.js

Node.js是一个基于Chrome V8引擎的JS运行环境

注意

  • 浏览器是js的前端执行环境,node.js是js的后端执行环境。
  • Node.js中无法调用DOM、BOM与AJAX等浏览器内置API

fs 文件系统模块

​ 引用fs模块

1
const fs = require("fs");

fs.readFile()

​ 使用readFile可以读取指定文件中的内容,格式如下(甚至可以我读我自己):

1
2
3
4
5
6
7
8
9
fs.readFile('test.txt', 'utf8', (err, data) => {
if (err) {
// 读取成功err为null
console.error(err);
} else {
// 读取失败时data为undefined
console.log(data);
}
})
  • 参数一:必选,字符串,表示文件路径;
  • 参数二:可选,表示以什么格式来读取文件,一般默认为utf8;
  • 参数三:必选,表示回调函数,err为错误信息,data为读取到的内容。

fs.writeFile()

​ 使用writeFile可以向指定的文件中写入内容,格式如下:

1
2
3
4
5
fs.writeFile('test.txt',"666","utf8",(err) => {
if (err) {
console.error(err);
}
})
  • 参数二表示写入的内容,会覆盖文件的原内容;
  • 回调函数只有err参数,其余部分与readFile相同;
  • 若文件不存在,则会新建文件。

处理路径问题

​ 如果操作路径是相对路径。容易出现路径动态拼接错误的问题。

 class person{    name:T;    constructer(name: T){        this.name = name;   }}ts

​ 可以使用__dirname来表示当前文件所处的目录,可通过字符串的拼接来得到完整路径。

path 路径模块

path模块是Node.js官方提供的用来处理路径的模块。

1
const path = require("path");

path.join()

​ 用来将多个路径片段拼接成一个完整的路径字符串

1
2
3
path.join(__dirname,"/test.txt");
// '../'会抵消一层路经
console.log(path.join('/a','/b/c','../','./d','e')); // 输出\a\b\d\e

path.basename()

​ 通过该方法可以获取路径中的最后一部分,通常用basename获取路径中的文件名

1
2
3
4
const test = path.basename(path.join(__dirname,"name.txt"));
// 参数二可选,表示文件后缀名
console.log(path.basename(test)); // name.txt
console.log(path.basename(test,".txt")); // name

path.extname()

​ 用来获取路径中的扩展名,格式为path.extname(path),返回值为获取的扩展名

html 模块

http模块是用来创建web服务器的模块

1
const http = require("http");

创建服务器

1
2
3
4
5
6
7
8
9
10
// 创建server
const server = http.createServer();
// 绑定request事件
server.on('request',(req,res)=>{
console.log("666");
})
// 启动服务器
server.listen(8000,()=>{
console.log('server started');
})

req请求对象

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

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

res响应对象

  • res.end(test) 其中test为向客户端发送的内容,并结束本次请求

res.setHeader()

​ 当调用res.end()方法时,想客户端发送中文内容时会出现乱码,为此需要在发送前设置响应头。

1
res.setHeader('content-type','text/html;charset=utf-8');

​ 参数一为响应头的名字,参数二为该响应头的值。

案例

​ 在浏览器访问网址,通过res.url解析出文件路径,再通过fs.readFile()方法读取文件内容,通过res.end()发送给浏览器使html文件呈现在页面上。

初步代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// server.js
// 导入模块
const http = require('http');
const fs = require('fs');
const path = require('path');
// 创建服务器
const server = http.createServer();
server.on('request',(req,res)=>{
let url;
// 设置响应头
res.setHeader('content-type','text/html;charset=utf-8');
// 进行判断并合成地址,如果地址为‘/’则替换为html文件地址
if(req.url === '/' || req.url === "index.html"){
url = path.join(__dirname,'/page/index.html');
} else {
url = path.join(__dirname, "/page", req.url);
}
// 读取文件
fs.readFile(url,'utf8',(err,data)=>{
if(err){
res.end('404 not found');
} else {
res.end(data);
}
});
})
server.listen(8000,()=>{
console.log('server started');
})

问题

  • 浏览器根据 HTTP 响应头里的 Content-Type 来决定如何处理收到的资源。如果你不显式把 CSS 文件的 Content-Type 设置成 text/css,浏览器可能会当作 text/plain 或者二进制流处理,最终就不会应用其中的样式,因此页面上不会显示css内容。

​ 因此在响应css请求时需要修改响应头,设置为text/css

1
res.setHeader('content-type','text/css;charset=utf-8');

然而这样的话每种类型的请求都需要重新设置响应头,过于繁琐,因此可以使用mine-types库。

改进方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const http = require('http');
const fs = require('fs');
const path = require('path');
// 导入mime-types
const mime = require('mime-types');

const server = http.createServer();
server.on('request',(req,res)=>{
let url;
if(req.url === '/' || req.url === "test.html"){
url = path.join(__dirname,'/page/test.html');
} else {
url = path.join(__dirname, "/page", req.url);
}
fs.readFile(url,'utf8',(err,data)=>{
if(err){
res.end('404 not found');
} else {
// 在响应前设置响应头
// 使用mime.looker()方法可以得到类似"text/html"、"text/css"、"application/javascript"的返回值
res.setHeader('content-type', mime.lookup(url) + ';charset=utf-8');
res.end(data);
}
});
})
server.listen(8000,()=>{
console.log('server started');
})

​ 除此之外还可以使用mime库,但是需要改为ESM模块,即需要:

  1. package.json中声明"type": "module" 或 将js文件后缀改为.mjs;

  2. 将所有require修改为import,但这样就没有了__dirname

  3. 在ESM中重建 __filename__dirname

    1
    2
    3
    4
    5
    import { fileURLToPath } from 'url';
    // fileURLToPath(import.meta.url) 会把类似 'file:///Users/you/project/server.mjs' 转成 '/Users/you/project/server.mjs'
    const __filename = fileURLToPath(import.meta.url);
    // path.dirname(...) 则得出该文件所在的目录
    const __dirname = path.dirname(__filename);
  4. mime库中与mime-types的lookup方法类似的是getType,其余地方与使用mime-types的方法一致。