Is it possible to share NPM dependencies between apps and packages?

I am using Meteor 1.3+ for making several applications, I use React rendering and NPM modules to setup the infrastructure, such us redux, react-redux, react-router, etc; but at the same time and in order to promote modularity and reusability I am sharing React components in a separate Meteor package.

The infrastructure that I have posed may be depicted as:

Meteor App #1
   NPM Package react
   Meteor Package A
      NPM Package react
   Meteor Package B
      NPM Package react
Meteor App #2
   NPM Package react
   Meteor Package A
      NPM Package react

I have used npm install --save [module] in the applications and packages. But when I try to render components that are created in both applications and packages, I got the next React error:

Uncaught Error: Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component's 'render' method, or you have multiple copies of React loaded (details: https://fb.me/react-refs-must-have-owner).

What is happening is that React is being instantiated several times, one per application and package. That unable me to use react references on components as those rely on a singleton React.

Do you know is there is a way to avoid a npm module to be instantiated more than one time? I have also tried to use Npm.depends([modules]) on each package, but it happens the same.

Thanks

I used to organise my apps using meteor packages, but have changed to ES6 modules inside /imports and it work much better now. To share components between apps I create those components in a top level folder or separate git repository and just create a link inside /imports to that folder. Changes to components are automatically detected and the app rebuilds. Also check “npm link” as a way to link the components repository.

I’m not a react user, but I think the peer npm dependencies section of the Writing Atmosphere Packages article in the Meteor Guide is directly applicable to your question.

Thanks for your answer.

What you said sounds well, but what happens if the meteor package where I keep the components depends on other meteor package. If I want to move my components to a separate repository to create a npm module, how do I import built stuff from a meteor package and use it?

As an example, I am using meteor-simple-schema in my current meteor package where I define react components.

Thanks buddy!

That is what I tried first. But this only ensures that we will use a concrete version of a NPM module in our app level.

To avoid multiple React instances, we would require to not include the react NPM dependency in the package, and only doing it at the app level. I tried on this, but this implies the test server for the package would not include the react dependency and therefore tests would not work.

I’m curious because I’m likely to dive into the React world soon and will definitely be going into the NPM package world since all of Meteor is going there, does making it a development dependency (–save-dev) in the package and a regular dependency (–save) in the app perhaps get both the app and test working? I’m thinking the app might still just run one instance and the test of the package would pick up the development dependency.

My reusable components are simple modules (not full packages) so I have to install all dependencies at the app level. This is not ideal from the organisation of code point of view, but at least have the advantage of avoiding the problem of loading a dependencies multiple times. In not a distant future all meteor core packages are going to be npm packages and I believe atmosphere packages will be abandoned or converted to npm packages.

Thank you @okada and @rlivingston for your help. I really appreciate your ideas, they filled my mind up with new perspectives.

In case this is useful for somebody, I have finally went through the idea to keep my current Meteor packages but without defining the needed NPM dependencies. Instead, I rely on the apps to define each dependencies needed by the packages. I use check-npm-versions to warn me about a dependency version required by a package when running my applications.

Concerning to the test issue, this is a well-known limitation and cause to an issue I opened up in the meteor repository, they suggest me to create a separate app to keep all tests from my packages. I decided to go this way for the moment.

As far as I have tested, there is not distinction between dev-deps and deps in terms of that they are imported and used on the package if you install them.