1

之前有用过一些别人写的,要嘛太冗杂,要么有错误,还是自己搞一搞靠谱。

需求背景

之前开发环境用的是xampp的Apache和php的环境,因为公司服务器的语言是PHP的,有时要写一些后台,但是下载的一些前端lib框架库文件没有放在htdocs目录下怕太乱。

有时要查看一些前端框架的源码和example,file:///显然是不行的,例如引入一个cdn的文件,或者页面有ajax,就需要一个简单的静态服务器可以访问这些文件。这个时候nodejs一个文件就可以搞定一个简单的服务器就显得十分合适。

系统环境:windows

基本思路:

  1. http模块创建服务器

  2. url,path模块解析url确定文件路径

  3. 判断请求的文件类型,返回不同的MIME类型(MIME类型不正确浏览器是不能正常解析的)

  4. 返回对应的资源

  5. 移动端真机测试访问的处理

创建服务器

var 
http = require('http'),
url  = require('url'),
path = require('path'),
fs   = require('fs'),
os   = require('os');

var server = http.createServer(function (req,res){
    res.writeHead(200,{'Content-Type':'text/plain'});
    res.write('hello');
    res.end();
})

server.listen('8080',function (){
    console.log('server start');
})

服务器创建好了,可以访问后,就要根据请求的url确定请求的文件路径了。

处理请求文件路径--简单的路由

请求成功回调函数如下


    var filename = __dirname+url.parse(req.url).pathname;
    
    var resContentType = 'text/html';//返回资源的MIME类型
    
    fs.exists(filename,function (exists){
        if (!exists){
            //文件不存在返回404
            res.writeHead(404,{'Content-Type':'text/plain'});
            res.write('404 Not Found');
            res.end();
        }else {
            //文件存在读取并返回
            fs.readFile(filename,function (err,data){
                if (err){
                    res.writeHead(500,{'Content-Type':'text/plain'});
                    res.end(err);
                }else{
                    res.writeHead(200,{'Content-Type':resContentType});
                    res.write(data);
                    res.end();
                }
            })
        }
    })

这里我们先所有请求都返回html类型,这显然是不行的,像css文件,js文件的MIME不是'text/html',所以要处理不同请求文件的MIME类型,这里我们加一个映射表。

注意:__dirname一定要加上,单纯的url.parse(req.url).pathname的路径,fs.exists是找不到的,永远返回404。还有有的文章还有用path.exists...坑的好惨啊,path模块根本没有exists方法,要用fs模块的。

处理不同文件类型的MIME

var mime = {
    "html": "text/html",
    "htm": "text/html",
    "css": "text/css",
    "js": "text/javascript",
    "xml": "text/xml",
    "json": "application/json",

    "jpg": "image/jpeg",
    "jpeg": "image/jpeg",
    "png": "image/png",
    "gif": "image/gif",
    "bmp": "image/bmp",
    "svg": "image/svg+xml",
    "ico": "image/x-icon",

    "mp3": "audio/mpeg",
    "wav": "audio/x-wav",
    "mp4": "video/mp4",
    "swf": "application/x-shockwave-flash",

    "woff": "application/x-font-woff"

}

这个表不一定全根据自己的需求添加即可。

回调函数里的部分就变成

    var filename = __dirname+url.parse(req.url).pathname;
    var extname = path.extname(filename);

    //扩展名含点号如'.html',截掉
    extname = extname ? extname.slice(1) : 'unknown';
    //映射表中查找请求的资源的MIME类型并返回,没有映射均返回'text/plain'类型
    var resContentType = mime[extname] || 'text/plain';

移动端要可以访问

其实这个与nodejs代码并没有必然的联系,移动端访问本机的两个条件(服务器没有请求限制的情况下,如apache需要修改一些配置文件):

  • 把你的localhost改成192.168.0.xxx

  • 手机的网络要与电脑在同一网段(如用的同一个WIFI)

当然也可以手动到cmd中ipconfig一下看看本机的ip地址,这里我额外加了os模块用于获取本机系统的ip,图个方便,当然这个不是静态服务器必须的要素。

最后的server.js的全部代码也就很小的一段,就可以当静态服务器了。复制一份扔在一些需要查看的文件夹的根目录就可以充当小型服务器进行example浏览和测试了。
注:这个小文件没有做缓存等一些其他逻辑的处理(测试时也有好处,要不修改后有些还要手动清浏览器缓存),也没有做访问目录权限的处理,仅供本地测试时使用。

最后附上完整代码:

var 
http = require('http'),
url  = require('url'),
path = require('path'),
fs   = require('fs'),
os   = require('os');

function getIPv4(){
    var interfaces = os.networkInterfaces();//获取网络接口列表
    var ipv4s = [];//同一接口可能有不止一个IP4v地址,所以用数组存

    Object.keys(interfaces).forEach(function (key){
        interfaces[key].forEach(function (item){

            //跳过IPv6 和 '127.0.0.1'
            if ( 'IPv4' !== item.family || item.internal !== false )return;

            ipv4s.push(item.address);//可用的ipv4s加入数组
            console.log(key+'--'+item.address);
        })        
    })

    return ipv4s[0];//返回一个可用的即可
}
var mime = {
    "html": "text/html",
    "htm": "text/html",
    "css": "text/css",
    "js": "text/javascript",
    "xml": "text/xml",
    "json": "application/json",

    "jpg": "image/jpeg",
    "jpeg": "image/jpeg",
    "png": "image/png",
    "gif": "image/gif",
    "bmp": "image/bmp",
    "svg": "image/svg+xml",
    "ico": "image/x-icon",

    "mp3": "audio/mpeg",
    "wav": "audio/x-wav",
    "mp4": "video/mp4",
    "swf": "application/x-shockwave-flash",

    "woff": "application/x-font-woff"

}
var server = http.createServer(function (req,res){

    var filename = __dirname+url.parse(req.url).pathname;
    var extname = path.extname(filename);

    //扩展名含点号如'.html',截掉
    extname = extname ? extname.slice(1) : 'unknown';
    //映射表中查找请求的资源的MIME类型并返回,没有映射均返回'text/plain'类型
    var resContentType = mime[extname] || 'text/plain';

    fs.exists(filename,function (exists){
        if (!exists){
            //文件不存在返回404
            res.writeHead(404,{'Content-Type':'text/plain'});
            res.write('404 Not Found');
            res.end();
        }else {
            //文件存在读取并返回
            fs.readFile(filename,function (err,data){
                if (err){
                    res.writeHead(500,{'Content-Type':'text/plain'});
                    res.end(err);
                }else{
                    res.writeHead(200,{'Content-Type':resContentType});
                    res.write(data);
                    res.end();
                }
            })
        }
    })

});

server.listen('8080',function (){
    console.log('server start on: '+getIPv4()+':8080');
})

eric_bin
859 声望42 粉丝

web前端开发一枚...