手寫簡版無三方依賴Node Server

預告:今天寫的可能用處不大,各位看官謹慎選擇要不要看下去...

😶又是顯得D疼造輪子系列之手寫無三方依賴的輕量級Node-server,哇,好多的形容詞,且看需求。html

產品說要看一下頁面寫的怎麼樣了可是他又不想動或者你不想看到他,我以爲多半是由於後者🙄,那麼問題來了,憑咱本身能不能把產品拒在10米以外又讓他把頁面瞅一眼,那必須是能夠的,廢話少說,直接開寫。node

Node知識點

  • fs
  • http
  • os

從開啓一個基本的Node服務開始, http模塊參考文檔

http.createServer(function (request, response) {
    // 發送 HTTP 頭部 
    // HTTP 狀態值: 200 : OK
    // 內容類型: text/plain
    response.writeHead(200, {'Content-Type': 'text/plain'});
    // 發送響應數據 "Hello World"
    response.end('Hello World\n');
}).listen(8888);
// 這就開啓了一個最基礎的node服務,瀏覽器訪問 http://127.0.0.1:8888 便可看到Hello World
複製代碼

那麼萬里長征第一步的踮腳動做算是完成了,接下來就是實現怎麼打開咱們本身的html頁面。 想要打開html頁面確定就要訪問文件,因而就得用到fs模塊,如下代碼能夠實現深層遍歷腳本同目錄下的html文件。git

遍歷頁面須要的文件, fs模塊參考文檔

function geFileList(path) {
    var filesList = [];
    readFile(path, filesList);
    return filesList;
}

//獲取文件類型
function getType(filename){
    var index=filename.lastIndexOf(".");
    if(index!=-1){
    	var type=filename.substring(index+1,filename.length);
	    return type;
    }
}
//遍歷讀取文件 
function readFile(path, filesList) {
    files = fs.readdirSync(path);//須要用到同步讀取 
    files.forEach(walk);
    function walk(file) {
        states = fs.statSync(path + '/' + file);
        if (states.isDirectory()) {
            readFile(path + '/' + file, filesList);
        }
        else {
            var obj = new Object();
            obj.size = states.size;
            obj.name = file;//文件名 
            obj.type = getType(file)
            filesList.push(obj);
        }
    }
}
// 統計各種文件數量
function countFileByType(obj){
	var keyContainer = {}; 
	obj.forEach(item => {
	  keyContainer[item.type] = keyContainer[item.type] || [];
	  keyContainer[item.type].push(item);
	});
	return keyContainer
}

module.exports.geFileList = geFileList

module.exports.countFile = countFileByType

module.exports.getType = getType

//方法模塊化,把文件讀取操做剝離比較容易整理思路,emmmmmmm,可是寫的不是很優雅,有待改進
複製代碼

Node服務能夠開啓了,文件能夠遍歷了,至此基礎建設算是搞起來了,接下來就須要開一個不用看見產品的服務了。github

開啓局域網服務

咱們再次把獲取ip地址的方法剝離,須要用到的Node知識點是os模塊, os模塊參考文檔npm

const os = require('os');
const getlocalIp = () => {
	var interfaces = os.networkInterfaces();
	var ipArr = []
    for (var devName in interfaces) {
        var iface = interfaces[devName];
        for (var i = 0; i < iface.length; i++) {
            var alias = iface[i];
            if (alias.family == 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
                ipArr.push(alias.address)
            }
        }
    }
    return ipArr
}


const getWlanIp = () => {
    var interfaces = os.networkInterfaces().WLAN
    var WlanIp = ''
    for(let ip of interfaces){
        if(ip.family=='IPv4'){
            WlanIp = ip.address
        }
    }
    return WlanIp
}

module.exports.getlocalIp = getlocalIp

module.exports.getWlanIp = getWlanIp 
// 爲何這裏要留兩種ip地址呢,由於有時候咱們也須要開啓一個非局域網ip的服務啦,多功能加成
複製代碼

寫到這裏忽然想到一個問題,我作這個功能的另一個很重要的目的是解決http-server默認開啓8080端口的缺陷,由於8080端口很大可能會被佔用,因而想到開啓服務時不妨隨機分配一個8###端口,這樣就極少可能存在端口被佔用的狀況了,一個隨機數就能實現😁api

捋一下功能實現的步驟

  • 讀取某目錄下的html文件
  • 獲取局域網Ip地址/本地Ip地址
  • 分配隨機端口
  • 自動打開瀏覽器,生成index文件連接

整合後核心步驟

模塊引入

const http = require('http');
const fs = require('fs');
const Ip = require('../lib/get-ip')
const F = require('../lib/get-file')
const root = process.cwd();  //當前目錄
const port = Math.floor(Math.random () * 1000) + 8000;
var localIP = Ip.getlocalIp()
var wlanIp = Ip.getWlanIp() || localIP[0]
複製代碼

主方法

function setHttpServer() {
	await setConsoleInfo();
	await fs.exists('index.html',function(exists){
	if(!exists){
			openDefaultBrowser(`http://`+wlanIp+':'+port)
	  	}else{
			openDefaultBrowser(`http://`+wlanIp+':'+port+'/index.html')
	  	}
	})
}
複製代碼

開啓服務並排錯

server=http.createServer(function(req,res){
    if(req.url === '/favicon.ico') {
        // console.log('\033[42;30m DONE \033[40;32m Compiled successfully in 19987ms\033[0m')
    }else{
        var url=req.url;
        var file = root+url;
        fs.readFile(file,function(err,data){
            if(err){
                res.writeHeader(404,{
                    'content-type' : 'text/html;charset="utf-8"'
                });
                if(!F.countFile(F.geFileList(root)).html){
                    res.write('<h1>404頁面</h1><p><h2>當前目錄沒有html文件</h2>')
                }else{
                    let fileList =  fs.readdirSync(`${file}`);
                    for(let f of fileList){
                        let type = F.getType(f)
                        if(type=='html'){
                            res.write('<br/>'+`<a href="${f}">${f}</a>`+'\n')
                        }
                    }
                }
                res.end();
            }else{
                var surl = '.'+url;
                var type = surl.substr(surl.lastIndexOf(".")+1,surl.length)
                res.writeHeader(200,{
                    'content-type' : "text/"+type+';'+'charset="utf-8"'
                });
                res.write(data);
                res.end();
            }
        })  
    } 
}).listen(port);
複製代碼

控制檯顯示一下服務地址

function setConsoleInfo(){
  let info = 'The default service has been opened in the browser!'
	console.log('\033[42;30m DONE \033[;32m' + info + '\033[0m')
	for(let dev of localIP){
		console.log(`${dev}`+':'+port)
	}

}
複製代碼

自動打開瀏覽器

function openDefaultBrowser(url) {
  var exec = require('child_process').exec;
  switch (process.platform) {
    case "darwin":
      exec('open ' + url);
      break;
    case "win32":
      exec('start ' + url);
      break;
    default:
      exec('xdg-open', [url]);
  }
}
複製代碼

至此一個簡單的無三方依賴的輕量級的Node服務就創建起來了,過程略顯粗暴,沒有詳細的解釋模塊方法的使用方式,由於所用的的方法都比較簡單。瀏覽器

固然這個小插件還有必定的缺陷,擴展性略低,只能知足簡單的需求,還有很大的改進空間,但願走過路過的不吝給予更好的建議。😳[來自青銅選手的真誠臉]markdown

歡迎使用npm進行安裝試用dom

npm i set-node-server
set-server / ss模塊化

git交流地址:vannvan/set-node-server

相關文章
相關標籤/搜索