Unsolving the mysteries of yarn/npm link for libraries development
Tags: react, javascript, node, npm
Published: 2019-06-19 09:37:48

## Introduction

Imagine you are developing a web app, that web app belongs to a family of web apps who shares the same style in their visual components, which means that you are probably going to build a UI library to centralize all your components. That will give you the possibility of changing some behaviour, even look and feel of specific components across all your applications by just modifying that library.

Now we have an issue: How do we test our library integration with the rest of the ecosystem locally without releasing a version every time we modify something? That’s a common bad practice that you’ll see at some companies, just releasing beta/minor versions to test stuff as they don’t have a local way to test the integration of the library with their apps.

Testing the individual components from your library can easily be done by using for example Storybook, but the integration with the rest of your applications is the tricky part, here is where you should use `yarn link`, the idea behind this is pretty simple: It just creates a symlink to whatever you point to.

## Time to add some real work

Let assume we have the app `myApp` who uses `myLibrary-UI`, being myLibrary-UI the UI library that provides all the base component to `myApp`. You are gonna have something like this in your `package.json`:

{% gist https://gist.github.com/MFCo/1269adaa5a800ee047ce3311098ea94e %}


Right now when we run yarn we can say that it generates the following structure: `myApp`is going to contain our library in its package, but if we want to use the local version instead of the published version, how do we override the version it uses?

![Our app containing our library](https://cdn-images-1.medium.com/max/1600/1*SUB5lIB_-efNER6KvHf48g.png)
<figcaption>Our app containing our library</figcaption>

It’s pretty simple, you should just build your library locally, then you run `yarn link` in the directory you build it, by doing it you’ll register your package locally. After this, you should just go to the root directory of your application and run `yarn link "@yourCompany/myLibrary-ui"`, this will create a symlink to your local copy that will be resolved before the copy installed by yarn.

- **WARNING:** *if you run yarn again, this link might disappear, you’ll need to run the last command again.*

![Our app linked to our local version of the library](https://cdn-images-1.medium.com/max/1600/1*piANkIo89icteb4T9V_X-A.png)
<figcaption>Our app linked to our local version of the library</figcaption>

By now we already have our app running using our local version of the library, this way we can easily test the integration of the new version with our app, and we can also use it to prepare our app to adopt any breaking changes from our library in case we need a simultaneous release. This might seems to be pretty straight forward but now is when the real issues begin.

## Multiple definitions

I’ll assume we are using React in our library, but we are also using React in our application, this should be easily solved by our package manager while installing them in a regular way.

![React is just installed at the top level, then used by children](https://cdn-images-1.medium.com/max/1600/1*PCKZl8ZG14eMkr05gWfS3w.png)
<figcaption>React is just installed at the top level, then used by children</figcaption>

But as we are linking it locally we have the problem of multiple React definitions in our project, this gonna generate multiple errors that are not that easy to debug and really not very descriptives, like for example:

- *Unhandled Rejection (Invariant Violation): Invalid hook call. Hooks can only be called inside of the body of a function component.*

![React is defined two times causing errors](https://cdn-images-1.medium.com/max/1600/1*2L5uZXX_HSNMBIk2epLtuQ.png)
<figcaption>React is defined two times causing errors</figcaption>

The easy way to fix it is by using the link command, we just go to our library and we create a link from there the React definition in our application, something like this: `npm link "../myApp/node_modules/React”`. This will create a symlink in our library to the React definition in our app. The result is our project will only use the React definition in `myApp` but it will run our local version of `myLibrary-UI`.

![Now we are using just the main definition](https://cdn-images-1.medium.com/max/1600/1*tmg8DxgutkTWqdjCfWICxQ.png)
<figcaption>Now we are using just the main definition</figcaption>

Now you are able to develop your library and test its integration with your apps locally just by using link commands. There are other ways to avoid multiple definitions, for example, let’s say we are using styled-components in both packages, but our app is also using NextJS, we can solve this issue by adding the resolver for this specific package in Webpack configuration:

{% gist https://gist.github.com/MFCo/17f8f9972020106fc3d92d6cbf8cfc0c %}

## Conclusion

Sometimes it’s really important to test your library locally so you can test its integration with other apps that use it. That’s really tricky sometimes but it helps you a lot to develop a better library.

By using link command you can easily achieve a configuration that allows you to test your libraries in a local environment, saving you from making for example test releases to check the integration.

Hope you like this article and most important I wish you find it helpful, I’ve been fighting with issues to test integrations between multiple packages a couple of times, some of this came out after several fails by myself.