关于nodejs服务器的大部分教程都是一上来直接让你使用 ‘req.send()’ 发一个 ‘Hello world’,然后就直接跳到使用 ‘express’ 之类的框架去了。
之前一直用的是webstorm,它在预览的时候可以启动一个localhost端口,现在转sublime,只能通过直接打开HTML文件的方式来预览页面,正好nodejs本身就是为服务器所诞生的,但使用express框架又有一种大炮打蚊子的感觉,那就自己写一个简单的服务器吧 :-)
一般来说服务器的业务流程有以下几步
- cookie session用户表示
- body-parse解析请求
- router分发
- 静态资源html
- SOA(service-oriented architecture)服务获取
……
对于一个简易的服务器来说,基本上做到响应浏览器的请求,调度静态资源并发送给浏览器就可以满足需求了,那么,如何做到呢
创建一个工作目录
- server.js 为设置node服务器的文件
- public文件夹中为需要发送的单页面文件,包含基本的 HTML,css,javascript文件
需要使用到的node原生模块
http
- 启动服务器所必需的
fs
- 对资源调度涉及到对文件系统的操作
path
- 对资源的调度当然要通过路径来操作
实例化一个http服务器对象,并响应页面请求
const http = require('http'),
fs = require('fs'),
path = require('path'),
server = http.createServer();
//req为request的缩写,意思为(浏览器)请求
//res为response的缩写,意思为(服务器)响应
server
.on('request', (req, res) => {
})
.listen(4000);
首先,发送一个文件进行测试
那就使用public文件夹下的 index.html 吧
<!--public/index.html-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<p>Hello world</p>
</body>
</html>
在上面代码倒数第三行函数里踢添加如下语句
let filePath = path.join(__dirname,'/public/index.html') ;
res.writeHead(200, {
'Content-type': 'text/html'
});
let readStream = fs.createReadStream(filePath);
readStream.pipe(res);
- path.join() 方法是可以将传入其中的参数组合成一个完整路径,
__dirname
的值为当前目录的绝对路径,在我的电脑上的值是这样的:/Users/nizhenyang/Desktop/未命名文件夹
- res.writeHead() 方法的内容为传回浏览器的相关信息,第一个200为http状态码,表示正常,第二个参数为传回去的文件类型,这里是HTML文件
- fs.createReadStream() 方法是接收一个文件路径,产生一个读取那个文件的对象,画风如下,其中的属性
path
就是前面 path.join() 方法生成的路径(这是我的电脑上的路径):
- readStream.pipe() 方法接收一个对象,将当前文件数据传给它
好了,保存,启动node(切记使用node做项目之前要在项目根目录中执行 ‘npm init’ 来初始化项目,生成一个json文件),也就是在命令行中输入’node server.js’,打开浏览器,输入 ‘localhost:4000’,画风如下:
如果出现找不到 ‘favicon.ico’ 的错误不用说在意,那个是用来表示网页图标的(就是浏览器标签左边的那个图标)
推荐使用 supervisor 来启动服务,因为使用原生node的话每次更改文件都需要重新启动,而前者不需要,输入以下命令进行安装
npm install supervisor -g
如果出现权限问题,则使用
sudo npm install supervisor -g
对请求信息进行分析
那个函数接收的参数有两个,现在查看第一个参数的url属性值,画风如下:
一个斜杠
那么,如果在HTML文件中引入 js 以及 css 文件呢
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<p>Hello world</p>
<script src="js/app.js"></script>
</body>
</html>
测试结果如下
总共发起了三次请求,那么需要在 server.js 文件中提供处理相应请求的方法,将之前那个函数中的内容修改如下:
let index = req.url.lastIndexOf('.');
let contentType = req.url.substr(index + 1);
switch (contentType) {
case '/' :
contentType = 'text/html';
break;
case 'js':
contentType = 'text/javascript';
break;
case 'css':
contentType = 'text/css';
break;
case 'ico':
contentType = 'image/x-icon';
break;
default:
contentType = '';
break;
}
if ( req.url === '/') {
req.url = "index.html";
}
let filePath = path.join(__dirname, '/public', req.url) ;
res.writeHead(200, {
'Content-type': contentType
});
let readStream = fs.createReadStream(filePath);
readStream.pipe(res);
其中第二行为解析 req.url 请求内容,也就是上图中输出字符串最后一个 ‘.’ 后的内容,用来在 ‘switch’ 中判断请求的文件类型
根据上图观察,请求的内容与一些字符串进行合理拼接后可以得到所要获取文件的完整路径,这里使用 path.join() 方法
小功告成
现在已经基本可以满足对文件的简单传输了,当然还有一些类型比如说图片啊,视屏啊也可以加入处理的 switch 函数中,这里你可以参考这个链接Simple node.js server that sends html+css as response