原文: https://zhictory.github.io/bl...
網友 bottle_ 提供搭建一個簡單本地服務器的思路爲下:javascript
- 咱們須要一個 HTTP 服務器
- 對於不一樣的請求,根據請求的 URL,咱們的服務器須要給予不一樣的響應,所以咱們須要一個路由,用於把請求對應到請求處理程序(request handler)
- 當請求被服務器接收並經過路由傳遞以後,須要能夠對其進行處理,所以咱們須要最終的請求處理程序
- 咱們須要從 HTML 文件裏提取數據以及展現服務器傳入的數據,所以須要將 HTML 和服務器結合起來
index.jshtml
引用模塊java
const fs = require('fs'); // 系統文件及目錄進行讀寫操做 const http = require('http'); // 封裝了高效的 HTTP 服務器和 HTTP 客戶端 const url = require('url'); // URL 處理
路由node
/** * 路由 * @param {Function} handle 請求處理程序 * @param {String} pathname 路徑 * @param {Object} response 響應數據 * @param {Object} postData 請求參數 */ function route(handle, pathname, response, postData) { if (typeof handle[pathname] === 'function') { handle[pathname](response, postData); } else { response.writeHead(404, { 'Content-Type': 'text/plain' }); response.write('404 Not Found'); response.end(); } }
服務器git
/** * 服務器 * @param {Function} route 路由 * @param {Function} handle 請求處理程序 */ function start(route, handle) { function onRequest(request, response) { const pathname = url.parse(request.url).pathname; let postData = ''; switch (request.method) { case 'GET': postData += url.parse(request.url).query; request.setEncoding('utf8'); route(handle, pathname, response, postData); break; case 'POST': request.addListener('data', function (postDateChunk) { postData += postDateChunk; }); request.addListener('end', function () { route(handle, pathname, response, postData); }); break; }; } http.createServer(onRequest).listen(8080); console.log('Server has started'); }
請求處理程序github
// 請求處理程序 const handle = { // index 接口 '/public/index.html': function (response, postData) { const pathname = __dirname + '/public/index.html'; fs.readFile(pathname, function (err, data) { response.end(data); }); }, // download 接口 '/download': function (response, postData) { response.writeHead(200, { 'Content-Type': 'text/html' }); response.write(JSON.stringify({ code: 200, data: { 'time': new Date().toLocaleString("en-US") } })); response.end(); }, // upload 接口 '/upload': function (response, postData) { response.writeHead(200, { 'Content-Type': 'text/html' }); response.write('You have sent: ' + JSON.parse(postData).value); response.end(); } };
啓動服務器ajax
// 啓動服務器 = 路由處理 + 接口處理 start(route, handle);
index.htmlexpress
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <input type="text" name="input"> <button value="submit" name="submit">submit</button> <p></p> <!-- submit demo --> <script> const btn = document.querySelector('button'); btn.addEventListener('click', function () { const value = document.querySelector('input').value; ajax(value); }, true); function ajax(value) { const xmlhttp; if (window.XMLHttpRequest) { xmlhttp = new XMLHttpRequest(); } else { xmlhttp = new ActiveXObject('Microsoft.XMLHTTP'); } xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState === 4 && xmlhttp.status === 200) { document.querySelector('p').innerHTML = xmlhttp.responseText; } } xmlhttp.open('POST', '/upload', true); xmlhttp.send(JSON.stringify({ value: value })); // xmlhttp.open('GET', '/upload?value='+value, true); // xmlhttp.send(); } </script> </body> </html>
關於 GET 和 POST 方式的請求參數npm
GET 的請求參數是以查詢參數形式放在 URL 後面的,服務器能夠從 URL 上獲取參數:url.parse(request.url).query
。json
POST 的請求參數則須要做爲 xhr.send()
的參數並轉換爲字符串來傳遞,本文使用 JSON.stringify()
來轉換,再在服務器端用 JSON.parse()
轉換。
服務器端在響應兩種請求方式時,響應數據格式參考官方文檔。
關於服務器響應頭中的 Content-Type
通常網站的作法是:當返回 HTML 頁面時爲 text/html,當使用 JSONP 時爲 text/javascript,當使用 CORS 時爲 application/json。
關於 Node.js 熱部署
Node.js 啓動服務器時是將腳本放入內存,之後都會直接訪問內存,避免重複載入。這種設計雖然有利於提升性能,卻不利於開發調試,致使修改 Node.js 代碼後須要手動終止進程並重啓纔會生效。
網友 會奔跑的胖子 提出方案:
你只須要在修改文件後保存,它就能自動替你發佈,這就是所謂的熱部署。
supervisor 就是一個 Node.js 的開源熱部署工具:
npm i supervisor -g supervisor server.js
該網友還提到另外一個開源熱部署工具 hotcode,但經測試 hotcode 若使用 express 4.x 則會報錯,由於 hotcode 使用的 express.createServer() 已經被廢棄。
參考:
學習筆記:用Nodejs搭建一個簡單的本地服務器
NodeJS」熱部署「代碼,實現動態調試(hotnode,能夠實現熱更新)