a spetacular web package manager and a cross-browser nodejs API provider
Instead of using a mix of browserify
, bower
or other package manager, we ported and enhanced node.js API to browser-side.
-
We ported
node.js
API to browser, so your could do things asrequire( 'stream' )
and expect same behaviors from withinnode.js
. -
We use asyncronous loading without having the need to
define
it as specified onAMD
pattern, we simply check things it really needs before running it, asCommonJS
does! We have developed a new pattern based on bothCommonJS
andAMD
patterns, on top ofPromises
wich is perfect for optional dependencies. Oh yes, I was forgotting, you could have optional dependencies which will run only when you need them! -
You could store your private packages on third-party SaaS (if you offer this kind of service, please create a storage module :) ), but the awesome around this is that you could compile into a folder and serve them by your own! We already created an
AWS S3
storage module. -
We do not serve Javascript packages, we serve web packages, which means that you could have packages without js at all. This is awesome for libraries such as font-awesome. For providing this versatilty, we created adapters, so they can handle compiling/loading/importing of files. The most is that adapters aren't only responsable for single filetypes, which means that you could have multiple adapters handling different types of files, which is really helpful for compressing, scrambling and other kind of stuff.
npm i -g requirehit
I belive that is easier to you to understand by placing a kind of FAQ for usage explaination.
If you are always with hurry as I am most of the times, and you do read things horizontally I suggest you to take a little of time to read this entirely just because it's worthed!
So, here are the questions:
We have done some research arround front-end package managers, we figured out some but they didn't were so versatile as we were looking for. So we started our creative process by creating initial specs on how everything would work.
While we were already coding requirehit
, we spoted webpack
. It could do
almost everything that we needed, but inspite it was modular and awesome, it
didn't fit our needs.
We needed something which we could (easily):
- apply under a lot of already existing npm modules without having to PR them and wait until someone accepts it;
- bring them to front-end without having to
browserify
them (actually we did the opposite of all package managers, we boughtnode.js
sources to browser); - place them on CDNs such AWS Cloudfront, by uploading them to a S3 bucket, and
thats why we have
storages
; - have packages with only html, tpl or css files;
- and more reasons I can't recall ATM, but as soon i remember them I will update this README! :)
By default, our configuration runs up from a .rh.js
file, but we have worked
out (at our code gym :p) to provide compability-mode for those that already
have a module configured with a package.json
.
Well, thats pretty easy to explain. I've said before that we needed to define
optional modules, and as you may know, package.json
doesn't support it.
We ended up on a more complex but fair easier way to configure packages:
We accept an Object as dependencies
options which you have to include
objects for different proposes.
IMPORTANT NOTE: If you choose to provide an object without some of those keys, requirehit will suppose that all things are modules and required.
Here you will include packages that you would include as dependencies
on a
regular package.json
file. It will respect exacly the same API, that means
that you could place up: semver wildcards, git, tar and that kind of stuff!
{
"required": {
"findhit-util": "^0.2.3"
}
}
We load components when we need them, that improves significally performance and its why we didn't pick any other package builder/loader.
As so, you could place here all optional packages exacly the same way as you do
on required
, the only difference is that you should use any async require way
such as promise
or callback
(you will understand in a few minutes how).
{
"optional": {
"some-new-fancy-component-that-you-wont-need-always": "latest"
}
}
Here is the interesting part that I've not mentioned earlier! We figured out
that we need sometimes to include packages on specific environments, not only
on testing
environment where you need test suits but also on different
development versions.
Internally we have four development stages: sdk
, analysis
, testing
and dev
.
sdk
is the environment of our modules into each developer computer.
analysis
is when our modules run over a specific PR, this is pretty useful
since we can stack up failings before changing it into testing
state.
testing
is for CI tests, well, name says all right?
dev
is for an internal server we have which we show up all new exciting features
we will merge on next version release! The most important propose for us is the
fact that we can checkup for bugs before release a beta
.
{
"environment-required-dev": {
"internal-bug-reporter": "git://.../../../bug-reporter.git"
}
}
var One = require( 'one' );
var Two = require( 'two' );
var modules = require([ 'one', 'two' ]);
// module[0] or module.one will be One
// module[1] o module.two will be Two
// ...
require( 'one', 'promise' )
.then(function ( One ) {
// One will have `one` module
});
require([ 'one', 'two' ], 'promise')
.then(function ( modules ) {
// module[0] or module.one will be One
// module[1] o module.two will be Two
})
// You could also use `.spread`
.spread(function ( one, two ) {
// one will be One
// two will be Two
});
// ...
require( 'one', function ( One ) {
// One
});
require( [ 'one', 'two', 'three' ], function ( one, two, three ) {
// one will be One
// two will be Two
// three will be Three
});
// or
require( [ 'one', 'two', 'three' ], function ( modules ) {
// module[0] or module.one will be One
// module[1] o module.two will be Two
// module[2] o module.three will be Three
});
This seems AMD
pattern right? :)
This method is available for those who want to handle module loading manually or out of promise or callback scopes ( such as observers and so on ).
// ...
var module = require( 'one', 'module' );
// When module.loaded turns truth
// module.exports will be One
var modules = require( [ 'one', 'two', 'three' ], 'module' );
// When `module.loaded` turns truth
// `module.exports` will be One
You could load files from your module or from another module, the only difference is that you will get them as a string or blob if they aren't threated by any adapter.