Does browserify API need vinyl object? - node.js

I'm trying to browserify some angular files and integrate them into my gulp tasks. While trying to get the gulp plugin for browserify I came across this https://github.com/gulpjs/plugins/issues/47
Browserify should be used as a standalone module. It returns a stream and figures out your dependency graph. If you need vinyl objects, use browserify + vinyl-source-stream
I'm ashamed to say that I didn't know what vinyl objects were and after reading up a bit I came across this.
Vinyl is a very simple metadata object that describes a file.
And apparently you need vinyl adapters to expose .src, .watch and .dest? So, I'm guessing vinyl-source-stream is that sort of adapter? I guess what I don't understand is why would I need vinyl object in my browserify when I can simply do this:-
var gulp = require('gulp'),
browserify = require('browserify');
gulp.task('browserify', function(){
browserify('./js/index.js')
.bundle()
.pipe(gulp.dest('./js/bundle.js'));
And instead have to do this:-
var gulp = require('gulp'),
source = require('vinyl-source-stream'),
browserify = require('browserify');
gulp.task('browserify', function(){
browserify('./js/index.js')
.bundle()
.pipe(source('./js/index.js')) //this line in particular
.pipe(gulp.dest('./js/bundle.js'));
Apologize if this doesn't make sense. I'll edit this if it needs more explanation.

You can't just pipe to the string './js/bundle.js'. You use source to attach a name to the new file created by bundle, then you pipe the stream of file(s) to it's destination directory:
var gulp = require('gulp'),
source = require('vinyl-source-stream'),
browserify = require('browserify');
gulp.task('browserify', function(){
return browserify('./js/index.js')
.bundle()
.pipe(source('bundle.js')) //this line in particular
.pipe(gulp.dest('./js'));

Related

NodeJS/NPM - Package that will merge css files

I'm currently trying to optimize my website and I would like to know if there is a package that would automatically merge every css file and send only parts that are required for the site.
Is there anything similar to my idea?
You should probably go ahead with Gulp or Grunt , I prefer Gulp and you can follow this way
More details cab be found here https://gulpjs.com/
Create A Gulp Task
Then Execute the task by referring the name (This would create the merged css in the build/css folder)
var less = require('gulp-less');
var minifyCSS = require('gulp-csso');
var concat = require('gulp-concat');
gulp.task('css', function(){
return gulp.src('client/css/*.css')
.pipe(less())
.pipe(minifyCSS())
.pipe(gulp.dest('build/css'))
});
gulp.task('default', [ 'css' ]);

r.js from node script?

I feel like this must be so obvious but it's escaping me.
I'd like to run requirejs's r.js compilation from a node module instead of from the command line, and every bit of documentation I've seen just shows the command line option. Something like this is what I'm looking for:
var r = require('requirejs');
r('./build/common.js');
r('./build/app-main.js');
Let me explain the underlying motivation in case there's a better way to do it:
I've got a few different build.js files that I want to run r.js on (separate bundles for common dependencies and the main app). I'd like to wrap this up inside a gulpfile or gruntfile that runs both, and without putting all the r.js config in the actual grunt/gulp file like the grunt and gulp require.js plugins all seem to do. Leaving the r.js config in the separate build/*.js files would let us use grunt/gulp OR command line when we want to.
Any way to accomplish this?
Using the optimizer as a Node module is documented but it is not in the most evident place. This is the example that the documentation gives:
var requirejs = require('requirejs');
var config = {
baseUrl: '../appDir/scripts',
name: 'main',
out: '../build/main-built.js'
};
requirejs.optimize(config, function (buildResponse) {
//buildResponse is just a text output of the modules
//included. Load the built file for the contents.
//Use config.out to get the optimized file contents.
var contents = fs.readFileSync(config.out, 'utf8');
}, function(err) {
//optimization err callback
});

huge files size when browserifying angular

I am just trying gulp + angular + browserify app and got a huge browserified file, about 2M. While all it does just require angular and a sample controller.
// setup gulp task
gulp.task('browserify', function() {
gulp.src([util.format('%s/app/main.js', JS_BASE_DIR)])
.pipe(browserify({
insertGlobals: true,
debug: true
}))
// Bundle to a single file
.pipe(concat('bundle.js'))
// Output it to our dist folder
.pipe(gulp.dest(util.format('%s/js/', BUILD_BASE_DIR)));
});
//in the main.js
(function() {
'use strict';
var angular = require('angular');
var indexCtrl = require('./controllers/indexCtrl');
var app = angular.module('wohu.app', []);
app.controller('ctrl', indexCtrl);
})();
angular is installed via
npm install angular
The bundle.js is not minified but it shouldn't be that huge. Wonder what the problem is.
Browserify will include a source map in the bottom of the file which can make it seem HUGE. You can strip this out (and you should) for production. You can use exorcist for this (https://www.npmjs.com/package/exorcist) which pulls the source map into an external file for you and can be hooked up to your build process (I use Grunt but will work for Gulp too).

How to use Gulp to create a separate vendor bundle with Browserify from Bower components

I'm using Gulp and Browserify to package my Javascript into 2 separate bundles: application.js and vendor.js.
How do I bundle the vendor package if my vendor libraries are installed with Bower?
In my gulpfile, I'm using the following modules:
var gulp = require("gulp");
var browserify = require("browserify");
var debowerify = require("debowerify");
var source = require("vinyl-source-stream");
Assuming that I have only the Phaser framework installed with bower (for this example), my Gulp task to create the application package looks like this:
gulp.task("scripts-app", function () {
browserify("./app/javascripts/index.js")
.external("phaser")
.pipe(source("application.js"))
.pipe(gulp.dest("./tmp/assets"));
});
Meanwhile, the vendor task looks like this:
gulp.task("scripts-vendor", function () {
browserify()
.transform(debowerify)
.require("phaser")
.pipe(source("vendor.js"))
.pipe(gulp.dest("./tmp/assets"));
});
When I run this Gulp task, I get an error that states Error: Cannot find module 'phaser' from and then all the directories it search through (none of which are the bower_components directory).
Any ideas about how to package these up successfully are greatly appreciated. Thanks!
Answered my own question:
When using require in the Gulp task, you need to supply a path to a file, not just a name.
gulp.task("scripts-vendor", function () {
browserify()
.transform(debowerify)
.require("./bower_components/phaser/phaser.js")
.pipe(source("vendor.js"))
.pipe(gulp.dest("./tmp/assets"));
});
Notice that require("phaser") became require("./bower_components/phaser/phaser.js").
Doing this works, although the bundle takes forever to build (around 20 seconds). You're probably better of just loading giant libraries/frameworks directly into your app through a <script> tag and then using Browserify Shim.
This let's you require() (in the NodeJS/Browserify sense) global variables (documentation).
Seems like you figured out how to require the bower file. Hopefully you'll only have to bundle it once initially, and not every build. Including the library via a script tag isn't a bad idea. Another technique I'm using is to use scriptjs (a polyfill would work too), to async load whatever vender libraries I need, but make sure to include any/all require's after the script loads. For example, your index.js could be like:
$script.('/assets/vendor', function() {
var phaser = require('phaser');
//rest of code
});
It's especially nice for loading cdn files or having the ability to defer loading certain libraries that aren't necessarily used in the core app by every user, or loading libraries after client-side routing.

How to "require" text files with browserify?

I am using browserify (using browserify-middleware)
how can I require simple text files, something like:
var myTmpl = require("myTmpl.txt");
I cheked stringify plugin for browserify but the code in the documentation is not working with browserify V2
require() is really best for just javascript code and json files to maintain parity with node and to improve readability of your code to outsiders who expect require() to work the way it does in node.
Instead of using require() to load text files, consider using the brfs transform. With brfs, you maintain parity with node by calling fs.readFileSync() but instead of doing synchronous IO as in node, brfs will inline the file contents into the bundle in-place so
var src = fs.readFileSync(__dirname + '/file.txt');
becomes
var src = "beep boop\n";
in the bundle output.
Just compile with -t brfs:
browserify -t brfs main.js > bundle.js
More discussion about why overloading require() too much is a bad idea: http://mattdesl.svbtle.com/browserify-vs-webpack
stringify:
https://github.com/JohnPostlethwait/stringify
Here's author example:
var bundle = browserify()
.transform(stringify(['.hjs', '.html', '.whatever']))
.add('my_app_main.js');
If you really want to use require(), you may want to look at partialify:
my.txt:
Hello, world!
index.js:
alert( require( "my.txt" ) );
Where Browserify is configured:
var partialify = require( "partialify/custom" );
partialify.alsoAllow( "txt" );
bundle.add( "./index.js" );
bundle.transform( partialify );
Theoretically you will get a "Hello, world!" message in browser.
P.S. I haven't tried this myself.
Edit: note that this solution breaks NodeJS compatibility - it only works in browserified state, as NodeJS doesn't know how to require .txt files.

Resources