在实际开发过程中,经常需要同时运行和修改多个React Native工程,比如运行github上的开源项目以观察某种控件的实际效果。那么此时,各项目下的初始化(npm install)就会非常的痛苦,因为React Native的文件非常大,以0.17.0为例,安装后达到309MB。尽管,我们可以通过阿里npm等镜像站的方式加速下载的过程,但是下载后的进一步编译也非常地耗时。

此外,多React Native工程还带来了React Native自身的冗余,如果创建了十几个工程,那么多占用的空间轻松达到3GB以上,非常地不友好。

npm link原理

我的解决思路是:用npm link替代npm install。npm link [package-name]命令的原理是,去[prefix]/lib/node_modules/下检索是否已经全局安装了当前的package,如果是,则直接用软链接的方法在本地路径指向全局package。如果没检索到,则会先在全局路径下安装该package,再去建立软链接。npm获取全局路径的命令是:npm config get prefix

需要注意的是,有package.json的路径下,不要类比npm install,就这么执行npm link。此时npm link会把当前路径作为一个本地package,在全局路径下创建一个软链接。由此可知,npm link并不会像npm install一样,读取package.json中的依赖并自动配置。

配置过程

npm install -g react-native
cd [program_path]
npm link react-native

简单三步搞定。然后运行react-native run-android,打个Android包检测一下。

纳尼,报错如下:

Looks like you installed react-native globally, maybe you meant react-native-cli?
To fix the issue, run:
npm uninstall -g react-native
npm install -g react-native-cli

原因很简单,react-native框架其实由两个部分组成:react-native和react-native-cli,前者用于提供编译环境,后者则是封装了react-native开发过程中所要用到的命令,如react-native start,实质就是封装了sh ./node_modules/react-native/packager/packager.sh

官方文档要求全局安装react-native-cli,但是局部安装react-native,这是有原因的。如果你先全局安装了react-native-cli,会在/usr/local/bin下生成一个名为react-native的软链接,其指向为:react-native -> ../lib/node_modules/react-native-cli/index.js*。而随后再次"全局"安装react-native的时候,又会生成一个名为react-native的软链接,覆盖了react-native-cli安装时生成的软链接,其指向是:../lib/node_modules/react-native/local-cli/wrong-react-native.js。由此可见,React Native官方已经意识到了这个问题,然而不知何原因并不推荐全局安装React Native。然而笔者从节约硬盘空间和加快初始化的角度,认为还是有必要全局安装React Native,从而快速npm link的,所以有必要研究该报错的原理。

因此,针对这个报错,两种解决方法:

  1. npm install -g react-native,再npm install -g react-native-cli。然而,如果以后使用过程中又升级了全局React Native,此时需看方案2。

  2. cd /usr/local/binln -s ../lib/node_modules/react-native-cli/index.js react-native,即可重新创建一个指向react-native-cli的软链接。如果prefix的地址不是默认的,则ln -s prefix/lib/node_modules/react-native-cli/index.js react-native

缺陷

当前这个自动添加统一依赖的方法,存在一个问题。所有依赖于全局路径下的React Native都必须是一个版本的,npm link并没有提供多版本号依赖的解决方法。因此,还是建议选择一个常用的React Native版本安装在全局路径,个别需求其他版本号的React Native的项目,使用npm install来配置局部依赖。

插说一句,npm自身的依赖管理设计还是非常优秀的,然而React Native实在是太大了,而且我们完全有理由相信,他会更大。他其实应该是与Android SDK, Java SDK一般重量级的开发SDK,因此更应该借鉴rvm,设计一个React Native Version Manager。然而却委身于node_modules,因而产生了这种无奈的冗余。

====================================
如果您觉得我的文章对您有所启迪,请点击文末的推荐按钮,您的鼓励将会成为我坚持写作的莫大激励。 by DesGemini

如果觉得我的文章对你有用,请随意赞赏

你可能感兴趣的文章

8 条评论
Kenny田 · 2016年02月16日

我之前也是一直在想,能不能多个项目共用一个node_modules,感谢你的分享

回复

Fakefish · 2016年03月09日

我这里报了这个错 `Cannot find entry file index.ios.js in any of the roots: ["/usr/local/lib"]`

回复

zengxp0605 · 2016年07月07日

我有个更直接的做法, 当然也是只能适用于依赖同一版本的情况. 我的做法是,比如项目目录是 d:/project 那么所有的模块npm安装在 d:/node_modules/ 下面. 根据require('xxx')的查找原理得来的

回复

SuperMaxLi · 2016年09月28日

请问具体如何实现呢?我大概使用了一下,没有成功啊

回复

zengxp0605 · 2016年10月31日

不好意思,好久没登录,才看到消息.
我的意思就是假如你的项目在 d:/project/demo 这个目录下面,那么你的模块可以安装在 d:/node_modules/ 目录下, 然后在 demo目录下的js文件可以直接require引入已安装的模块

回复

SuperMaxLi · 2016年10月31日

好的,其实主要是修改package文件里面的配置信息就好了。

回复

potpot · 3月11日

这样来看的话,通过npm link能实现全局包的复用吧?但是有一个问题想请教下,比如我本地项目依赖eslint,我在全局安装了eslint,但是我不希望在本地安装,而是通过npm link将全局软链接到了本地项目,但是这个依赖并没有自动添加进package.json里,这样的话,完全不知道项目到底link了哪些东西,不容易维护,有相关的命令能处理这种情况吗?谢谢!

回复

要么你自己在 package.json 之外维护一个文件来记录你的本地 link 咯;或者你照样写在 package.json 里面。没什么区别,共同点是你去改写 npm install 方法,利用 shell alias,在 npm install 之前加一个预处理命令,随你用什么写啊,js, python, ruby,最终变成了 alias "npm install" = "your_tool_command; npm install"

DesGemini 作者 · 3月11日 回复
载入中...
DesGemini DesGemini

366 声望

发布于专栏

编程沉思录

予我风雷,以翱以翔

12 人关注

SegmentFault

一起探索更多未知

下载 App