从 npm 包的子文件夹导入

新手上路,请多包涵

我一直致力于创建一个小型的 React 组件库,用于其他几个项目。我在内部发布包(使用私有 GitHub 存储库),然后包含在另一个项目中。但是,当我从包的子目录导入时,我无法这样做,因为路径不匹配。

使用该包的项目都使用 webpack 来捆绑/转译代码,因为我尽可能避免在组件库中进行 任何 构建。

目录结构

- package.json
- src/
  - index.js
  - Button/
    - index.js
    - Button.jsx
    - ButtonGroup.jsx
  - Header/
    - index.js
    - Header.jsx (default export)

包.json

 ...
"main": "./src/index.js",
"scripts": "",
...

源代码/按钮/index.js

 import Button from './Button';
import ButtonGroup from './ButtonGroup';

export default Button;

export { Button, ButtonGroup};

源代码/index.js

如果仅从子目录导入,是否真的需要此文件?

 import Button from './Button';
import ButtonGroup from './Button/ButtonGroup';
import Header from './Header';

export { Button, ButtonGroup, Header };

其他项目

// This project is responsible for building/transpiling after importing
import { Button, ButtonGroup } from 'components-library/Button';

例子

Material-UI 是一个 React 组件库,通过以下方式要求使用: import { RadioButtonGroup } from 'material-ui/RadioButton 。我试图弄清楚这对他们有何作用,但无济于事。

类似问题

问题

  1. 我可以在导入路径中以某种方式跳过 src/ 目录吗?
  2. 我可以跳过包中任何类型的构建阶段吗(这样开发人员就不必在提交之前构建)?
  3. 类似material-ui的包是怎么处理这个的?

原文由 Kendall 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1k
2 个回答

一种可能的解决方案是 webpack 别名系统。

您可以创建另一个项目,例如将其称为“app-aliases”,这样您的别名就可以重复使用。

这个项目将有一个包含所有包路径的 js 文件:

 const path = require('path');

module.exports = {
'@components': path.resolve(__dirname, 'node_modules/components-library/src'),
'@another': path.resolve(__dirname, 'node_modules/any/path/you/want'),
}

然后将它添加到任何负责构建/转译的项目的 webpack 配置中:

webpack.config.js

 const appAliases = require('app-aliases');

const config = {
...
  resolve: {
    alias: {
      ...appAlises
    }
  }
}

在运行时代码中,您将能够像这样使用它:

 import {Button} from '@components/Button';
import {Something} from '@another'

如果您使用的是打字稿,则需要将相同的别名添加到 paths tsconfig 属性。

所以你的问题的答案是:

  1. 是的,您可以在别名中使用任何路径
  2. 是的,没有必要构建所有项目
  3. 我看到现在 mui 使用来自 directi 包的导入(例如核心),请参阅 https://material-ui.com/components/radio-buttons/ import Radio from '@material-ui/core/Radio'; 。但我希望他们使用我在下面描述的再出口。

还有关于 node.js 解析机制。

当您导入某个库时,它会尝试在其中查找 node_modules/some-library/package.jsonmain 属性。此属性应指向您的主要入口点。通常它是 src/index.js (如果还没有,你应该在 package.json 中设置它)。在此文件中,您可以从内部文件结构中重新导出任何您想要的内容,并且无需完整路径即可使用它。请参阅此 回购 以获取一些示例。

原文由 nickbullock 发布,翻译遵循 CC BY-SA 4.0 许可协议

我可以在导入路径中以某种方式跳过 src/ 目录吗?

是的。使用 package.json "exports" 字段,Webpack 应该在不久的将来支持它(参见这个 问题),但是自从 Node 12 LTS 遵循 Bare Module Specifier Resolution 提案 以来,Node 已经支持它:

包.json

 ...
"main": "./src/index.js",
"type": "module",
...
"exports": {
  "./Button": "./src/Button/index.js",
  "./Header": "./src/Header/index.js"
},
...

现在,以下代码:

 // This project is responsible for building/transpiling after importing
import { Button, ButtonGroup } from 'components-library/Button';

应该翻译成:

 import { Button, ButtonGroup } from 'components-library/src/Button/index.js';

应该正确导入请求的模块。

警告

现在,尝试更简单的版本肯定很诱人:

 ...
"exports": {
  "./Button": "./src/Button/",
  "./Header": "./src/Header/"
},
...

所以作为通常的导入语句

import { ... } from 'components-library/Button';

被翻译成

import { ... } from 'components-library/src/Button';

这看起来不错,但在这种情况下 不起作用,因为您的子模块没有各自的 package.json 文件,而是依赖于它们的 index.js 文件才能找到。

/!\ 与 CommonJS 不同,不会自动搜索 index.js 或 index.mjs 或文件扩展名。


src/index.js - 如果只从子目录导入,这个文件真的是必需的吗?

我不这么认为,但如果你愿意,你可以保留它。


我可以跳过包中任何类型的构建阶段吗?

使用 "exports" 字段不需要您转换代码。

原文由 Luc125 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题