从npm包

时间:2017-06-03 14:59:38

标签: javascript node.js npm webpack package.json

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

使用该软件包的项目都利用webpack捆绑/转换代码,因为我试图避免在可能的情况下在组件库中进行任何构建。

目录结构

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

的package.json

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

的src /按钮/ index.js

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

export default Button;

export { Button, ButtonGroup};

的src / 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. 我可以在导入路径中以某种方式跳过component-library/src/item目录吗?
  2. 我是否可以跳过包中的任何类型的构建阶段(因此开发人员在提交之前不必构建)?
  3. 与material-ui类似的包如何处理?

6 个答案:

答案 0 :(得分:1)

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

是的。使用package.json select e.dateended e.salary i.amount ext.contribution from earnings e left join intcontributions i on e.folderid = i.folderid and e.dateended = i.datereceived left join extcontributions ext on e.folderid = ext.folderid and e.dateended = ext.datepaid 字段,Webpack将在不久的将来支持该字段(请参阅此issue),但是自Bare Module Specifier Resolution proposal之后的节点12 LTS以来,Node已支持该字段。 :

package.json

"exports"

现在,以下代码:

...
"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文件被发现。

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


src / index.js-如果仅从子目录导入,实际上是否需要此文件?

我不这么认为,但是您可以保留它。


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

使用index.js字段不需要翻译代码。

答案 1 :(得分:1)

您必须安装 babel-plugin-module-resolver 软件包

在您的 .babelrc 文件别名中指定包的相对路径,如下所示

{
  "plugins": [
    ["module-resolver", {
      "alias": {
        "components-library": "./node_module/components-library"
      }
    }]
  ]
}

然后您可以像这样导入npm包的子目录

import { Button, ButtonGroup } from 'components-library/Button';

答案 2 :(得分:0)

答案可能取决于您安装组件库的方式。如果您是通过 i = 0 while i < nt: //do whatever you want if i == nt-1: i=0 npm install <git-host>:<git-user>/<repo-name>

完成的
  1. 根据your first linked question,您应该能够npm install <git repo url>。与Node's require() resolution类似,Webpack应该解析组件库中相对于组件库入口点的子目录。您可以通过webpack.config.resolve属性找到有关自定义解决方案行为的文档。 material-ui似乎依赖于从模块入口目录解析子目录导入。

  2. 要分发ES模块库,在分发之前无需构建。但是,create-react-app等项目可能需要预先编译的版本。

  3. 或者,您可以写import {Button} from 'component-library/Button'。  Webpack将通过每个import {Button} from 'components-library'追溯依赖关系,而不用大惊小怪。

答案 3 :(得分:0)

可能的解决方案之一是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程序包(例如core)导入的数据,请参阅https://material-ui.com/components/radio-buttons/,其中有import Radio from '@material-ui/core/Radio';。但我希望他们使用我在下面介绍的重新导出。

还有node.js解析机制。
导入某些库时,它将尝试在其中找到node_modules/some-library/package.json,然后找到main属性。此属性应指向您的主要入口点。通常是src/index.js(如果尚不存在,则应在package.json中设置它)。在此文件中,您可以从内部文件结构中重新导出所需的任何内容,并且无需完整路径即可使用它。 请查看此repo的示例。

答案 4 :(得分:0)

我是一个从未使用过react的开发人员,但是我可以说material-ui使用的是monorepo,其中相同的概念存在于angular中,我们创建了一个工作区,并且该工作区包含了react中命名的多个项目/包。了解更多信息Workspaces with Yarn

材料ui在tsconfig中使用伪造的路径,使其看起来像src文件夹,这在您提供的git中不存在:tsconfig.json

答案 5 :(得分:0)

这是可能的,但需要发布精选的 dist 文件夹,而不是项目的根目录。

如果您了解模块解析的工作原理,那么整个事情就相当简单了,您只需要一个小脚本来准备您的发行版。

为免我在此重复所有细节,请参阅我对Importing from subfolders for a javascript package的回答。