You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用http模块创建Node.js服务器时,如何加载外部CSS/JS/图片?

原生Node.js HTTP服务器加载静态资源404问题解决

问题场景

使用原生http模块结合if语句处理路由时,浏览器加载外部CSS文件返回404错误,但改用Express路由则能正常加载。错误代码如下:

const http = require('http');
const url = require('url');
const fs = require('fs');
const path = require('path');
const express = require('express');
const app = express();

const home = fs.readFileSync(`${__dirname}/pages/home.html`, 'utf-8');
const style = app.use(express.static(path.join(__dirname, '/public')));

const server = http.createServer((req, res) => {
  const pathName = req.url;

  if (pathName === '/' || pathName === '/home') {
    res.writeHead(200, {
      'Content-type': 'text/html',
    });
    res.end(home);
  } else {
    res.writeHead(404, {
      'Content-type': 'text/html',
    });
    res.end("<h1>Who's there ? </h1>");
  }
});

server.listen(3333, '127.0.0.1', () => {
  console.log('are you working on 3333?');
});

正常加载的Express参考代码:

const fs = require('fs');
const url = require('url');
const express = require('express');
const path = require('path');

const app = express();

app.use(express.static(__dirname + '/public'));

const termen = path.join(__dirname + '/pages/home.html');

app.get('/', function (req, res) {
  res.sendFile(termen);
});

app.listen(3333);

console.log('hai');

问题原因

你在原生http服务器中引入了Express的express.static,但该中间件只适用于Express的请求处理流程,原生http服务器并不会识别它。同时,当前的路由逻辑将所有非/、/home的请求直接返回404,包括CSS等静态资源的请求。

修改方案

直接在原生http的请求处理逻辑中添加静态资源处理分支,读取对应文件并返回:

const http = require('http');
const url = require('url');
const fs = require('fs');
const path = require('path');

const home = fs.readFileSync(`${__dirname}/pages/home.html`, 'utf-8');
const publicDir = path.join(__dirname, 'public');

// 定义常见资源的Content-Type映射,确保浏览器正确解析资源
const mimeTypes = {
  '.html': 'text/html',
  '.css': 'text/css',
  '.js': 'text/javascript',
  '.png': 'image/png',
  '.jpg': 'image/jpeg',
  '.gif': 'image/gif'
};

const server = http.createServer((req, res) => {
  const pathName = req.url;

  if (pathName === '/' || pathName === '/home') {
    res.writeHead(200, {
      'Content-type': 'text/html',
    });
    res.end(home);
  } else {
    // 处理静态资源请求
    const filePath = path.join(publicDir, pathName);
    const ext = path.extname(filePath);

    // 检查文件是否存在
    fs.access(filePath, fs.constants.F_OK, (err) => {
      if (err) {
        // 文件不存在返回404
        res.writeHead(404, { 'Content-type': 'text/html' });
        res.end("<h1>Who's there ? </h1>");
        return;
      }

      // 根据文件后缀设置正确的Content-Type
      const contentType = mimeTypes[ext] || 'application/octet-stream';
      res.writeHead(200, { 'Content-type': contentType });
      
      // 流式读取文件并返回,比同步读取更高效
      fs.createReadStream(filePath).pipe(res);
    });
  }
});

server.listen(3333, '127.0.0.1', () => {
  console.log('are you working on 3333?');
});

关键改动说明

  • 移除无用的Express依赖,纯原生实现静态资源处理
  • 添加mimeTypes对象,根据文件后缀设置对应Content-Type,避免浏览器无法识别资源类型
  • 对非首页请求,优先检查是否为public目录下的有效文件,存在则返回文件内容,不存在才返回404
  • 使用fs.createReadStream流式读取文件,相比同步读取更适合处理大文件,性能更优

内容的提问来源于stack exchange,提问作者Corneliu Grozavu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 06:34:54