linklocal
is a development tool that reduces overheads of breaking your application into small packages. It gives you more expressive power than simple files and folders, yet requires far less overhead than versioning and publishing packages to a local private registry.
Requires npm 2.0.0 and above in order for npm to recognise local paths as dependencies.
npm install -g linklocal
linklocal --help
Usage: linklocal [options] <dir>
Options:
-h, --help output usage information
-f, --format [format] output format
-l, --link Link local dependencies [default]
-r, --recursive Link recursively
-q, --unique Only unique lines of output
-u, --unlink Unlink local dependencies
-n, --named Link only named packages, last argument is cwd
--absolute Format output paths as absolute paths
--files Output only symlink targets (--format="%h") [default]
--links Output only symlinks (--format="%s")
--list Only list local dependencies. Does not link.
--long Output the symlink to hardlink mapping (--format="%s -> %h")
--no-summary Exclude summary i.e. "Listed 22 dependencies"
-V, --version output the version number
Examples:
linklocal # link local deps in current dir
linklocal link # link local deps in current dir
linklocal -r # link local deps recursively
linklocal unlink # unlink only in current dir
linklocal unlink -r # unlink recursively
linklocal list # list all local deps, ignores link status
linklocal list -r # list all local deps recursively, ignoring link status
linklocal -- mydir # link local deps in mydir
linklocal unlink -- mydir # unlink local deps in mydir
linklocal --named pkgname ../to/pkg # link local dep by name/path
linklocal --named pkgname1 pkgname2 ../to/pkg # link local deps by name/path
linklocal unlink --named pkgname ../to/pkg # unlink local dep by name/
linklocal --named -r pkgname ../to/pkg # link local deps recursively by name/
linklocal --named -r @scope/pkgname pkgname ../to/pkg # link local deps recursively by name/ with npm @scope
Formats:
%s: relative path to symlink
%S: absolute path to symlink
%h: relative real path to symlink target
%H: absolute real path to symlink target
relative paths are relative to cwd
npm 2.0.0 supports specifying local dependencies in your package.json:
> npm install --save ../apple
> cat package.json
{
"name": "bowl",
"version": "1.0.0",
"dependencies": {
"apple": "file:../apple"
}
}
npm install
will copy (and npm install
) the package into the target's node_module's hierarchy.
This is not an ideal workflow during development: any time you modify your local dependency, you must reinstall it in every location that depends on it. If you do not update all copies, you will have different versions of the same code, probably under the same version number.
Global npm link
dependencies are also not ideal as packages clobber each other across projects.
By symlinking local dependencies while in development, changes can be instantly consumed by dependees, effects are limited to the current package and you can be more certain local dependees are using the latest changes.
linklocal
symlinks both development and production dependencies, and ignores modules packed by NPM (.tgz
).
linklocal
creates symlinks to any local dependencies it finds in your package.json.
e.g. test/banana/package.json.
{
"name": "banana",
"version": "1.0.0",
"private": true,
"dependencies": {
"apple": "file:../apple"
}
}
Note file:
dependencies are standard syntax in npm 2.x, just so that npm will copy the dependency into place, rather than symlink it. That's what linklocal
is for:
# from test/banana
# find local dependencies and symlink them
> linklocal
node_modules/apple -> ../apple
Linked 1 dependency
> # proof:
> ls -l node_modules
total 8
lrwxr-xr-x 1 timoxley staff 11 20 Sep 01:39 apple -> ../../apple
You can unlink all local links using linklocal --unlink
.
# from test/banana
> linklocal --unlink
node_modules/apple -> ../apple
Unlinked 1 dependency
> ls -l node_modules
>
If your local dependencies have local dependencies, you can use
linklocal -r
to recursively link all local dependencies:
bowl
depends on banana
banana
depends on apple
apple
gets linked into banana
node_modules/apple -> ../apple
node_modules/banana -> ../banana
../banana/node_modules/apple -> ../apple
node_modules/@nuts/almond -> ../almond
Linked 4 dependencies
apple
does not get linked into banana
# from test/bowl
> linklocal
node_modules/apple -> ../apple
node_modules/banana -> ../banana
node_modules/@nuts/almond -> ../almond
Linked 3 dependencies
# from test/named
> linklocal --named mypackagename ../
node_modules/mypackagename -> ../mypackagename
Linked 1 dependency
When linking local named packages, you may do so regularly or with recursion. The package names should be entered as an unordered list of strings, where the final argument is the relative path to where the source files for these packages are located.
linklocal
does not install dependencies of linked dependencies. To have dependencies installed, use timoxley/bulk or xargs
in a script like:
{
"name": "my-app",
"scripts": {
"dev": "linklocal link -r && linklocal list -r | bulk -c 'npm install --production'",
"prepublish": "if [ \"$NODE_ENV\" != \"production\" ]; then npm run dev; fi"
}
}
linklocal
does not install dependencies of linked dependencies, as such you typically end up installing dependencies of linked dependencies twice: once during npm install, then again after linklocal
Big thanks to:
- Yoshua Wuyts
- ben_cripps
- Vincent Weevers
- Craig Jefferds
- amalygin
- Mikael Brevik
MIT