Skip to content

Latest commit

 

History

History
91 lines (74 loc) · 3.57 KB

README.md

File metadata and controls

91 lines (74 loc) · 3.57 KB

loaderify

A Browserify transform which allows one to add functional loaders on matching require() statements, similar to webpack

    npm install --save-dev loaderify

I wrote this transform after spending hours trying to find a way to inject templates and styles in to my Angular (ng2+) components that ALSO supported minifications, less, sass, emmet, etc. There were transforms for injecting html and css (stringify), but they hung on minification. There were transforms to inject scss/sass (scssify) but they injected <style> tags instead of just strings. Worse yet, the two transforms didn't get along well together, meaning I could choose between un-minified templates and css, or scss with no templates.

I didn't like those options

I'd seen this exact problem solved at work, where we use webpack. In webpack, you specify loaders for files matching certain patterns. These loaders can be functions or chains of functions, which operate on the source file and return a modified source. Seemed like a simple enough thing to do with browserify transforms, so I set about writing this plugin.

##How do I use it?

simply add loaderify in to your bundle process, specifying a list of loaders in the config, like so:

function bundle(){
    return browserify({})
    .add('./entry.js') 
    .transform(loaderify, {
        loaders: [
            {
                Pattern: '**/*.html', 
                Function: injectMinifedHtml
            },
            {
                Pattern: '**/*.scss', 
                Function: injectSass
            },
            {
                Pattern: 'assets/styles/*.css', 
                Function: injectCss
            }
        ]
    })
    .bundle()
    .pipe(gulp.dest('dist/')));
}

The strings in Pattern are standard wildcard matches. ** matches 0 or more directories, and * matches all files in the current directory. So **/*.html matches all html files, while assets/styles/*.css matches top level .css files in the assets/styles directory.

The functions in the Function key are in the format function(filelocation, contents, callback), where filelocation is the location of the required file relative to process.cwd() and contents holds the contents. The body can do whatever it wants to transform those contents, and when they are passed back to the callback, all instances of require('./filename') will be replaced with the results of your transforms!

For conditional transforms, the callback also an abort argument in the form of callback(abort, results). That way, your transforms can choose to leave the require() statement alone.

##What else can it do?

One possible use for the conditional transforms is environment-specific file loads. A transform could be written like so:

function envSwitch(fileloc, contents, callback){
    var env = process.env;
    if(env !== 'LOCAL') {
        return callback(true);
    } else {
        // find the corresponding mock service
        var mockLocation = path.join(path.dirname(fileloc), 'mock.'+path.basename(fileloc));
        // require the mock service instead!
        return callback(null, 'require(\''+mockLocation+'\')');
    }
}

function bundle(){
    return b
    .add('./entry.js')
    .transform(loaderify, {
        loaders: [
            {
                Pattern: 'services/**/*.js', 
                Function: envSwitch
            }
        ]
    })
    .bundle();
}

The possibilities are limitless. Just think how many transforms you can replace with this!