React Native: npm链接本地依赖项,无法解析模块

75

我正在为React Native开发一个按钮UI包。我尝试构建一个示例项目来测试这个按钮。目录结构如下:

my-button/
    package.json
    index.js
    example/
        package.json
        index.js

我尝试使用npm link

cd my-button
npm link

cd example
npm link my-button

example/node_modules/中,我可以看到my-button符号链接,在my-button包中,VSCode也能自动完成函数。

但执行示例应用程序将显示错误:

Unable to resolve module my-button ...
Module does not exist in the module map or in these directories: ...

但错误信息中的路径是正确的。

我不知道我的问题出在哪里,或者在React-Native中是否有特殊的方法来处理本地依赖关系?

我也尝试过npm install file:../.。这种方式很好用,但是在我编辑了my-button之后,更新example/中的依赖关系并不容易。


2
你最终找到了解决方案吗?还是React Native不支持本地npm包? - Magnus
你找到解决方案了吗? - Vito Lipari
13个回答

75
npm link命令无法使用,因为React Native打包程序不支持符号链接
经过一番研究,我发现有两种方法可以解决这个问题。
  1. 在示例应用中使用Haul打包程序。Haul支持符号链接,因此您可以像往常一样使用npm link
  2. 通过file:../使用本地依赖项,然后编辑node_modules文件夹中的文件或每次更改时重新安装。
我发现Haul非常适合这种用例,甚至设置了一个小型起始项目,其中还包括storybook,如果您需要在许多组件之间切换,这真的很有帮助。

