You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Webpack在Monorepo中按包根目录解析依赖?

Yarn 3 Monorepo中Webpack跨包模块路径解析失败问题

环境与配置

根目录package.json(片段)

{
  "name": "myweb",
  "workspaces": [
    "client/*"
  ]
}

目录结构

client/
  client-A/
    index.js
    src/
      components/
        AThing1.jsx
        AThing2.jsx
  client-B/
    src/
      components/
        BThing.jsx

关键文件代码

  • client/client-A/index.js:
export { default as AThing1 } from './components/AThing1'
  • client/client-A/src/components/AThing1.jsx:
import AThing2 from 'components/AThing2'
  • client/client-B/src/components/BThing.jsx:
import { AThing1 } from '@myweb/client-A'

报错信息

在client-B中启动Webpack 5开发服务器时出现:

ERROR in ../client-A/src/components/AThing1.jsx ...
Module not found: Error: Can't resolve 'components/AThing2' in '/workplace/termly_web/client/client-A/src/components/AThing1'

问题核心:Webpack在client-B的上下文解析client-A的模块时,会默认从client-B的src目录查找components/AThing2,而非client-A自身的src目录。

已尝试但无效的操作

  • 将client/client-A/src路径添加到client-B的Webpack配置resolve.modules和resolve.roots数组
  • 设置resolve.preferRelative = true

需求:不想修改client-A中所有导入语句为长相对路径(如../../../../components/Foo),也不想给导入添加@myweb/前缀。

现有配置文件

client/client-B/webpack.config.js(片段)

resolve: {
  modules: [
    'src',
    'node_modules',
  ],
  roots: [
    path.resolve(__dirname, 'src'),
  ],
  extensions: ['.js', '.jsx', '.scss', '.css', '.sass'],
},
module: {
  rules: [
    {
      test: /\.jsx?$/,
      exclude: [
        {
          and: [/node_modules/],
          not: [/@mycompany\/react-components\/src/],
        },
      ],
      loader:  'babel-loader',
    },
  ]
}

client/client-B/babel.config.js

module.exports = {
  presets: [
    '@babel/preset-env',
    '@babel/preset-react',
  ],
  plugins: [
    '@babel/plugin-proposal-class-properties',
    [
      'module-resolver',
      {
        alias: {
          'test': './test',
          'react': '../../node_modules/react',
          'react-dom': '../../node_modules/react-dom',
        },
      },
    ],
  ],
  env: {
    production: {
      plugins: [
        'transform-react-remove-prop-types',
      ],
    },
  },
}

解决方案

1. 给client-A添加自身的babel模块解析配置(推荐)

在client-A目录下创建babel.config.js,使用babel-plugin-module-resolver将src设为模块解析根目录,确保client-A内部的导入在任何上下文都能正确解析:

// client/client-A/babel.config.js
module.exports = {
  plugins: [
    ['module-resolver', {
      root: ['./src'], // 将src设为模块解析根目录
      alias: {
        // 可选:直接给components设置别名,进一步明确路径
        components: './src/components'
      }
    }]
  ]
}

同时,必须给client-A添加自己的package.json,指定包名才能让Yarn正确识别工作区包:

// client/client-A/package.json
{
  "name": "@myweb/client-A",
  "main": "index.js",
  "private": true // 标记为私有包,避免意外发布到npm
}

2. 在client-B的Webpack中针对client-A配置别名

如果不想给client-A单独加配置,可以在client-B的Webpack配置中添加别名,让Webpack解析client-A中的components/xxx时指向client-A的src目录:

// client/client-B/webpack.config.js
const path = require('path');

module.exports = {
  // ...其他配置
  resolve: {
    alias: {
      // 避免和client-B自身的components目录冲突,精确匹配client-A的组件路径
      '@myweb/client-A/components': path.resolve(__dirname, '../client-A/src/components')
    },
    // ...原有resolve配置
  }
}

3. 利用Yarn Workspace的exports字段(需调整导入语句,可选)

在client-A的package.json中设置exports字段,定义模块导出路径:

// client/client-A/package.json
{
  "name": "@myweb/client-A",
  "exports": {
    "./components/*": "./src/components/*",
    ".": "./index.js"
  }
}

此时client-A内部可改为import AThing2 from '@myweb/client-A/components/AThing2',但此方法需要修改导入语句,不符合需求,仅作备选。

内容的提问来源于stack exchange,提问作者dkreft

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 07:03:15