Задать вопрос
@alOstrovsqkii

Как собирать компоненты react?

Необходимо реализовать конструктор страниц. Сейчас компоненты собираются с помощью esbuild в esm модули. И в конструкторе страниц собранные component.js отображаются с помощью загрузки через import(component.js).

Но в этом есть проблемы. Во-первых в сборку надо помещать все библиотеки, что увеличивает бандл. Иначе при загрузке компонента выдаются ошибки по нахождению в брaузере react:
Ошибка загрузки компонента MyApp: TypeError: Failed to resolve module specifier "react". Relative references must start with either "/", "./", or "../".


Во-вторых происходит дубляж React и каждая зависимость использует номерной React.
67d9482a43573131018055.jpeg
Здесь React28.useMemo выдает ошибку
react-dom.development.js:26923 Uncaught TypeError: Cannot read properties of null (reading 'useMemo')
    at Object.useMemo4 (MyApp.js:1120:29)
    at Provider (MyApp.js:46709:32)

Код сборщика esbuild:
import fs from "fs";
import path from "path";
import esbuild from "esbuild";
import { fileURLToPath } from "url";
import aliasPlugin from "esbuild-plugin-alias";
import { svgrPlugin } from "esbuild-svgr-plugin";
import { sassPlugin, postcssModules } from "esbuild-sass-plugin";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const componentsDir = path.resolve(__dirname, "components");

const args = process.argv.slice(2);
const specificComponentDir = args[0];

const getEntryPoints = () => {
  if (specificComponentDir) {
    const entryPoint = path.join(specificComponentDir, "index.tsx");
    if (!fs.existsSync(entryPoint)) {
      console.error(`Указанный компонент не найден: ${specificComponentDir}`);
      process.exit(1);
    }
    return [entryPoint];
  } else {
    return fs
      .readdirSync(componentsDir)
      .filter((folder) =>
        fs.statSync(path.join(componentsDir, folder)).isDirectory(),
      )
      .map((folder) => path.join(componentsDir, folder, "index.tsx"));
  }
};

const entryPoints = getEntryPoints();

const customProcessingPlugin = {
  name: "custom-processing",
  setup(build) {
    build.onLoad(
      { filter: /\.(ts|tsx)$/ },
      async (args) => {
        let source = await fs.promises.readFile(args.path, "utf-8");

        // Добавляем React. перед хуками (useState, useEffect и т. д.)
        source = source.replace(
          /\b(useState|useEffect|useRef|useMemo|useCallback|useContext)\s*(<[^>]*>)?\s*\(/g,
          "React.$1$2(",
        );

        // Заменяем process.env.NEXT_PUBLIC_IS_PRODUCTION на false
        source = source.replace(/process\.env\.NEXT_PUBLIC_IS_PRODUCTION/g, "false");

        return { contents: source, loader: "tsx" };
      }
    );
  },
};

entryPoints.forEach((entryPoint) => {
  const componentName = path.basename(path.dirname(entryPoint));
  const outFile = path.resolve(__dirname, `dist`, `${componentName}.js`);

  esbuild
    .build({
      entryPoints: [entryPoint],
      outfile: outFile,
      format: "esm",
      bundle: true,
      loader: { ".tsx": "tsx", ".ts": "ts", ".jpg": "file", ".png": "file" },
      platform: "browser",
      sourcemap: false,
      minify: false,
      treeShaking: true,
      plugins: [
        aliasPlugin({
          "@lib": path.resolve(__dirname, "./ui-kit/lib"),
          "@ui-kit/types": path.resolve(
            __dirname,
            "./ui-kit/models/types/index.ts",
          ),
          "@icons": path.resolve(__dirname, "./ui-kit/assets/icons"),
          "@images": path.resolve(__dirname, "./ui-kit/assets/images"),
          "@ui-kit": path.resolve(__dirname, "./ui-kit"),
          "@components": path.resolve(__dirname, "./components"),
        }),
        svgrPlugin(),
        customProcessingPlugin,
        sassPlugin({
          filter: /\.module\.scss$/,
          transform: postcssModules({
            localsConvention: "camelCaseOnly",
          }),
          type: "style",
        }),
        sassPlugin({
          type: "style",
        }),
      ],
    })
    .then(() => {
      console.log("Сборка завершена");
    })
    .catch((error) => {
      console.error("Ошибка сборки:", error);
    });
});
  • Вопрос задан
  • 37 просмотров
Подписаться 1 Простой Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы