【问题标题】:Webpack resolve alias and compile file under that aliasWebpack 解析别名并在该别名下编译文件
【发布时间】:2020-07-28 16:50:39
【问题描述】:

我有一个使用 lerna 的项目(monorepo,多个包)。很少有软件包是独立的应用程序。

我想要实现的是在少数包上使用别名来实现依赖注入。例如,我有别名 @package1/backendProvider/useCheckout 并且在我的独立应用程序的 webpack 中,我将其解析为 ../../API/REST/useCheckout 。因此,当我将后端提供程序更改为其他内容时,我只会在 webpack 中进行更改。

问题

当其他包(不是独立应用程序)使用此别名时会出现问题。例如:

目录结构如下:

Project
    packageA
           ComponentA
    packageB
           API
              REST
                  useCheckout
    standalone app

组件A在packageA中

useCheckout 在/API/REST/useCheckout 路径下的packageB 中

ComponentA 使用 useCheckoutimport useCheckout from '@packageA/backendProvider/useCheckout 之类的别名

独立应用使用组件A

我得到的错误是Module not found: Can't resolve '@packageA/backendProvider/useCheckout

但是,当在独立应用程序(具有下面提供的配置的 webpack)中使用相同的别名时,它正在工作。问题仅发生在依赖项上。

可能的解决方案

我知道一种解决方案是使用 webpack 编译每个包 - 但这似乎并不友好。我认为可行的是告诉 webpack 将这些别名解析为目录路径,然后重新编译它。第一部分(解析别名)已完成。

当前代码

当我使用 NextJS 时,我的 webpack 配置如下所示:

 webpack: (config, { buildId, dev, isServer, defaultLoaders }) => {
    // Fixes npm packages that depend on `fs` module
    config.node = {
      fs: "empty"
    };

    const aliases = {
    ...
      "@package1/backendProvider": "../../API/REST/"
    };

    Object.keys(aliases).forEach(alias => {
      config.module.rules.push({
        test: /\.(js|jsx)$/,
        include: [path.resolve(__dirname, aliases[alias])],
        use: [defaultLoaders.babel]
      });

      config.resolve.alias[alias] = path.resolve(__dirname, aliases[alias]);
    });

    return config;
  }

【问题讨论】:

    标签: javascript webpack babeljs next.js lerna


    【解决方案1】:

    您不需要使用别名。我有一个类似的设置,只需切换到 yarn (v1) 工作区,这是一个非常聪明的技巧,它将符号链接添加到根 node_modules 中的所有包。

    这样,每个包都可以毫无问题地导入其他包。

    为了使用 lerna 应用纱线工作空间:

    // lerna.json
    {
      "npmClient": "yarn",
      "useWorkspaces": true,
      "packages": [
        "packages/**"
      ],
    }
    
    // package.json
    {
      ...
      "private": true,
      "workspaces": [
        "packages/*",
      ]
      ...
    }
    

    这将启用带有 lerna 的纱线工作区。

    剩下要解决的唯一想法是让消费者包转译所需的包(因为 babel 和 webpack 的默认配置是忽略 node_module 转译)。

    在 Next.js 项目中很简单,使用next-transpile-modules

    // next.config.js
    
    const withTM = require('next-transpile-modules')(['somemodule', 'and-another']); // pass the modules you would like to see transpiled
     
    module.exports = withTM();
    

    在使用 webpack 的其他包中,您需要指示 webpack 转译您使用的包(假设它们在 @somescope/ 的 npm 范围内)。

    因此,例如,为了转换 typescript,您可以添加额外的模块加载器。

    // webpack.config.js
    {
      ...
      module: {
        rules: [
          {
            test: /\.ts$/,
            loader: 'ts-loader',
            include: /[\\/]node_modules[\\/]@somescope[\\/]/, // <-- instruct to transpile ts files from this path
            options: {
              allowTsInNodeModules: true, // <- this a specific option of ts-loader
              transpileOnly: isDevelopment,
              compilerOptions: {
                module: 'commonjs',
                noEmit: false,
              },
            },
          }
        ]
      }
      ...
      resolve: {
          symlinks: false, // <-- important
      }
    }
    

    如果你有 css,你还需要为 css 添加一个部分。

    希望这会有所帮助。

    额外优势,yarn 工作区将减少您的 node_modules 大小,因为它会安装重复的包(具有相同的 semver 版本)一次!

    【讨论】:

    • 我已经尝试过了,webpack 4 (babel-loader?) 会中断符号链接模块中的任何错误。修复需要删除 node_modules/.cache/babel-loader 并重新启动服务器。你遇到过吗?
    • 这取决于你之前的设置,需要删除一次吗?
    猜你喜欢
    • 1970-01-01
    • 2017-07-27
    • 2018-11-01
    • 1970-01-01
    • 2018-08-29
    • 2022-10-24
    • 1970-01-01
    • 2017-06-16
    相关资源
    最近更新 更多