首页 > 解决方案 > Package.json 使用 webpack 5 导出 - 找不到动态导入的模块

问题描述

我在协调 i18n 语言环境的动态导入路径时遇到了一些麻烦。这是相关代码 -

function getLoader(
  lang: SupportedLanguage,
  ns: SupportedNamespace
): NamespaceLoader | undefined {
  const matrixToCheck = UNSUPPORTED_MATRIX[ns];
  const isSupported = matrixToCheck && 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在他们各自的应用程序中调用 getter(在这种情况下)以获取语言和命名空间他们选择在运行时获取有效负载。

基于这个 GH 线程,我想dist通过package.json

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

例如,当我基于该exports配置发布包时,消费者将知道如何在调用 getter 时协调路径,无论是相对路径还是包名称前缀

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 安装的包将它们包含在它们的包中?

这是我的 Webpack 配置,很高兴根据需要提供其他信息

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",
      },
    ],
  },
};

标签: node.jsjsonwebpackwebpack-5

解决方案


导出指令规定明确定义允许导入的所有文件(文档)。它允许开发人员隐藏内部包文件结构。此指令未导出的内容只能在包内导入,不能在包外导入。它旨在简化维护。它允许开发人员重命名文件或更改文件结构,而不必担心破坏依赖包和应用程序。

因此,如果您想让内部文件对导入可见,您应该使用 export 指令显式导出它们,如下所示:

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

我不确定 Webpack 是否会处理这种情况,因为它还是一个实验性功能。但这就是 Node.js 现在的工作方式。

为什么会这样

更改应用程序文件结构是 semver 术语的重大变化,因此每次重命名或删除文件时都需要更新版本。为了避免这种情况,您可以指定哪些文件是包的公共接口的一部分。


推荐阅读