Node.js - 使用外部JS和CSS文件(仅使用Node.js而不是express)

21
我正在尝试学习Node.js,但遇到了一些困难。
我的问题是,我似乎无法将外部CSS和JS文件加载到HTML文件中。
GET http://localhost:8080/css/style.css 404 (Not Found) 
GET http://localhost:8080/js/script.css 404 (Not Found) 

(这是当所有文件都在应用程序的根目录中时)。
我被告知要模仿以下应用程序结构,添加一个路由来允许Web服务器为外部文件提供公共目录。
我的应用程序结构如下。
domain.com
  app/
    webserver.js

  public/
    chatclient.html

    js/
      script.js

    css/
      style.css

我的webserver.js脚本在应用程序的根目录中,我想要访问的所有内容都在“public”中。

我还看到了这个示例,它使用path.extname()来获取路径中的任何文件扩展名。(请参见最后一个代码块)。

因此,我尝试结合新的站点结构和这个path.extname()示例,使web服务器允许访问公共目录中的任何文件,以便我可以呈现引用外部js和css文件的html文件。

我的webserver.js如下所示。

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

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

  var myPath = url.parse(req.url).pathname;

    switch(myPath){

      case '/public':

        // get the extensions of the files inside this dir (.html, .js, .css)
        var extname = mypath.extname(path);

          switch (extname) {

            // get the html
            case '.html':
              fs.readFile(__dirname + '/public/chatclient.html', function (err, data) {
                if (err) return send404(res);
                res.writeHead(200, {'Content-Type': 'text/html'});
                res.write(data, 'utf8');
                res.end();
              });
            break;

            // get the script that /public/chatclient.html references
            case '.js':
              fs.readFile(__dirname + '/public/js/script.js', function (err, data) {
                if (err) return send404(res);
                res.writeHead(200, { 'Content-Type': 'text/javascript' });
                res.end(content, 'utf-8');
                res.end();
              });
            break;

            // get the styles that /public/chatclient.html references
            case '.css':
              fs.readFile(__dirname + '/public/css/style.css', function (err, data) {
                if (err) return send404(res);
                res.writeHead(200, { 'Content-Type': 'text/javascript' });
                res.end(content, 'utf-8');
                res.end();
              });
          }
          break;

          default: send404(res);
        }
    });

在公共案例中,我正在尝试通过以下方式获取此目录中的任何文件夹/文件: var extname = mypath.extname(path); 类似于我提供的链接。
但是,当我控制台记录它时,'extname'目前为空。
有人可以建议我需要添加或调整什么吗? 我知道在Express中可以轻松完成这个操作,但我想知道如何仅依靠Node来实现相同的事情。
我很感激您的帮助。
提前致谢。

尝试在调用send404()函数之前打印出err的值,以查看实际错误是什么。 - monsur
6个回答

32

你的代码存在几个问题:

  1. 由于没有指定监听端口,因此你的服务器无法运行。
  2. 正如Eric指出的那样,你的条件语句会失败,因为'url'中不存在'public'。
  3. 你在js和css响应中引用了一个不存在的变量'content',应该改为'data'。
  4. 你的css内容类型头应该是'text/css'而不是'text/javascript'。
  5. 在正文中指定'utf8'是不必要的。

我已经重新编写了你的代码。请注意,我没有使用case/switch。我更喜欢更简单的if和else,如果你喜欢可以将它们放回去。在我的重写中,url和path模块是不必要的,所以我已经将它们删除。

var http = require('http'),
    fs = require('fs');

http.createServer(function (req, res) {

    if(req.url.indexOf('.html') != -1){ //req.url has the pathname, check if it conatins '.html'

      fs.readFile(__dirname + '/public/chatclient.html', function (err, data) {
        if (err) console.log(err);
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.write(data);
        res.end();
      });

    }

    if(req.url.indexOf('.js') != -1){ //req.url has the pathname, check if it conatins '.js'

      fs.readFile(__dirname + '/public/js/script.js', function (err, data) {
        if (err) console.log(err);
        res.writeHead(200, {'Content-Type': 'text/javascript'});
        res.write(data);
        res.end();
      });

    }

    if(req.url.indexOf('.css') != -1){ //req.url has the pathname, check if it conatins '.css'

      fs.readFile(__dirname + '/public/css/style.css', function (err, data) {
        if (err) console.log(err);
        res.writeHead(200, {'Content-Type': 'text/css'});
        res.write(data);
        res.end();
      });

    }

}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

8

你可能想要考虑使用服务器框架,如express,它允许你设置一个“public”目录,自动路由静态文件。

var express = require('express'),app = express();
app.use(express.static(path.join(__dirname, 'public')));

这样一个框架的低廉开销确实值得花费精力来有效地"重新发明轮子"。

2
谢谢,但正如我在最后所说的那样,我想知道如何在没有Express的情况下使用Node.js完成这个。 - Denim Demon
1
它对我起作用,但我需要在我的情况下将“public”替换为“”。 - z0r0

2

public在客户端请求的URL中没有出现,因此myPath上的开关总是会跳过。


1
你可以考虑查看 Connect 提供的 Static 中间件。查看 Static 的源代码可能会给你一些想法,如何使用 node.js 代码实现这个功能(如果你想学习如何在不使用现有库的情况下完成它)。

0

自动更新文件,当文件改变时延迟1秒进行更新。 格式:app.js | index.htm | style.css

// packages
const http = require('http');
const fs = require('fs');
// server properties
const hostname = '127.0.0.1';
const port = 3000;
const timer = 300;

//should trigger atualize function every timer parameter
let htmlfile = '';
let cssfile = '';
let jsfile = '';

uptodate();

// should read file from the disk for html
function uptodate()
{
  console.log(1);
   fs.readFile('./index.html', function (err, html) {
    if (err) {
      throw err; 
    }       
    htmlfile = html;
  });
  // should read css from the disk for css
   fs.readFile('./style.css', function (err, html) {
    if (err) {
      throw err; 
    }       
    cssfile = html;
  });

  // should read js file from the disk
  fs.readFile('./app.js', function (err, html) {
    if (err) {
      throw err; 
    }       
    jsfile = html;
  });
  setTimeout(function(){ uptodate(); }, 1000);
}
const server = http.createServer((req, res) => {
  res.statusCode = 200;

  // should send css and js
  if(req.url.indexOf('.css') != -1){ //req.url has the pathname, check if it conatins '.js'
   res.writeHead(200, {'Content-Type': 'text/css'});
   res.write(cssfile);
   res.end();
   return;
  }
  if(req.url.indexOf('.js') != -1){ //req.url has the pathname, check if it conatins '.js'
   res.writeHead(200, {'Content-Type': 'text/javascript'});
   res.write(jsfile);
   res.end();
   return;
  }
  // should send html file via request
  res.writeHeader(200, {"Content-Type": "text/html"});  
  res.write(htmlfile);
  res.end();
});

// should send css and js 

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

0
    // get the extensions of the files inside this dir (.html, .js, .css)
    var extname = **mypath**.extname(path);

这些是反过来的。应该是:

   var extension = path.extname(mypath);

我尽可能避免将变量名用作函数名。


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