如何在本地通过Node.js提供静态文件服务?

19

我有以下文件位置:

file:///Users/MyName/Developer/sitename/scripts (contains all .js files..)
file:///Users/MyName/Developer/sitename/css (contains all .css files..)
file:///Users/MyName/Developer/sitename/images (contains all .jpg/png/etc. files..)
file:///Users/MyName/Developer/sitename/sitename.html
file:///Users/MyName/Developer/sitename/server.js

例如,在sitename.html中我加载所有必要的文件,如下所示:

<html>
  <head>
    <script src="scripts/somefile.js"></script>
  </head>
  ...
</html>

所以每当我打开 file:///Users/MyName/Developer/sitename/sitename.html,一切都正常。

但是,当我尝试通过我设置的本地 Node.js 服务器加载 file:///Users/MyName/Developer/sitename/sitename.html 时(服务器文件位置:file:///Users/MyName/Developer/sitename/server.js),就会出现问题:

var http = require("http"); 
var fs = require("fs");

fs.readFile('./sitename.html', function (err, html) 
{
    if (err) throw err; 

    http.createServer(function (request,response)
    {  
        // serve site
        if (request.url === "/")
        {
            response.writeHeader(200, {"Content-Type": "text/html"});  
            response.write(html);  
        }
        response.end(); 
    }).listen(8080); 
});

sitename.html 被找到并加载,但是所有应通过它加载的其他文件都未能加载,因为它们都被给予了前缀 http://localhost:8080/(例如,http://localhost:8080/scripts/somefile.js 不是有效的文件路径)。

看起来,一旦服务器创建(在 http.createServer(.....); 内),上下文就会发生变化,父目录现在变成了 http://localhost:8080/,而不是 file:///Users/MyName/Developer/sitename/,我想这是有道理的,但在仍然存储在本地的文件中使用时并不是很有帮助。

我该如何解决这个问题?而且,将 server.js (仅暂时)存储在同一个目录中是否使事情更加混乱?

谢谢!

3个回答

39

我发现在本地提供静态文件的最简单解决方案是使用Http-Server

它的用法非常简单。全局安装后,

 npm install http-server -g

前往您要提供服务的根目录

cd <dir>
http-server

就是这样!


这对我来说完美地解决了问题,我相信这正是楼主一直在寻找的解决方案!谢谢@hexinpeter。 - Abu Uzayr

11

你可以使用file:// URL来加载文件,因为这是您的Web浏览器的一个功能。

当加载地址http://localhost:8080时,您不再利用浏览器提供文件的能力(而是访问Node.js服务器)。被服务的HTML页面包含相对路径,它与当前主机名一起使用以加载资产。

有多种选项可用于提供资源。

您可以使用Node.js来提供文件:

或者,您可以使用Web服务器来为您提供文件。 这可能是性能最佳的选项。 此处提供了使用nginx提供静态内容的示例。


嘿,非常感谢您的回复。我会查看您建议的这两个选项。但是因为我是新手,您能否再详细解释一下:所以每当有人构建Web应用程序并使用Node.js来提供应用程序时,并且该应用程序具有大量静态文件(显然),这是否意味着他们在本地测试应用程序时总是需要使用像您建议的那样的“插件”?这似乎有点奇怪,Node没有默认选项来指定将提供所有静态文件的父文件夹位置。再次感谢您的帮助! - Kawd
1
Node提供了工具来服务这些文件,你只需要实现它。这就是为什么有那么多模块存在的原因,因为功能并不是直接内置的。你肯定可以使用Node.js来服务文件,但你需要在服务器中实现一个路由,识别对“/style.css”的请求,并从磁盘上读取该文件。 - Jeff Andersen
非常感谢Jeff的澄清。 - Kawd

5
问题在于,虽然您定义了一个静态资源的路径(sitename.html),但您没有定义其他所有静态资源的路径,例如(somefile.js)。假设以下文件结构,下面包含处理相对于公共目录(www)加载静态资源的服务器代码,而不使用外部模块。(部分取自此处
project/
    server/    
        server.js
        dispatcher.js
    www/
        index.html
        js/ (your javascript files)
        css/ (your css files)

server.js:

var http = require('http');
http.createServer(handleRequest).listen(8124, "127.0.0.1");
var dispatcher = require('./dispatcher.js');

function handleRequest(req, res) {
    try {
        console.log(req.url);
        dispatcher.dispatch(req, res);
    } catch(err) {
        console.log(err);
    }
}

dispatcher.js:

var fs = require('fs');
var path = require('path');

this.dispatch = function(request, response) {
    //set the base path so files are served relative to index.html
    var basePath = "../www";
    var filePath = basePath + request.url;

    var contentType = 'text/html';
    var extname = path.extname('filePath');
    //get right Content-Type
    switch (extname) {
        case '.js':
            contentType = 'text/javascript';
            break;
        case '.css':
            contentType = 'text/css';
            break;
    }

    //default to index.html
    if (filePath == basePath + "/") {
        filePath = filePath + "index.html";
    }

    //Write the file to response
    fs.readFile(filePath, function(error, content) {
        if (error) {
            response.writeHead(500);
            response.end();
        } else {
            response.writeHead(200, {'Content-Type': contentType});
            response.end(content, 'utf-8');
        }
    });

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接