我刚刚使用现有项目测试了Haul,但它无法工作,似乎没有维护。 - Dimitri Kopriwa
2
Haul已经演变成https://github.com/callstack/repack - ThomasRS
第二个选项对我没用 :( - JollyRoger

55

试试 wml (https://github.com/wix/wml),它是npm link的替代方案,可以实际复制更改的文件从源文件夹到目标文件夹

# add the link to wml using `wml add <src> <dest>`
wml add ~/my-package ~/main-project/node_modules/my-package

# start watching all links added
wml start

3
请确保关闭当前的 Metro Bundler 打包程序实例,并在下一次 react-native run-***** 命令时让 React Native 启动一个新实例。否则,你将继续遇到 OP 描述的错误。 - Dave Koo
6
WML仍在维护吗?自2017年以来,该代码库没有任何贡献。 - tjeisenschenk
如果有人正在使用此解决方案,并且遇到了与“node_modules”链接的问题,请在开始使用“wml start”之前,确保从“.watchmanconfig”文件的忽略列表中删除“node_modules”,该文件是由“wml”创建的。 - pmiranda
2
@pmiranda,你能让这个工作起来吗?我认为现在的答案已经过时了。 - Alwaysblue
WML在2022年对我很有效,但最初遇到了它无法执行任何操作的问题,我通过这个问题进行了修复。 - squareborg

19

我不能总是使用 yarn link 成功。我发现 yalc 特别有用:

首先永久全局安装它:

npm install -g yalc

在本地的库/包(我将其称为my-local-package),运行:

yalc publish

然后在使用 my-local-package 作为依赖项的项目中运行以下命令: (如果您已经以其他方式添加了它,请先卸载它 (npm uninstall -S my-lockal-package))

yalc add my-local-package
npm install
如果 my-local-package 是一个本地模块,则运行 react-native run-android 命令来链接依赖项。(或者运行 run-ios)。
如果您对 my-local-package 进行任何更改,则:
cd path/of/my-local-package
yalc push //updates the local package
cd path/to/my-project
npm install
react-native run-android (or run-ios)

如果更新尚未应用,请尝试执行以下操作:cd android && ./gradlew clean && cd ..,然后重新运行:react-native run-android


谢谢。我使用 yalc 和 metro 配置文件中的 watchFolders 来支持链接和热重载。 - microJ

9

我正在开发一个关于现有本机SDK的本机模块包装器,遇到了同样的问题。起初,我按照@aayush-shrestha所建议的方式在本地安装该软件包,如下所示:

npm install ../<package-folder> --save

只要通过 NativeModules 引用模块,这就可以正常工作。导入它即可:

import { NativeModules } from 'react-native';

然后像这样访问一个叫做ActualModuleName的模块:

NativeModules.ActualModuleName

但是,当我尝试按名称导入模块时,它会失败:

import { ActualModuleName } from 'react-native-actualmodulename'

为了使它起作用,我必须先打包这个包。在包的根目录中运行以下命令: python setup.py sdist
npm pack

这将生成一个gzip压缩的tar包:
react-native-actualmodulename-1.0.0.tgz

现在将其安装在您的应用程序中:

npm install <path/to>/react-native-actualmodulename-1.0.0.tgz

这样做的一个巨大缺点是,每次更改模块时都必须重新打包。我知道的唯一解决方法是直接修改node_modules中包的文件,然后在完成后将这些更改复制回您的存储库。

但好处是,您的应用程序源代码可以以与发布到npm相同的方式导入ActualModuleName;无需环境特定的代码。


当使用npm install .tgz文件时,它无法安装pod依赖项。 - girish_pro
@girish_pro 需要单独安装pod依赖项;在打包扩展之前,在“ios”目录中运行pod install - Wayne
@wayne_burkett pod install没有安装子依赖项。我的.tgz文件依赖于react-native-branch,它需要node_module和Pod两者都有。但是当我直接将.tgz文件和pod install添加到ios文件夹中时,它不会安装react-native-branch pod,只会安装node_module。 - girish_pro

8

您可以使用Metro使用npm link。只需将链接软件包的源文件夹添加到metro.config.js中的watchFolders即可。


1
这是最佳答案。当您通过npm install 'path/to/local/package'或在package.json中使用'file://path/to/local/package'安装本地包时,npm会链接到本地包而不进行复制。Metro Bundler不知道如何正确导入这些包。您可以更新Metro Bundler配置以解决此问题。我无法在评论中提供太多细节,但是在metro.config.js中添加3行即可,并且您可以在此优秀的写作中阅读更多详细信息(非我撰写):https://medium.com/@alielmajdaoui/linking-local-packages-in-react-native-the-right-way-2ac6587dcfa2 - Alex Choi

3

我遇到了同样的问题。虽然我无法使npm link正常工作,但我通过在项目文件夹中安装本地软件包解决了此问题。

npm install ../<package-folder> --save

这将像普通包一样从本地文件夹安装软件包。缺点是您对软件包所做的更改不会反映出来。每次更改后,您都需要执行npm install


26
无法运行。我看到node_modules中包含了该软件包,但当我运行应用程序时,会出现错误在Haste模块映射中不存在'xyz'模块 - Sarneet Kaur
2
可能是这个命令在 node_modules 下创建了一个符号链接,例如 React Native 无法使用它们。请尝试使用以下命令:npm install $(npm pack <folder> | tail -1)。来源:https://dev59.com/wWEi5IYBdhLWcg3wRaqf#54588310 - iqqmuT

3

修改你的 package.json 文件

//...
"dependencies": {
   //...
    "my-button" : "file:../"
  },
//...

3
我已经尝试过这种方法了,这种方式会将整个项目复制到“example/node_modules”,而不仅仅是一个符号链接。更新依赖关系并不是非常方便。 - Rick Liao
2
这个解决方案对我们来说很完美,但我们仍然遇到了相同的“模块未找到”错误。有什么想法吗? - Egidio Caprino

2

我也遇到了这个问题。在访问下面的链接后,我得知react-native不支持符号链接。[点击此处][1]

然而,我通过在metro.config.js文件中添加以下行来解决这个问题。请用你的模块名替换your_module_name

const path = require('path');

const thirdPartyPath = path.resolve(__dirname + '/../your_module_name/');  // Path of your local module

const thirdParty= {
  'your_module_name': thirdPartyPath,
  };

const watchFolders = [ thirdPartyPath];

module.exports = {
// existing dependencies
resolver: {
  thirdParty,
  },
  watchFolders
};

0

这对我有用:

步骤1 前往包:

npm link packageNameHere

这将把此包链接到全局 node_module

步骤2 进入您想要使用此包的目录并运行以下命令

npm link pathToPackageDirectory
npm install pathToPackageDirectory

例如:npm link ~/myDemoPackage

这将把全局的node_moudle链接到该项目

如果您想将包导入文件,请使用文件路径而不是包名称!

例如:

我的包名是stripe-api-helper。我的代码在src/index.ts中,那么我需要这样解析:

import { postStripe, Item } from '@aliciaForDemo/stripe-api-helper/src'

如果你使用 '@aliciaForDemo/stripe-api-helper',它会失败。


0

我遇到了同样的问题。

我尝试使用npm安装本地模块,但一直无法解决该模块的问题,即使我可以在node_modules中看到该文件夹,并且类和方法名称的自动完成也可以正常工作。

在看到github上的issue后,我通过使用yarn而不是npm来安装本地库来绕过它。该问题于2020年9月开放,Facebook至今没有发表评论。


你能用Yarn让它工作吗?不幸的是,我不能。 - Alwaysblue
@iRohitBhatia 是的,我能够使用Yarn安装它。你遇到了什么问题? - Marline
和原始帖子一样。我会在周末分享更多细节。顺便说一下,谢谢 :) - Alwaysblue

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接