Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Browserify All The Things

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

Browserify All The Things

This talk is about how to use browserify to develop front-end modular code using Common.JS, and how those modules should be documented, designed, and released using an automated build system. In order to explain these concepts I'll walk you through a few of my own open-source creations, highlighting interesting points as we go along.

Avatar for Nicolás Bevacqua

Nicolás Bevacqua

August 28, 2014
Tweet

More Decks by Nicolás Bevacqua

Other Decks in Technology

Transcript

  1. ~function (window) { function sum (a, b) { return a

    + b; } window.math = {sum: sum}; }(this);
  2. Closures - Abuse global variables - Fine for tiny projects

    - Modularity is up to you - Manual dependency management
  3. define([], function () { function sum (a, b) { return

    a + b; } return { sum: sum }; }); math.js
  4. AMD Modules - Resolves dependency graph - Lacks a straightforward

    API - Drastic changes after you build - So. Much. Clutter.
  5. function sum (a, b) { return a + b; }

    ! export default {sum: sum}; math.js
  6. ES6 Modules - The Way Forward ™ - To use

    today, add a transpilation step
  7. ES6 Modules - The Way Forward ™ - To use

    today, add a transpilation step - Hard to interact with CJS modules
  8. ES6 Modules - The Way Forward ™ - To use

    today, add a transpilation step - Hard to interact with CJS modules - Not generally available / popular yet
  9. function sum (a, b) { return a + b; }

    module.exports = {sum:sum}; math.js
  10. var camel = /([a-z])([A-Z])/g; var hyphens = '$1-$2'; function parseStyles

    (styles) { if (typeof styles === 'string') { return styles; } return Object.keys(styles).map(function (key) { var prop = key.replace(camel, hyphens).toLowerCase(); return prop + ':' + styles[key]; }).join(';'); }
  11. var camel = /([a-z])([A-Z])/g; var hyphens = '$1-$2'; function parseStyles

    (styles) { if (typeof styles === 'string') { return styles; } return Object.keys(styles).map(function (key) { var prop = key.replace(camel, hyphens).toLowerCase(); return prop + ':' + styles[key]; }).join(';'); }
  12. var camel = /([a-z])([A-Z])/g; var hyphens = '$1-$2'; function parseStyles

    (styles) { if (typeof styles === 'string') { return styles; } return Object.keys(styles).map(function (key) { var prop = key.replace(camel, hyphens).toLowerCase(); return prop + ':' + styles[key]; }).join(';'); }
  13. var camel = /([a-z])([A-Z])/g; var hyphens = '$1-$2'; function parseStyles

    (styles) { if (typeof styles === 'string') { return styles; } return Object.keys(styles).map(function (key) { var prop = key.replace(camel, hyphens).toLowerCase(); return prop + ':' + styles[key]; }).join(';'); }
  14. var camel = /([a-z])([A-Z])/g; var hyphens = '$1-$2'; function parseStyles

    (styles) { if (typeof styles === 'string') { return styles; } return Object.keys(styles).map(function (key) { var prop = key.replace(camel, hyphens).toLowerCase(); return prop + ':' + styles[key]; }).join(';'); }
  15. var camel = /([a-z])([A-Z])/g; var hyphens = '$1-$2'; function parseStyles

    (styles) { if (typeof styles === 'string') { return styles; } return Object.keys(styles).map(function (key) { var prop = key.replace(camel, hyphens).toLowerCase(); return prop + ':' + styles[key]; }).join(';'); }
  16. module.exports = function (selector, styles) { var css = parseStyles(styles);

    var sheets = document.styleSheets; var s = sheets[sheets.length - 1]; var key = s.cssRules ? s.cssRules: s.rules; if (s.insertRule) { sheet.insertRule(selector + '{' + css + '}', key.length); } else if (sheet.addRule) { sheet.addRule(selector, css, key.length); } };
  17. module.exports = function (selector, styles) { var css = parseStyles(styles);

    var sheets = document.styleSheets; var s = sheets[sheets.length - 1]; var key = s.cssRules ? s.cssRules: s.rules; if (s.insertRule) { sheet.insertRule(selector + '{' + css + '}', key.length); } else if (sheet.addRule) { sheet.addRule(selector, css, key.length); } };
  18. module.exports = function (selector, styles) { var css = parseStyles(styles);

    var sheets = document.styleSheets; var s = sheets[sheets.length - 1]; var key = s.cssRules ? s.cssRules: s.rules; if (s.insertRule) { sheet.insertRule(selector + '{' + css + '}', key.length); } else if (sheet.addRule) { sheet.addRule(selector, css, key.length); } };
  19. module.exports = function (selector, styles) { var css = parseStyles(styles);

    var sheets = document.styleSheets; var s = sheets[sheets.length - 1]; var key = s.cssRules ? s.cssRules: s.rules; if (s.insertRule) { sheet.insertRule(selector + '{' + css + '}', key.length); } else if (sheet.addRule) { sheet.addRule(selector, css, key.length); } };
  20. module.exports = function (selector, styles) { var css = parseStyles(styles);

    var sheets = document.styleSheets; var s = sheets[sheets.length - 1]; var key = s.cssRules ? s.cssRules: s.rules; if (s.insertRule) { sheet.insertRule(selector + '{' + css + '}', key.length); } else if (sheet.addRule) { sheet.addRule(selector, css, key.length); } };
  21. function build () { var pkg = require('./package.json'); return browserify('./src/lib.js')

    .bundle({ debug: true, standalone: 'lib' }) .pipe(source('lib.js')) .pipe(streamify(header(ext, { pkg: pkg }))) .pipe(gulp.dest('./dist')) .pipe(streamify(rename('lib.min.js'))) .pipe(streamify(uglify())) .pipe(streamify(header(min, { pkg: pkg }))) .pipe(streamify(size())) .pipe(gulp.dest('./dist')); }
  22. function build () { var pkg = require('./package.json'); return browserify('./src/lib.js')

    .bundle({ debug: true, standalone: 'lib' }) .pipe(source('lib.js')) .pipe(streamify(header(ext, { pkg: pkg }))) .pipe(gulp.dest('./dist')) .pipe(streamify(rename('lib.min.js'))) .pipe(streamify(uglify())) .pipe(streamify(header(min, { pkg: pkg }))) .pipe(streamify(size())) .pipe(gulp.dest('./dist')); }
  23. function build () { var pkg = require('./package.json'); return browserify('./src/lib.js')

    .bundle({ debug: true, standalone: 'lib' }) .pipe(source('lib.js')) .pipe(streamify(header(ext, { pkg: pkg }))) .pipe(gulp.dest('./dist')) .pipe(streamify(rename('lib.min.js'))) .pipe(streamify(uglify())) .pipe(streamify(header(min, { pkg: pkg }))) .pipe(streamify(size())) .pipe(gulp.dest('./dist')); }
  24. function build () { var pkg = require('./package.json'); return browserify('./src/lib.js')

    .bundle({ debug: true, standalone: 'lib' }) .pipe(source('lib.js')) .pipe(streamify(header(ext, { pkg: pkg }))) .pipe(gulp.dest('./dist')) .pipe(streamify(rename('lib.min.js'))) .pipe(streamify(uglify())) .pipe(streamify(header(min, { pkg: pkg }))) .pipe(streamify(size())) .pipe(gulp.dest('./dist')); }
  25. function build () { var pkg = require('./package.json'); return browserify('./src/lib.js')

    .bundle({ debug: true, standalone: 'lib' }) .pipe(source('lib.js')) .pipe(streamify(header(ext, { pkg: pkg }))) .pipe(gulp.dest('./dist')) .pipe(streamify(rename('lib.min.js'))) .pipe(streamify(uglify())) .pipe(streamify(header(min, { pkg: pkg }))) .pipe(streamify(size())) .pipe(gulp.dest('./dist')); }
  26. function build () { var pkg = require('./package.json'); return browserify('./src/lib.js')

    .bundle({ debug: true, standalone: 'lib' }) .pipe(source('lib.js')) .pipe(streamify(header(ext, { pkg: pkg }))) .pipe(gulp.dest('./dist')) .pipe(streamify(rename('lib.min.js'))) .pipe(streamify(uglify())) .pipe(streamify(header(min, { pkg: pkg }))) .pipe(streamify(size())) .pipe(gulp.dest('./dist')); }
  27. function build () { var pkg = require('./package.json'); return browserify('./src/lib.js')

    .bundle({ debug: true, standalone: 'lib' }) .pipe(source('lib.js')) .pipe(streamify(header(ext, { pkg: pkg }))) .pipe(gulp.dest('./dist')) .pipe(streamify(rename('lib.min.js'))) .pipe(streamify(uglify())) .pipe(streamify(header(min, { pkg: pkg }))) .pipe(streamify(size())) .pipe(gulp.dest('./dist')); }
  28. function build () { var pkg = require('./package.json'); return browserify('./src/lib.js')

    .bundle({ debug: true, standalone: 'lib' }) .pipe(source('lib.js')) .pipe(streamify(header(ext, { pkg: pkg }))) .pipe(gulp.dest('./dist')) .pipe(streamify(rename('lib.min.js'))) .pipe(streamify(uglify())) .pipe(streamify(header(min, { pkg: pkg }))) .pipe(streamify(size())) .pipe(gulp.dest('./dist')); }
  29. function build () { var pkg = require('./package.json'); return browserify('./src/lib.js')

    .bundle({ debug: true, standalone: 'lib' }) .pipe(source('lib.js')) .pipe(streamify(header(ext, { pkg: pkg }))) .pipe(gulp.dest('./dist')) .pipe(streamify(rename('lib.min.js'))) .pipe(streamify(uglify())) .pipe(streamify(header(min, { pkg: pkg }))) .pipe(streamify(size())) .pipe(gulp.dest('./dist')); }
  30. function build () { var pkg = require('./package.json'); return browserify('./src/lib.js')

    .bundle({ debug: true, standalone: 'lib' }) .pipe(source('lib.js')) .pipe(streamify(header(ext, { pkg: pkg }))) .pipe(gulp.dest('./dist')) .pipe(streamify(rename('lib.min.js'))) .pipe(streamify(uglify())) .pipe(streamify(header(min, { pkg: pkg }))) .pipe(streamify(size())) .pipe(gulp.dest('./dist')); }
  31. function build () { var pkg = require('./package.json'); return browserify('./src/lib.js')

    .bundle({ debug: true, standalone: 'lib' }) .pipe(source('lib.js')) .pipe(streamify(header(ext, { pkg: pkg }))) .pipe(gulp.dest('./dist')) .pipe(streamify(rename('lib.min.js'))) .pipe(streamify(uglify())) .pipe(streamify(header(min, { pkg: pkg }))) .pipe(streamify(size())) .pipe(gulp.dest('./dist')); }
  32. gulp.task('watch', function() { var pattern = { glob: 'src/**/*.js' };

    watch(pattern, function () { gulp.start('build'); }); });
  33. gulp.task('watch', function() { var pattern = { glob: 'src/**/*.js' };

    watch(pattern, function () { gulp.start('build'); }); });
  34. gulp.task('watch', function() { var pattern = { glob: 'src/**/*.js' };

    watch(pattern, function () { gulp.start('build'); }); });
  35. gulp.task('watch', function() { var pattern = { glob: 'src/**/*.js' };

    watch(pattern, function () { gulp.start('build'); }); });
  36. gulp.task('bump-only', function () { // major.minor.patch var bumpType = process.env.BUMP

    || 'patch'; ! return gulp.src(['./package.json', './bower.json']) .pipe(bump({ type: bumpType })) .pipe(gulp.dest('./')); }); ! gulp.task('bump', ['bump-only'], build);
  37. gulp.task('bump-only', function () { // major.minor.patch var bumpType = process.env.BUMP

    || 'patch'; ! return gulp.src(['./package.json', './bower.json']) .pipe(bump({ type: bumpType })) .pipe(gulp.dest('./')); }); ! gulp.task('bump', ['bump-only'], build);
  38. gulp.task('bump-only', function () { // major.minor.patch var bumpType = process.env.BUMP

    || 'patch'; ! return gulp.src(['./package.json', './bower.json']) .pipe(bump({ type: bumpType })) .pipe(gulp.dest('./')); }); ! gulp.task('bump', ['bump-only'], build);
  39. gulp.task('bump-only', function () { // major.minor.patch var bumpType = process.env.BUMP

    || 'patch'; ! return gulp.src(['./package.json', './bower.json']) .pipe(bump({ type: bumpType })) .pipe(gulp.dest('./')); }); ! gulp.task('bump', ['bump-only'], build);
  40. gulp.task('bump-only', function () { // major.minor.patch var bumpType = process.env.BUMP

    || 'patch'; ! return gulp.src(['./package.json', './bower.json']) .pipe(bump({ type: bumpType })) .pipe(gulp.dest('./')); }); ! gulp.task('bump', ['bump-only'], build);
  41. gulp.task('bump-only', function () { // major.minor.patch var bumpType = process.env.BUMP

    || 'patch'; ! return gulp.src(['./package.json', './bower.json']) .pipe(bump({ type: bumpType })) .pipe(gulp.dest('./')); }); ! gulp.task('bump', ['bump-only'], build);
  42. gulp.task('tag', ['bump'], function () { var pkg = require('./package.json'); var

    v = 'v' + pkg.version; var message = 'Release ' + v; ! return gulp.src('./') .pipe(git.commit(message)) .pipe(git.tag(v, message)) .pipe(git.push('origin', 'master', '--tags')) .pipe(gulp.dest('./')); });
  43. gulp.task('tag', ['bump'], function () { var pkg = require('./package.json'); var

    v = 'v' + pkg.version; var message = 'Release ' + v; ! return gulp.src('./') .pipe(git.commit(message)) .pipe(git.tag(v, message)) .pipe(git.push('origin', 'master', '--tags')) .pipe(gulp.dest('./')); });
  44. gulp.task('tag', ['bump'], function () { var pkg = require('./package.json'); var

    v = 'v' + pkg.version; var message = 'Release ' + v; ! return gulp.src('./') .pipe(git.commit(message)) .pipe(git.tag(v, message)) .pipe(git.push('origin', 'master', '--tags')) .pipe(gulp.dest('./')); });
  45. gulp.task('tag', ['bump'], function () { var pkg = require('./package.json'); var

    v = 'v' + pkg.version; var message = 'Release ' + v; ! return gulp.src('./') .pipe(git.commit(message)) .pipe(git.tag(v, message)) .pipe(git.push('origin', 'master', '--tags')) .pipe(gulp.dest('./')); });
  46. gulp.task('tag', ['bump'], function () { var pkg = require('./package.json'); var

    v = 'v' + pkg.version; var message = 'Release ' + v; ! return gulp.src('./') .pipe(git.commit(message)) .pipe(git.tag(v, message)) .pipe(git.push('origin', 'master', '--tags')) .pipe(gulp.dest('./')); });
  47. gulp.task('tag', ['bump'], function () { var pkg = require('./package.json'); var

    v = 'v' + pkg.version; var message = 'Release ' + v; ! return gulp.src('./') .pipe(git.commit(message)) .pipe(git.tag(v, message)) .pipe(git.push('origin', 'master', '--tags')) .pipe(gulp.dest('./')); });
  48. gulp.task('tag', ['bump'], function () { var pkg = require('./package.json'); var

    v = 'v' + pkg.version; var message = 'Release ' + v; ! return gulp.src('./') .pipe(git.commit(message)) .pipe(git.tag(v, message)) .pipe(git.push('origin', 'master', '--tags')) .pipe(gulp.dest('./')); });
  49. var cp = require('child_process'); var spawn = cp.spawn; ! gulp.task('npm',['tag'],function(done){

    spawn('npm', ['publish'], { stdio: 'inherit' }).on('close', done); });
  50. var cp = require('child_process'); var spawn = cp.spawn; ! gulp.task('npm',['tag'],function(done){

    spawn('npm', ['publish'], { stdio: 'inherit' }).on('close', done); });
  51. var cp = require('child_process'); var spawn = cp.spawn; ! gulp.task('npm',['tag'],function(done){

    spawn('npm', ['publish'], { stdio: 'inherit' }).on('close', done); });
  52. var cp = require('child_process'); var spawn = cp.spawn; ! gulp.task('npm',['tag'],function(done){

    spawn('npm', ['publish'], { stdio: 'inherit' }).on('close', done); });
  53. var doc = global.document; var tag = 'iframe'; function poser

    (type) { var frame = doc.createElement(tag); frame.style.display = 'none'; doc.body.appendChild(frame); return frame.contentWindow[type]; } module.exports = poser;
  54. var doc = global.document; var tag = 'iframe'; function poser

    (type) { var frame = doc.createElement(tag); frame.style.display = 'none'; doc.body.appendChild(frame); return frame.contentWindow[type]; } module.exports = poser;
  55. var doc = global.document; var tag = 'iframe'; function poser

    (type) { var frame = doc.createElement(tag); frame.style.display = 'none'; doc.body.appendChild(frame); return frame.contentWindow[type]; } module.exports = poser;
  56. var doc = global.document; var tag = 'iframe'; function poser

    (type) { var frame = doc.createElement(tag); frame.style.display = 'none'; doc.body.appendChild(frame); return frame.contentWindow[type]; } module.exports = poser;
  57. var doc = global.document; var tag = 'iframe'; function poser

    (type) { var frame = doc.createElement(tag); frame.style.display = 'none'; doc.body.appendChild(frame); return frame.contentWindow[type]; } module.exports = poser;
  58. var vm = require('vm'); function poser (type) { var box

    = {}; var code = 'stolen=' + type; vm.runInNewContext(code, box, 'vm'); return box.stolen; } module.exports = poser;
  59. var vm = require('vm'); function poser (type) { var box

    = {}; var code = 'stolen=' + type; vm.runInNewContext(code, box, 'vm'); return box.stolen; } module.exports = poser;
  60. var vm = require('vm'); function poser (type) { var box

    = {}; var code = 'stolen=' + type; vm.runInNewContext(code, box, 'vm'); return box.stolen; } module.exports = poser;
  61. var vm = require('vm'); function poser (type) { var box

    = {}; var code = 'stolen=' + type; vm.runInNewContext(code, box, 'vm'); return box.stolen; } module.exports = poser;
  62. var vm = require('vm'); function poser (type) { var box

    = {}; var code = 'stolen=' + type; vm.runInNewContext(code, box, 'vm'); return box.stolen; } module.exports = poser;
  63. Client Side On first load GET request established by the

    browser Server-side renders layout and view Client-side controller gets executed
  64. Client Side On navigation - after first load AJAX request

    for partial model Client-side renders view Client-side controller gets executed