npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ffun

v2019.3.22

Published

Proof of concept for function-level dependencies

Downloads

4

Readme

npm-ffun

Proof of concept for function-level dependencies.

In other words, instead of adding a whole package (aka library) to your project as a dependency, you only add the functions (aka methods) that you need. You can think of each function as a 'mini-package', and ffetch.js as an alternative supplement to npm.

Example:

Say that you need a math function to add two numbers together, but you are not interested in the PI constant and the 100 other things a math package might provide.

You find the code you need in https://example.com/url/math/addition-1992.js

// a single arrow function
(x, y) => x + y

Your nodejs app could import just the code it needs:

// require ffetch with defaults()
const ff = require('ffun')()

// url (or local file path) to our dependency
let path = 'https://example.com/url/math/addition-1992.js'

// fetch the function and run it locally
ff(path)(2,5).then((add_result) => console.log(`2 plus 5 equals ${add_result)}`))

Outputs:

2 plus 5 equals 7

A more complex use case

The remote function could be more interesting. Fetched functions can also use ffetch themselves to retrieve other functions, and so forth, building an entire dependency tree they require to do complex tasks. An entire program can be built from only functions.

It takes a bit of practice in functional programming to think of constructing your programs in this way, but you will find it very rewarding to give it a try ~ regardless whether this project is a success or not.

Background

Dependencies often entail breaking changes. Often, especially for small pieces of code, developers prefer to copy or re-invent the wheel to avoid this dependency problem all togehter.

How many megabytes of dependencies does a project have ~ do you really need to download all the code, even if you only run a subset ?

Also, there is no benefit in re-testing and re-building the same things over and over if it's execution path hasn't changed. It slows down the dev/test feedback loop.

Semantic versioning makes dependency management a little easier with a convention: _._.x will probably not be a breaking change _.x._ also won't be a breaking change, pinky promise ;) x._._ is more honenst : changes will possibly break your code, oops!

However the version number only reflects the interactions with a package/library. Sometimes. The behaviour changes from version to version, and a 0.0.x bump could still be a breaking change anyway.

What we want is to re-use shared code, without pushing breaking changes to unknown consumers, and signal updates that people can opt into. (ex. security, bugfixes and performance improvements)

Futher work

Function-level dependency resolution, especially dynamically, provides it's own set of challenges and concerns to use over a traditional package manager (ex. npm, yarn).

I suspect dynamic resolution will have to be optional (mainly for security & reliability reasons), and to rather/also create a build tool.

Just as any central repository (Github <3, brew.sh, etc..) can evaporate, that problem is exemplified by having thousands of url based dependencies. Instead of creating yet another package manager central, it would be better to have a p2p-mesh network for sharing code. Thoughts arount that project:

  • Function identifiers could be a hash of the function, signed by the publisher on a shared ledger.
  • A mechanism to enable the mesh to additionaly share optimized javascript, python, and eventually compiled language components.
  • Who knows, maybe pure functions could be memoized globally..