A fast node package manager for better productivity and efficiency
fyn is a super fast node package manager with some unique features:
node_moduleswith guaranteed single copy of a package
Interested in giving it a quick test? Just install and run it on your project:
$ npm i -g fyn $ cd <your-project> $ fyn
fyn is the result of a long pursuit to make developing and managing large and complex software in NodeJS easier.
To realize that, it ultimately ends up being a node package manager.
It started out as small experiments for a single goal of better local package installing and linking, ie: better npm link, but has gradually grown to a fully functional node package manager for the flat node_modules design. It is fast, production quality, and maintains 100% compatibility.
While it has all the bells and whistles to make it an extremely fast and efficient package manager, it's not just another npm.
It comes with two unique features that are very useful when you are working on a large NodeJS application that consists of many packages.
So why would you want to use this? If you just want to try a different approach to installing your
node_modules, then it's worth a look.
node_modules is the smallest in size because there are no multiple copies of the exact same package installed.
It also has a special
fynlocal mode that's a better npm link for handling local packages.
If your development in NodeJS are typically simple and involves only a single module or small applications, then
fyn's advantage may not be apparent to you, but if your NodeJS project is large and complex, then fyn may be helpful to you. Please read further to learn more.
fyn has a
fynlocal mode that's designed specifically to be a much better npm link. It treats packages on your local disk like they've been published. You can install and use them directly, and quickly test changes iteratively. It would be very useful if you've ever done any of these:
node_modules, and then have to copy the changes out to commit.
fynworks particularly well with a lerna repo.
What is this? Think npm link, but better.
fyn subjects local packages to the same dependency resolution logic as those from the npm registry. Then you can test changes to any module locally as if they were published.
To enable, use the path to your local modules as semver in your package.json, or you can use the
fyn add command.
fyn add ../my-awesome-module
That will install
my-awesome-module into your node_modules. You can continue to develop and test
my-awesome-module in its own directory and have the changes within existing files reflected in your app directly. Unlike
npm link, your app resolves dependencies for
my-awesome-module instead of relying on having them installed under
If you add/remove files/directories in your local package, then running
fyn install would take only seconds to update.
fyn will also save a file
package-fyn.json with local dependencies in a section called
fyn. You should not commit this file and
fyn will automatically check this file when installing, but you can turn off
fynlocal mode with with the flag
As a package manager,
fyn employs a different approach that installs only one copy of every required versions of a package in a flat node_modules structure. Hence the name
fyn, which stands for Flatten Your Node_modules.
At the top level, it installs a chosen version of each package. All other versions are installed under the directory
When necessary, packages have their own
node_modules with symlinks/junctions inside pointing to dependencies under
This approach has the benefit of guaranteeing a single copy of a package installed and therefore slightly smaller size
With a guaranteed single copy of a package, it makes debugging easier when you have to reach into code under
node_modules installed by npm could potentially have multiple copies of an identical package. So even if you've identified the module under
node_modules to investigate your issue, you may still need to figure which copy.
node_modules design, there is only one copy of any version so it's easier for you to set your breakpoint.
fyn to your NodeJS setup globally.
npm install -g fyn
Change into the directory for your project with the
package.json file, and run:
installis the default command.
Depending on the size of your dependencies and your network speed, this could take anywhere from a few seconds to a few minutes.
fyn run <script-name>or
fyn run -lor
If you have a lockfile, then
fyn takes sub seconds to regenerate the entire dependency tree even on very large applications. This makes it very fast to probe what's installed.
It has a
stat command that's very fast and can let you know all copies of a package installed and all others that depend on it.
$ fyn stat chalk > loaded lockfile ~/fyn > done resolving dependencies 0.113secs > chalk matched these installed versions firstname.lastname@example.org, email@example.com(fv) > firstname.lastname@example.org has these dependents email@example.com, firstname.lastname@example.org, email@example.com, firstname.lastname@example.org, email@example.com, firstname.lastname@example.org, email@example.com, ~package.json > firstname.lastname@example.org has these dependents email@example.com, firstname.lastname@example.org
Ever want to install your dependencies only consider packages published up to a certain date in the past?
fyn's got you covered with the
$ rm fyn-lock.yaml $ fyn install --lock-time "12/01/2018"
$ fyn install --lock-time "dec 01, 2018"
fyn will only consider packages published up to Dec 01, 2018 when installing.
If you have any optional dependencies, then they will not be re-evaluated if you have a lock file.
You can re-evaluate optional dependencies with
fyn install --refresh-optionals
lerna actually implements its own internal
npm link like feature to support a monorepo with packages that depend on each other.
You can use fynpo's
local command to update and commit your monorepo's packages'
package.json, and you can run
fyn to install and update their dependencies without having to do it through bootstrap.
$ fynpo local $ cd packages/my-awesome-package $ fyn
fyn options can be listed in help:
fyn loads config from
~/.npmrc in this specified order, from highest to lowest priority.
.npmrc, only fields
_auth are read.
.fynrc file can be an ini or
YAML format. For the
YAML format, the first line must be
Below is an
YAML example, with all the options set to their default values:
--- registry: https://registry.npmjs.org "@scope:registry": https://registry.custom.com offline: false forceCache: false lockOnly: false progress: normal logLevel: info production: false centralStore: false
Or as an ini:
registry=https://registry.npmjs.org @scope:registry=https://registry.custom.com offline=false forceCache=false lockOnly=false progress=normal logLevel=info production=false centralStore=false
Any command line option can be converted to an option in the RC file by changing the name to camelCase form.
If there's no RC file or command line override, then these defaults are used:
Scope registry can be specified in the RC files, the same as
For example, in Yaml format:
--- "@scope:registry": https://registry.custom.com
In ini format:
Inspired by pnpm,
fyn supports storing a single copy of all packages at a central location, and use hardlinks to install them into your
The main advantage of this is to save disk space and slightly faster install if the storage is primed.
However, this feature is not enabled by default due to the following drawbacks:
Creating hardlinks actually could take a lot more than trivial time.
What this means is the first time you install with
fyn, when nothing is cached in the storage, central store mode will actually take noticeably more time, but subsequent installs could be faster.
In particular, very bad on MacOS (High Sierra). For example, using hardlinks to replicate the module
nyc actually takes longer than untaring the tgz file. It improves somewhat with concurrency, but still significant.
On Linux with ext4 hardlinking appears to be more than 10 times more efficient than MacOS.
You can't do your debugging and development by modifying code that's installed into
Reason being that any change you make will affect the central copy, and therefore any other
node_modules that's linked to it.
If you do this, then even after you blow away your
node_modules and reinstall it, your "debugging" changes will be there again.
I imagine that this is actually a fairly big drawback for a lot of people.
However, the primary design goal of
fyn is to make your module development easier with its local linking install feature. You should use that to develop and debug multiple modules locally.
Similar to 2, but if any package has
postinstall script that modifies its own files, then those modifications would affect all installations.
In general if disk space is not an issue for you, then it's better to avoid this and the issues that will likely creep up on you when you least expect it.
If you do have a use of this feature despite the drawbacks, then you can enable it with the
--central-store CLI option.
The recommendation is to add the following to
.fynrc because then you don't have to remember to specify the option in the CLI every time.
And to work around the issues,
fyn does the following:
--copyoption that allows you to force any package to install with copying instead of hardlinking.
fynwill not hard link packages from central store if they have
fyn's top level
node_modules is 100% compatible with NodeJS and 3rd party tools and modules. No special updates or changes needed.
fyn uses npm's pacote to do data retrieval. That means its package data handling is the same as npm and it can use npm's cache directly.
fyn uses symlinks to resolve nested dependencies is also fully compatible with NodeJS. The only caveat is NodeJS module loader always resolve a package's path to its real path.
For example, if
A depends on
B@1.0.0 that's not at the top level, then
node_modules/A/node_modules/B is a symlink to
Without preserve symlinks,
B's path would be resolved to the real path
node_modules/B/__fv_/1.0.0/B, instead of the symlink path
If you want to keep the symlink path, then set the environment variable NODE_PRESERVE_SYMLINKS to
1. It doesn't affect normal operations either way unless you have code that explicitly depend on the path, which should be avoided. The subtle difference is that with preserve symlink, each symlink path of the same module will be loaded as its own instance by Node's module system.
fyn will take npm's
package-lock.json if its own
fyn-lock.yaml file doesn't exist, but will save
As a package manager, the top level
node_modules installed by
fyn is a flat list of all the modules your application needs. It's easier to view and smaller in size. Extra versions of a module will be installed under a directory
__fv_, and linked through symlinks or flat-module.
fyn has an asynchronous and concurrent dependency resolution engine that is 100% compatible with node's nesting design, and properly handles
Node Package Manager is a very large and complex piece of software. Developing
fyn was 10 times easier because of the generous open source software from the community, especially the individual packages that are part of
Other than benefiting from the massive package ecosystem and all the documents from
npm, these are the concrete packages from
fyn is using directly.
runas a convenience.
runcommand as a convenience.
Copyright (c) 2015-present, WalmartLabs
Licensed under the Apache License, Version 2.0.