You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Node.js无框架服务器单请求中静态文件重复加载问题求助

解决Node.js无框架服务器中静态文件重复加载/JS重复执行的问题

我仔细看了你这段无框架Node.js服务器的实现代码,问题的根源其实非常清晰——你每次调用Handle.get()的时候,都会给server对象绑定一个新的request事件监听器。比如你先后绑定了//profile/manage三个路由,那每次有请求进来时,这三个监听器都会被触发一遍,导致静态文件的处理逻辑被多次执行,自然就会出现前端JS重复加载执行的情况。

具体问题点拆解

  • SampleJs.get()方法内部,每次调用都会执行server.on("request", ...),这会不断给服务器添加新的事件处理器,而不是复用或替换已有处理器。
  • 每个处理器里的静态文件判断逻辑(比如.js.css匹配)都会在每个监听器里运行一次,同一个静态资源请求会被多次响应,前端就会重复接收并执行JS代码。

修复后的完整代码

服务端代码

var http = require("http"); 
var fs = require("fs"); 
var path = require("path"); 
var url = require("url"); 
var port = process.env.PORT || 3000; 
var staticFolders = require("./config"); 

// 只绑定一次request事件处理器
var server = http.createServer(function(request, response) {
    var getUrl = url.parse(request.url).pathname;
    var req = request;
    var res = response;

    // 封装render方法,统一处理HTML页面返回
    res.render = function(pathFile, file) {
        var htmlSource = path.join(__dirname, pathFile, file);
        fs.readFile(htmlSource, function(err, html) {
            if (err) {
                res.writeHead(404, {"content-type": "text/html"});
                res.write("<h1>404 Not Found</h1>");
                return res.end();
            }
            res.writeHead(200, {"content-type": "text/html"});
            res.write(html);
            res.end();
        });
    };

    // 路由匹配逻辑:先处理页面请求
    var routeMatched = false;
    if (getUrl === "/") {
        res.render("pages", "home.html");
        routeMatched = true;
    } else if (getUrl === "/profile") {
        res.render("pages", "profile.html");
        routeMatched = true;
    } else if (getUrl === "/manage") {
        res.render("pages", "manage.html");
        routeMatched = true;
    }

    // 如果不是页面路由请求,再处理静态资源
    if (!routeMatched) {
        handleStaticAssets(req, res);
    }
});

// 单独提取静态资源处理函数,避免重复逻辑
function handleStaticAssets(req, res) {
    var filePath = path.join(staticFolders.public, req.url);
    var contentType = getContentType(req.url);

    // 先检查文件是否存在,避免报错
    fs.access(filePath, fs.constants.F_OK, function(err) {
        if (err) {
            res.writeHead(404, {"content-type": "text/plain"});
            res.write("404: Resource not found");
            return res.end();
        }

        res.writeHead(200, {"content-type": contentType});
        var stream = fs.createReadStream(filePath);
        stream.pipe(res);
    });
}

// 辅助函数:根据文件后缀返回标准MIME类型
function getContentType(url) {
    if (url.match(/.css$/)) return "text/css";
    if (url.match(/.js$/)) return "application/javascript"; // 修正为标准MIME类型
    if (url.match(/.jpg$|.jpeg$/)) return "image/jpeg";
    if (url.match(/.png$/)) return "image/png";
    return "text/plain";
}

server.listen(port);
console.log(`Server running on port ${port}`);

配置文件(保持不变)

const path = require("path"); 
var staticFolders = { 
    htmlView: path.join(__dirname, "pages/"), 
    public: path.join(__dirname, "public") 
}; 
module.exports = staticFolders;

关键改动说明

  1. 只绑定一次request事件:避免多次添加监听器导致重复执行逻辑。
  2. 分离路由与静态资源处理:先匹配页面路由,匹配失败再处理静态资源,逻辑更清晰,避免冲突。
  3. 提取静态资源处理函数:把重复的文件类型判断、流处理逻辑抽成单独函数,代码更简洁易维护。
  4. 修正MIME类型:JS文件的标准MIME类型是application/javascript,之前的text/js是非标准类型,可能导致浏览器处理异常。
  5. 增加错误处理:添加了文件不存在的404响应,避免服务器因文件读取错误崩溃。

这样修改后,每个请求只会被处理一次,静态资源不会重复加载,前端JS也就不会出现重复执行的问题了。

内容的提问来源于stack exchange,提问作者tarek salem

火山引擎 最新活动