Node.js 項目開發調試時前端項目時一般須要提供web服務器,才能實現一些頁面的功能調試。
由於若是經過file://
協議訪問html或js時,與相比 http://
協議安全方面差異較大,file://
訪問文件時沒法傳遞http協議頭之類的東西,因此搭建web服務器成爲了必須選項。css
不少ide自動提供了這樣的功能,如HBuilder. 本身搭建靜態的web服務器也很容易,live-server這個node.js開發的軟件就很好用。html
live-server安裝使用都很簡單:
安裝:前端
npm install -g live-server
使用:java
live-server --port=9090
能夠指定綁定的ip和端口號,也能夠指定證書來配置對 https 協議的支持。live-server 可以自動監控文件變更從而本身從新加載頁面,對前端開發來講很是方便。node
但也有一些狀況下須要進行一些客戶化設定,好比先後端分離項目,須要訪問後端接口時,須要進行跨域的配置,若是使用代理方式的話,就可更加靈活的方式,而沒必要修改後端代碼(由於這些修改經常是在正式發佈後是不須要的,由於生產環境可能由網關完成跨域配置,或是同域的根本不須要跨域配置)。web
這時本身能過簡單的js文件完成一個代理的 web 服務器便很方便。npm
搭建一個能夠訪問靜態文件的web服務器大致只須要如下的代碼:後端
"use strict"; const fs = require('fs'); const path = require('path'); const http = require('http'); const url = require('url'); const PORT = 3000; const args = process.argv let staticBasePath = '../dist'; if(args.length>2) staticBasePath = args[2]; const staticServe = function(req, res) { const resolvedBase = path.resolve(staticBasePath); const safeSuffix = path.normalize(req.url).replace(/^(\.\.[\/\\])+/, ''); const fileLoc = path.join(resolvedBase, safeSuffix); let pathname = url.parse(req.url).pathname; //根據url獲得文件路徑,讀取文件並返回給客戶端 fs.readFile(fileLoc, function(err, data) { if (err) { res.writeHead(404, 'Not Found'); res.write('404: File Not Found!'); return res.end(); } res.statusCode = 200; res.write(data); return res.end(); }); }; const httpServer = http.createServer(staticServe); httpServer.listen(PORT);
fs, http, path, url都是node.js自帶的模塊,在以上簡單的狀況下,不須要安裝額外的模塊便可實現對js,html,css,圖片的靜態文件的訪問。api
當須要同時訪問靜態文件和後端接口時,能夠增長對http-proxy的支持,只須要在上面代碼的基礎上增長少許代碼以下:跨域
"use strict"; const fs = require('fs'); const path = require('path'); const http = require('http'); const url = require('url'); const PORT = 3000; //npm install http-proxy --save-dev // 用來代理部分請求到java const httpProxy = require('http-proxy'); const proxy = httpProxy.createProxyServer({ //後端服務的接口地址 target: 'http://localhost:8080/', }); proxy.on('error', function(err, req, res){ res.writeHead(500, { 'content-type': 'text/plain' }); console.log(err); res.end('Something went wrong. And we are reporting a custom error message.'); }); const args = process.argv let staticBasePath = '../dist'; if(args.length>2) staticBasePath = args[2]; const staticServe = function(req, res) { const resolvedBase = path.resolve(staticBasePath); const safeSuffix = path.normalize(req.url).replace(/^(\.\.[\/\\])+/, ''); const fileLoc = path.join(resolvedBase, safeSuffix); let pathname = url.parse(req.url).pathname; //判斷若是是接口訪問,則經過proxy轉發 //這裏假設前端訪問後端接口是經過 /gaming/xxx 來實現路由區分 if(pathname.indexOf("gaming") > 0){ proxy.web(req, res); return; } fs.readFile(fileLoc, function(err, data) { if (err) { res.writeHead(404, 'Not Found'); res.write('404: File Not Found!'); return res.end(); } res.statusCode = 200; res.write(data); return res.end(); }); }; const httpServer = http.createServer(staticServe); httpServer.listen(PORT);
若是須要對特殊文件的支持,如 WebAssembly, 擴展名是.wasm,則須要在返回的Content-Type上作一下處理,即:
var mime = require('mime') fs.readFile(fileLoc, function(err, data) { if (err) { res.writeHead(404, 'Not Found'); res.write('404: File Not Found!'); return res.end(); } let extension = path.extname(fileLoc); let type = mime.getType(fileLoc); if(type) { res.setHeader('Content-Type',type); }else if(extension=='.wasm'){ res.setHeader('content-type', "application/wasm"); } res.statusCode = 200; res.write(data); return res.end(); });
這是由於前端加載 WebAssembly 裏,瀏覽器要求必須按application/wasm
返回 content-type.
參考連接: