网友 bottle_ 提供搭建一个简单本地服务器的思路为下:
- 我们需要一个 HTTP 服务器
- 对于不同的请求,根据请求的 URL,我们的服务器需要给予不同的响应,因此我们需要一个路由,用于把请求对应到请求处理程序(request handler)
- 当请求被服务器接收并通过路由传递之后,需要可以对其进行处理,因此我们需要最终的请求处理程序
- 我们需要从 HTML 文件里提取数据以及展示服务器传入的数据,因此需要将 HTML 和服务器结合起来
首先需要两个文件 index.js 和 index.html。
-
index.js
引用模块
1const fs = require('fs'); // 系统文件及目录进行读写操作2const http = require('http'); // 封装了高效的 HTTP 服务器和 HTTP 客户端3const url = require('url'); // URL 处理路由
1/**2* 路由3* @param {Function} handle 请求处理程序4* @param {String} pathname 路径5* @param {Object} response 响应数据6* @param {Object} postData 请求参数7*/8function route(handle, pathname, response, postData) {9if (typeof handle[pathname] === 'function') {10handle[pathname](response, postData);11} else {12response.writeHead(404, { 'Content-Type': 'text/plain' });13response.write('404 Not Found');14response.end();15}1 collapsed line16}服务器
1/**2* 服务器3* @param {Function} route 路由4* @param {Function} handle 请求处理程序5*/6function start(route, handle) {7function onRequest(request, response) {8const pathname = url.parse(request.url).pathname;9let postData = '';10switch (request.method) {11case 'GET':12postData += url.parse(request.url).query;13request.setEncoding('utf8');14route(handle, pathname, response, postData);15break;14 collapsed lines16case 'POST':17request.addListener('data', function (postDateChunk) {18postData += postDateChunk;19});20request.addListener('end', function () {21route(handle, pathname, response, postData);22});23break;24};25}2627http.createServer(onRequest).listen(8080);28console.log('Server has started');29}请求处理程序
1// 请求处理程序2const handle = {3// index 接口4'/public/index.html': function (response, postData) {5const pathname = __dirname + '/public/index.html';6fs.readFile(pathname, function (err, data) {7response.end(data);8});9},10// download 接口11'/download': function (response, postData) {12response.writeHead(200, { 'Content-Type': 'text/html' });13response.write(JSON.stringify({14code: 200,15data: {12 collapsed lines16'time': new Date().toLocaleString("en-US")17}18}));19response.end();20},21// upload 接口22'/upload': function (response, postData) {23response.writeHead(200, { 'Content-Type': 'text/html' });24response.write('You have sent: ' + JSON.parse(postData).value);25response.end();26}27};启动服务器
1// 启动服务器 = 路由处理 + 接口处理2start(route, handle); -
index.html
1<!DOCTYPE html>2<html lang="en">34<head>5<meta charset="UTF-8">6<meta name="viewport" content="width=device-width, initial-scale=1.0">7<meta http-equiv="X-UA-Compatible" content="ie=edge">8<title>Document</title>9</head>1011<body>12<input type="text" name="input">13<button value="submit" name="submit">submit</button>14<p></p>15<!-- submit demo -->33 collapsed lines16<script>17const btn = document.querySelector('button');18btn.addEventListener('click', function () {19const value = document.querySelector('input').value;20ajax(value);21}, true);2223function ajax(value) {24const xmlhttp;25if (window.XMLHttpRequest) {26xmlhttp = new XMLHttpRequest();27} else {28xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');29}3031xmlhttp.onreadystatechange = function () {32if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {33document.querySelector('p').innerHTML = xmlhttp.responseText;34}35}3637xmlhttp.open('POST', '/upload', true);38xmlhttp.send(JSON.stringify({39value: value40}));4142// xmlhttp.open('GET', '/upload?value='+value, true);43// xmlhttp.send();44}45</script>46</body>4748</html>
注意事项:
-
关于 GET 和 POST 方式的请求参数
GET 的请求参数是以查询参数形式放在 URL 后面的,服务器可以从 URL 上获取参数:
url.parse(request.url).query
。POST 的请求参数则需要作为
xhr.send()
的参数并转换为字符串来传递,本文使用JSON.stringify()
来转换,再在服务器端用JSON.parse()
转换。服务器端在响应两种请求方式时,响应数据格式参考官方文档。
-
关于服务器响应头中的 Content-Type
一般网站的做法是:当返回 HTML 页面时为 text/html,当使用 JSONP 时为 text/javascript,当使用 CORS 时为 application/json。
-
关于跨域
如果希望某个接口可以跨域,需要设置响应头的
Access-Control-Allow-Origin
为*
,比如允许 download 接口跨域,代码修改如下:Terminal window 1response.writeHead(200, { 'Content-Type': 'text/html', 'Access-Control-Allow-Origin': '*' });调试的话,只要启动两个不同端口的 index.js 即可,代码仓库里 server.1.js 和 server.2.js 就表示两个不同的 index.js。
-
关于 Node.js 热部署
Node.js 启动服务器时是将脚本放入内存,以后都会直接访问内存,避免重复载入。这种设计虽然有利于提高性能,却不利于开发调试,导致修改 Node.js 代码后需要手动终止进程并重启才会生效。
网友 会奔跑的胖子 提出方案:
你只需要在修改文件后保存,它就能自动替你发布,这就是所谓的热部署。
supervisor 就是一个 Node.js 的开源热部署工具:
Terminal window 1npm i supervisor -g2supervisor server.js该网友中还提到另一个开源热部署工具 hotcode,但经测试 hotcode 若使用 express 4.x 则会报错,因为 hotcode 使用的 express.createServer() 已经被废弃。
参考:
学习笔记:用Nodejs搭建一个简单的本地服务器
NodeJS”热部署“代码,实现动态调试(hotnode,可以实现热更新)