Перезапуск экспресс-сервера в esbuild

Я пытаюсь создать простой express сервер с esbuild. Это мой код

      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

Если бы вы запустили это приложение, я сначала буду работать, но когда вы измените код, сервер не будет обновляться, даже если вы обновите страницу.

Я не совсем уверен, где я делаю ошибку, Любая помощь, пожалуйста

3 ответа

Проблема в том, что 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];
    }
  }
};

Если вы не перезагрузите среду выполнения, глобальный объект и дочерний объект будут иметь одинаковую ошибку. Вы можете использовать при изменении кода, это так же быстро, как 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

Надеюсь, это может вам помочь :)

@es-exec/esbuild-plugin-serveили@es-exec/esbuild-plugin-startдва альтернативных плагина esbuild, которые вы можете попробовать. Они запускают ваши пакеты или любой сценарий командной строки для вас после сборки вашего проекта (поддерживает режим наблюдения для перестроения при изменении файла).

Документацию можно найти по следующему адресу:

Отказ от ответственности: я являюсь автором этих пакетов.

Другие вопросы по тегам