• Stars
    star
    428
  • Rank 101,481 (Top 2 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 5 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Installs local dependencies for optimal developer experience

relative-deps

Donate Buy Me A Coffee

Installs dependencies from a local checkout, and keeps them in sync, without the limitations of link


Summary

Relative deps introduces an additional dependency section in package.json, called relativeDependencies. This section contains paths to the local sources of any dependency, that will be built and installed over the publicly available versions, when needed.

Example package.json:

{
  "name": "my-project",
  "dependencies": {
    "my-cool-library": "0.1.0"
  },
  "relativeDependencies": {
    "my-cool-library": "../../packages/my-cool-library"
  },
  "scripts": {
    "prepare": "relative-deps"
  },
  "devDependencies": {
    "relative-deps": "^1.0.0"
  }
}

When the relative path can be found, the library at this path will be re-built and re-installed into this project, if the source files have been changed during prepare.

The normal my-cool-library dependency will be defaulted to, for those that don't have a local checkout of my-cool-library, and to resolve transitive dependencies.

An example setup, where examples project are linked to their hosting library, can be found here.

Why

The problem

Working on libraries that have examples embedded in the same git repository is usually tricky, as the examples are usually built against the public, published version of the library; the version that is mentioned in their package.json.

When working maintaining a project though, it is much more useful to work against the locally checked out version of the library. Published or not.

The problems with existing solutions

There are a few existing solutions, but they have their own limitations:

  • yarn link / npm link. These work only if there are no peer / shared dependencies involved. If there are shared dependencies, the linked library will resolve those in their own node_modules, instead of the node_modules of the hosting project, where it would normally be looked up. This results in peer dependencies ending up "twice" in the dependency tree, which often causes confusing behavior.
  • yarn workspaces. Those solve the above issue by putting all dependencies in one large root level node_modules. However, this setup is in practice quite obtrusive to the whole development setup.

How is relative deps different?

Relative deps doesn't fight the problem but tries to emulate a "normal" install. It builds the "linked" library on prepare (that is, after installing all deps), packs it, and unpacks it in the node_modules of the hosting project. Since there is no linking, or shared node_modules involved, the folder structure ends up to be exactly the same as if the thing was installed directly from yarn / npm. Which avoids a plethora of problems.

Since building a linked package every time yarn install is run is expensive, this tool will take a hash of the directory contents of the library first, and only build and install if something changed.

Usage

Installation

npx relative-deps init

Options:

  • --script

Alias -S. Default: prepare. Script name which is using for running relative-deps.

Running this script will install relative-deps, add script and initialize empty relativeDependencies section.

{
  "name": "my-project",
  "devDependencies": {
    "relative-deps": "^1.0.0"
  },
  "relativeDependencies": {},
  "scripts": {
    "prepare": "relative-deps"
  }
}

Optionally, you can add this step also for more scripts, for example before starting or building your project, for example:

{
  "name": "my-project",
  "scripts": {
    "prepare": "relative-deps",
    "prestart": "relative-deps",
    "prebuild": "relative-deps",
    "pretest": "relative-deps"
  }
}

In general, this doesn't add to much overhead, since usually relative-deps is able to determine rather quickly (~0.5 sec) that there are no changes.

Adding a relative dependency

Running following script will initialize relative-deps if not initialized yet, find the package at the provided path, install it as normal dependency and pack relative-dependency.

npx relative-deps add ../../packages/my-cool-library

Options:

  • --dev

Alias -D. Installs relative dependency in devDependencies section.

{
  "name": "my-project",
  "dependencies": {
    "my-cool-library": "0.1.0"
  },
  "relativeDependencies": {
    "my-cool-library": "../../packages/my-cool-library"
  },
  "scripts": {
    "prepare": "relative-deps"
  },
  "devDependencies": {
    "relative-deps": "^1.0.0"
  }
}

Example of a repository migration to relative-deps

Run npx relative-deps when devving!

The relative deps will automatically be checked for changes, based on the hooks you've set up during installation.

However, you can always trigger a manual check-and-build-if-needed by running npx relative-deps (or just yarn). If you are working on a project that supports hot reloading, this will makes sure the changes in the relative dependency will automatically show up in your project!

Watch mode

You can run relative-deps watch and it'll run relative-deps command when one of the relative dependecies changed, debounced with 500ms. This can go along with config of your project to watch over the relevant packages and it will automate the process completely, allowing you to change a library code and to enjoy the befefit of hot-reload.

How

Roughly, it works like this (obviously this can get out of date quickly):

- pre: yarn.lock exists or die
- read relativeDeps from nearest package.json
- doesn't exist? warn & exit
- for each relativeDep:
- check if target path exists
  - if not, do we have the module from normal install?
  - yes: warn
  - no: error
- if target path exists, does it have node modules?
  - no: run yarn / npm install (guess which one)
- find last modified timestamp of all files in target dir
  (excluding node_modules, .git, excluding the directory that contains the calling project if applicable, only use git versioned files)
- take hash and store / compare with stored
- if changed:
  - run yarn / npm build
  - run pack
  - extract package (mind scoped package names!)
  - run yarn install --no-dev-deps in target dir
- done

Tips

Tip: use the postinstall hook wherever applicable, if your dependency manager does not support prepare hooks yet.

More Repositories

1

use-st8

Single-function alternative for React.useState
TypeScript
229
star
2

import-size

Measure the real, minified, tree-shaken impact of individual imports into your app
JavaScript
123
star
3

redux-todomvc

Redux todoMVC, used to do some benchmarking
JavaScript
106
star
4

state-routing-blog-sources

JavaScript
88
star
5

remmi

Nothing to see here. Go away
TypeScript
86
star
6

rval

minimalistic transparent reactive programming library
TypeScript
85
star
7

react-mobx-shop

71
star
8

mst-course

Lesson sources for "Manage Application State with Mobx-state-tree" course
JavaScript
62
star
9

nscript

Write shell scripts like a bearded guru by unleashing your javascript skills!
JavaScript
60
star
10

mobx-todomvc

Trimmed down TodoMVC used for benchmarking
JavaScript
45
star
11

ts-npm-lint

Utility to help you to create typescript based npm modules. Can also strip reference paths.
JavaScript
38
star
12

willing-people

People you might want to ask instead of me
19
star
13

immer-gifts

Example accompanying the Immer course on egghead
JavaScript
19
star
14

react-next-2017-demo

JavaScript
10
star
15

miniup

Light-weight easy-to-use PEG parser with some toppings!
TypeScript
8
star
16

flipper-data-source-demo

TypeScript
6
star
17

NOA

A reflective data and calculating model for javascript
TypeScript
4
star
18

reactive2016-slides

The Quest For Immer Mutable State Management
HTML
4
star
19

math-tester

For my kids
TypeScript
4
star
20

mxgit

[unmaintained] Small tool that helps versioning Mendix projects with git.
JavaScript
4
star
21

react-ts-conversion-exercise

JavaScript
4
star
22

magix-mobx-slides

Slides from RuhrJS 2016 "Magic MobX" presentation
JavaScript
2
star
23

currencies-demo

JavaScript
2
star
24

clutility

The minimalistic class and inheritance utility for javascript.
JavaScript
2
star
25

flowmachine

TypeScript
1
star
26

reactjsday2017-presentation

HTML
1
star
27

react-next-2017-slides

HTML
1
star
28

reatjsday2017-demo

JavaScript
1
star