Package.json экспортируется с помощью webpack 5 — динамически импортируемый модуль не найден

#node.js #json #webpack #webpack-5

#node.js #json #webpack #webpack-5

Вопрос:

У меня возникли небольшие проблемы с согласованием пути динамического импорта для локалей i18n. Вот соответствующий код —

 function getLoader(
  lang: SupportedLanguage,
  ns: SupportedNamespace
): NamespaceLoader | undefined {
  const matrixToCheck = UNSUPPORTED_MATRIX[ns];
  const isSupported = matrixToCheck amp;amp; matrixToCheck.indexOf(lang) === -1;
  if (isSupported) {
    const path = `./locales/${lang}/${ns}.json`;
    const name = `${lang}_${ns}`;
    const named = {
      [name]: () => import(`${path}`),
    };
    return named[name];
  }
}
...
// eventual output
const SUPPORTED_LANGUAGES = {en: {namespace1: () => import('./locales/en/namespace1.json')}
 

Моя цель — управлять всеми соответствующими переводами в одном пакете npm, обрабатывать все настройки динамического импорта во время сборки, а затем потребители могут вызывать средство получения ( getTranslation в данном случае) в своих соответствующих приложениях для языка и пространства имен по своему выбору, чтобы получить полезную нагрузку во время выполнения.

Основываясь на этом потоке GH, я хотел согласовать dist путь локали с помощью package.json

  ...
 "exports": {
    ".": "./dist/src/main.js",
    "./": "./dist/"
  },
 ...
 

например, когда я публикую пакет на основе этой exports конфигурации, потребитель будет знать, как согласовать путь, либо относительный, либо префикс имени пакета, когда вызывается средство получения

 const fn = () => import('./locales/fr/myNamespace.json')  /// doesn't work
const anotherFn = () => import('@examplePackageName/locales/fr/myNamespace.json') /// doesn't work
 

Поскольку все является динамическим, я использую CopyWebpackPlugin для включения локалей в dist папку.

Это работает, как и ожидалось, локально, но когда я создаю dist , я получаю сообщение об ошибке Error: Module not found ./relative/path/to/the/json/I/want.json .

Мой вопрос:

Что я упускаю из виду? Есть ли простой способ предоставить доступ к этим переводам, чтобы другие приложения могли включать их в свои пакеты через пакет, установленный npm?

Вот моя конфигурация веб-пакета, с удовольствием предоставлю другую информацию по мере необходимости

 const path = require("path");
const CopyPlugin = require("copy-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

const getPlugins = () => {
  return [
    new CleanWebpackPlugin(),
    new CopyPlugin({
      patterns: [{ from: "locales", to: "locales" }],
    }),
  ];
};

module.exports = {
  mode: "production",
  entry: {
    main: "./src/main.ts",
  },
  output: {
    path: path.join(__dirname, "dist"),
    filename: "src/[name].js",
    chunkFilename: "chunk.[name].js",
    libraryTarget: "commonjs2",
  },

  resolve: {
    extensions: [".json", ".ts", ".js"],
    alias: {
      "@locales": path.resolve(__dirname, "locales/*"),
    },
  },
  plugins: getPlugins(),
  module: {
    rules: [
      {
        test: /.ts$/,
        exclude: [/.test.ts$/],
        include: path.join(__dirname, "src"),
        loader: "ts-loader",
      },
    ],
  },
};
 

Ответ №1:

Директива Exports предписывает явно определять все файлы, разрешенные для импорта (документация). Это позволяет разработчику скрывать внутреннюю структуру файла пакета. То, что не экспортируется этой директивой, доступно для импорта только внутри пакета, а не за его пределами. Это сделано для упрощения технического обслуживания. Это позволяет разработчикам переименовывать файлы или изменять файловую структуру, не опасаясь взлома зависимых пакетов и приложений.

Поэтому, если вы хотите сделать внутренние файлы видимыми для импорта, вы должны экспортировать их с помощью директивы exports явно, например:

 {
  "exports": {
      ".": "./dist/esm/src/main.js",
      "./dist/shared/locale/fr_fr.json": "./dist/shared/locale/fr_fr.json"
  }
}
 

Я не уверен, справится ли Webpack с этим случаем, потому что это пока экспериментальная функция. Но вот как Node.js работает и сейчас.

Почему это так

Изменение файловой структуры вашего приложения является серьезным изменением в терминах semver, поэтому вам нужно обновлять версию каждый раз, когда вы переименовываете или удаляете файлы. Чтобы избежать этого, вы можете указать, какие файлы являются частью общедоступного интерфейса пакета.

Комментарии:

1. В связанной проблеме явно указано ...if exports specifies a file, it hides other files. If exports specifies a directory, then all files in it can be accessed deeply (unlike pre Node 13.2). , что, я думаю, является моей главной причиной путаницы. Возможно, это ошибка реализации, возможно, это утверждение неверно. Спасибо за информацию.

2. Вы должны связать webpack.js.org/guides/package-exports , а не тот node.js документация