【问题标题】:Restarting express server in esbuild在 esbuild 中重新启动 express 服务器
【发布时间】:2021-05-08 10:40:01
【问题描述】:

我正在尝试使用esbuild 创建一个简单的express 服务器。这些是我的代码

import express from "express";

const app = express();
const port = 3000;

const stopServer = {
  stop: () => {},
};

export const createServer = async () => {
  app.get("/", async (req, res) => {
    res.json({
      first: "Hello",
    });
  });

  const server = app.listen(port, () => {
    console.log(`Listening on port: ${port}`);
  });

  stopServer.stop = () => {
    server.close();
  };
};

export const stop = () => {
  stopServer.stop();
  stopServer.stop = () => {};
};

esbuild.config.js

const esbuild = require("esbuild");
const path = require("path");

const restartPlugin = () => {
  return {
    name: "restart-express",
    setup(build) {
      build.onEnd(async (res) => {
        const { stop, createServer } = await import("../dist/server.js");
        stop();
        createServer();
      });
    },
  };
};

const run = async () => {
  await esbuild.build({
    entryPoints: [path.resolve(__dirname, "../src/server.ts")],
    outdir: path.resolve(__dirname, "../dist"),
    platform: "node",
    sourcemap: true,
    format: "cjs",
    watch: {
      onRebuild: async (err, res) => {
        if (err) {
          console.error(err);
        } else {
          console.log("There is some change");
        }
      },
    },
    plugins: [restartPlugin()],
  });
};

run();

插件参考:https://github.com/evanw/esbuild/issues/1258#issuecomment-834676530

如果您要运行此应用程序,我最初会工作,但是当您更改代码时,即使您刷新页面,服务器也不会更新。

我不确定我在哪里犯错,请帮助

【问题讨论】:

    标签: express esbuild


    【解决方案1】:

    问题是node 缓存了import("..dist/server.js"),因此它永远不会返回新模块。为了解决这个问题,我们将编写一个函数

    const purgeAppRequireCache = (buildPath) => {
      for (let key in require.cache) {
        if (key.startsWith(buildPath)) {
          delete require.cache[key];
        }
      }
    };
    

    这将从节点中删除缓存。我们也可以通过这种方式使用这个功能。这解决了我的问题

    const esbuild = require("esbuild");
    const path = require("path");
    
    const startPlugin = () => {
      return {
        name: "startPlugin",
        setup(build) {
          build.onEnd((res) => {
            const serverPath = path.resolve(__dirname, "../dist/server.js");
            const { stop } = require("../dist/server.js");
            stop();
            purgeAppRequireCache(serverPath);
            purgeAppRequireCache(path.resolve(__dirname, "../src"));
            const { listen } = require("../dist/server");
            listen();
          });
        },
      };
    };
    
    const run = async () => {
      await esbuild.build({
        entryPoints: [path.resolve(__dirname, "../src/server.tsx")],
        outdir: path.resolve(__dirname, "../dist"),
        platform: "node",
        sourcemap: true,
        format: "cjs",
        watch: true,
        bundle: true,
        plugins: [startPlugin()],
      });
    };
    
    run();
    
    const purgeAppRequireCache = (buildPath) => {
      for (let key in require.cache) {
        if (key.startsWith(buildPath)) {
          delete require.cache[key];
        }
      }
    };
    

    【讨论】:

      【解决方案2】:

      如果你不重新加载运行时,全局的对象和子require(xxx) 可能有相同的错误。 修改代码时可以使用kill and fork cluster,和require(xxx)一样快,有示例代码:https://github.com/ymzuiku/bike/blob/master/lib/index.js

      如果您需要查看kill and fork cluster 示例,这里有一个相同的功能包,也使用esbuild,但它使用fs.watch:https://www.npmjs.com/package/bike

      希望能帮到你:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-21
        • 2019-08-23
        • 2014-06-09
        • 2019-03-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多