Slide 1

Slide 1 text

! ! ! npm install --save bigpipe http://bigpipe.io

Slide 2

Slide 2 text

3rdEden 3rd-Eden arnout.kazemier

Slide 3

Slide 3 text

what is bigpipe And why should you care

Slide 4

Slide 4 text

facebook Introduced it on June 4, 2010 on.fb.me/1kAHLer

Slide 5

Slide 5 text

◅ ▻ # tl;dr

Slide 6

Slide 6 text

} Swaagie Martijn Swaagman 3rd-Eden Arnout Kazemier

Slide 7

Slide 7 text

◅ ▻ # header item list side bar

Slide 8

Slide 8 text

◅ ▻ # pagelet

Slide 9

Slide 9 text

◅ ▻ # page

Slide 10

Slide 10 text

! … ! ! … ! ! … !

Slide 11

Slide 11 text

pipe.arrive("login", { “css":["/b04d448dd7b67c3bdb2a75ff79198c840df88954.css"], “js":[], “processed”:1, “id":"0FWH-EFC8MTOQ-OLXRO9HG5H2-992RO1OR", “rpc":[], “remove":false, “authorized":true, “streaming":false, “data":{} });

Slide 12

Slide 12 text

pipe.arrive("login", { “css":["/b04d448dd7b67c3bdb2a75ff79198c840df88954.css"], “js":[], “processed”:1, “id":"0FWH-EFC8MTOQ-OLXRO9HG5H2-992RO1OR", “rpc":[], “remove":false, “authorized":true, “streaming":false, “data":{} });

Slide 13

Slide 13 text

why What do we gain by adopting this pattern

Slide 14

Slide 14 text

◅ ▻ # front-end/client & render performance JS % % % JS JS

Slide 15

Slide 15 text

◅ ▻ # & & & & & & & & & & & & optimal usage/performance

Slide 16

Slide 16 text

improved perceived performance & time to interact generation latency rendering time

Slide 17

Slide 17 text

perceived performance & time to interact generation latency rendering time

Slide 18

Slide 18 text

developer satisfaction ▶ { }

Slide 19

Slide 19 text

pagelet A small re-usable fragment which contains HTML, CSS and JavaScript

Slide 20

Slide 20 text

◅ ▻ # 'use strict';! ! var Pagelet = require(“bigpipe”).Pagelet;! ! //! // Alternatively, only depend on Pagelet! //! Pagelet = require(“pagelet”);

Slide 21

Slide 21 text

◅ ▻ # var Pagelet = require(“bigpipe”).Pagelet;! ! Pagelet.extend({! //! // Code here! //! }).on(module);

Slide 22

Slide 22 text

◅ ▻ # var asyncthings = require(“./asyncthings”)! , Pagelet = require(“bigpipe”).Pagelet;! ! Pagelet.extend({! get: function get(done) {! asyncthings(function fetched(err, data) {! done(err, { packages: data });! });! }! }).on(module);

Slide 23

Slide 23 text

◅ ▻ # var Pagelet = require(“bigpipe”).Pagelet;! ! Pagelet.extend({! things: require(“./asyncthings”),! get: function get(done) {! this.things(function fetched(err, data) {! done(err, { packages: data });! });! },! ! post: function get(body, files, next) {! this.things(body, function process(err) {! next(err);! });! }! }).on(module);

Slide 24

Slide 24 text

views Multiple built-in template engines supported ◅ ▻ $ npm install --save ejs! ! ..! ! $ vim index.js! ! ———————————————————————————————————————————— ! 'use strict';! ! var Pagelet = require(“bigpipe”).Pagelet;! ! Pagelet.extend({! view: “sidebar.ejs“! }).on(module);

Slide 25

Slide 25 text

views Custom error template when this particular pagelet fails. Can be a different language. ◅ ▻ 'use strict';! ! var Pagelet = require(“bigpipe”).Pagelet;! ! Pagelet.extend({! view: “sidebar.ejs“,! error: “unavailable.jade“! }).on(module);

Slide 26

Slide 26 text

auth Pagelet only shown when authorized ◅ ▻ 'use strict';! ! var Pagelet = require(“bigpipe”).Pagelet;! ! Pagelet.extend({! authorize: function (req, next) {! next(authenticate(req) === true);! }! }).on(module);

Slide 27

Slide 27 text

auth Don’t remove the placeholder from the DOM ◅ ▻ 'use strict';! ! var Pagelet = require(“bigpipe”).Pagelet;! ! Pagelet.extend({! authorize: function (req, next) {! next(authenticate(req) === true);! },! remove: false! }).on(module);

Slide 28

Slide 28 text

rpc Full real-time remote procedure calls ◅ ▻ 'use strict';! ! var Pagelet = require(“bigpipe”).Pagelet! , asyncthings = require(“./asyncthings”);! ! Pagelet.extend({! RPC: [“search“],! search: function search(reply, arg) {! asyncthings(function (err, data) {! reply(err, data);! });! }! }).on(module);

Slide 29

Slide 29 text

styling Name-spacing, pre- processing all happening transparently ◅ ▻ 'use strict';! ! var Pagelet = require(“bigpipe”).Pagelet;! ! Pagelet.extend({! css: “my-file.css“! }).on(module);

Slide 30

Slide 30 text

styling Name-spacing, pre- processing all happening transparently ◅ ▻ ul! &.foo! list-style: none! padding: 0! ! ———————————————————————————————————————————— ! [data-pagelet="sidebar"] ul.foo {! list-style: none;! padding: 0;! }

Slide 31

Slide 31 text

distribute Publish using npm ◅ ▻ 'use strict';! ! var Pagelet = require(“bigpipe”).Pagelet;! ! Pagelet.extend({! view: “view.jade”,! css: “my-file.sass“,! get: function get(done) {! setTimeout(function () {! done(undefined, { packages: 1 });! }, 10);! }! }).on(module);! ! ———————————————————————————————————————————— ! $ npm publish packages-pagelet!

Slide 32

Slide 32 text

distribute Share using npm ◅ ▻ $ npm install packages-pagelet! ! ———————————————————————————————————————————— ! 'use strict';! ! var Page = require(“bigpipe”).Page;! ! Page.extend({! path: “/packages/:name“,! pagelets: {! “packages“: require(“packages-pagelet“)! }! }).on(module);

Slide 33

Slide 33 text

distribute And remix existing pagelets ◅ ▻ $ npm install packages-pagelet! ! ———————————————————————————————————————————— ! 'use strict’;! ! var path = require(“path”)! , Pagelet = require(‘packages-pagelet');! ! //! // Manually export the re-mixed instance! // which has the new custom css.! //! module.exports = Pagelet.extend({! css: path.join(__dirname, ‘custom.styl’)! });

Slide 34

Slide 34 text

much much more ◅ ▻ Pagelet.extend({! streaming: true,! engine: ‘hogan.js’,! query: [‘data.bar.sync.0.foo’],! fragment: fs.readFileSync(‘fragment’),! initialize: function initialize() {! this.debug(‘i broke something’);! },! dependencies: []! }).on(module);

Slide 35

Slide 35 text

client Minimal, transparent framework

Slide 36

Slide 36 text

◅ ▻ # 'use strict';! ! pipe.once(“::render”, function (pagelet) {! //! // You can access the initialised pagelet here! //! });!

Slide 37

Slide 37 text

# 'use strict’;! ! pagelet.render(‘hi’); render Refresh the HTML of every paglet

Slide 38

Slide 38 text

# 'use strict’;! ! pagelet.submit(document.forms[0]); submit Submit a form over the real- time connection

Slide 39

Slide 39 text

# 'use strict';! ! pagelet.search(‘foo’, function (err, row) {! console.log(err, row);! }); rpc Simply call the same method name on the client

Slide 40

Slide 40 text

sandboxing docker like containers for the browser

Slide 41

Slide 41 text

asset loading async css & js

Slide 42

Slide 42 text

page The entry point

Slide 43

Slide 43 text

◅ ▻ # 'use strict';! ! var Page = require(“bigpipe”).Page;

Slide 44

Slide 44 text

◅ ▻ # 'use strict';! ! var Page = require(“bigpipe”).Page;! ! Page.extend({! pagelets: {! “pagelet-1”: “path to pagelet”,! “pagelet-2”: require(“custom-pagelet”)! }! }).on(module);

Slide 45

Slide 45 text

◅ ▻ # 'use strict';! ! var Page = require(“bigpipe”).Page;! ! Page.extend({! pagelets: ”/directory/with/pagelets”! }).on(module);

Slide 46

Slide 46 text

# 'use strict’;! ! var Page = require(‘bigpipe’).Page;! ! Page.extend({! path: “/url/:param/:name”! }).on(module); path smart URL routing

Slide 47

Slide 47 text

# 'use strict’;! ! var Page = require(‘bigpipe’).Page;! ! Page.extend({! path: /^\/foo\/bar/i! }).on(module); path regexp based routing

Slide 48

Slide 48 text

# path xRegExp name based routing 'use strict’;! ! var Page = require(‘bigpipe’).Page;! ! Page.extend({! path: ‘/^\\/(?[\\d\\.]+)\\/foo/'! }).on(module);

Slide 49

Slide 49 text

# 'use strict’;! ! var Page = require(‘bigpipe’).Page;! ! Page.extend({! path: “/“,! view: “index.ejs”! }).on(module); view The first chunk and placeholders

Slide 50

Slide 50 text

# ! ! ! <%- bootstrap %>! ! !
! ! ! ! ! ! ! ! ! ! ! view Manually include the {bootstrap} code

Slide 51

Slide 51 text

# 'use strict’;! ! var Page = require(‘bigpipe’).Page;! ! Page.extend({! path: “/“,! view: “index.ejs”,! authorize: function auth(req, next) {! next(false);! }! }).on(module); auth Authorize access to pages.

Slide 52

Slide 52 text

# 'use strict’;! ! var Page = require(‘bigpipe’).Page;! ! Page.extend({! path: “/“,! view: “index.ejs”,! mode: “async”,! ! pagelets: {! “name”: “path to pagelet”,! “another”: require(“custom-pagelet”)! }! }).on(module); mode Different pagelet render modes.

Slide 53

Slide 53 text

# 'use strict’;! ! var Page = require(‘bigpipe’).Page;! ! Page.extend({! path: “/“,! view: “index.ejs”,! mode: “async”,! ! pagelets: {! “name”: “path to pagelet”,! “another”: require(“custom-pagelet”)! }! }).on(module); mode async: fully async, unordered rendering

Slide 54

Slide 54 text

# 'use strict’;! ! var Page = require(‘bigpipe’).Page;! ! Page.extend({! path: “/“,! view: “index.ejs”,! mode: “pipeline”,! ! pagelets: {! “name”: “path to pagelet”,! “another”: require(“custom-pagelet”)! }! }).on(module); mode pipeline: render in the specified order.

Slide 55

Slide 55 text

# 'use strict’;! ! var Page = require(‘bigpipe’).Page;! ! Page.extend({! path: “/“,! view: “index.ejs”,! mode: “sync”,! ! pagelets: {! “name”: “path to pagelet”,! “another”: require(“custom-pagelet”)! }! }).on(module); mode sync: single flush, no fancy pancy rendering

Slide 56

Slide 56 text

# 'use strict’;! ! var Page = require(‘bigpipe’).Page;! ! Page.extend({! statusCode: 301,! method: ‘GET, POST, HEAD’,! contentType: ‘custom/html’,! data: { template: ‘data’ },! parsers: {},! charset: ‘UTF-7’,! dependencies: [],! initialize: function () {}! }).on(module); much much more

Slide 57

Slide 57 text

putting it all together Creating your first BigPipe instance

Slide 58

Slide 58 text

◅ ▻ # var BigPipe = require(“bigpipe”);! ! var bigpipe = BigPipe.createServer(8080, {! pages: __dirname +’/pages’,! dist: __dirname +’/dist’! });

Slide 59

Slide 59 text

◅ ▻ # var BigPipe = require(“bigpipe”);! ! var bigpipe = BigPipe.createServer(8080, {! pages: [Page, Page, Page, Page, Page]! dist: __dirname +’/dist’! });

Slide 60

Slide 60 text

◅ ▻ # var BigPipe = require(“bigpipe”);! ! var bigpipe = BigPipe.createServer(8080, {! pages: __dirname +’/pages’,! dist: __dirname +’/dist’! });! ! bigpipe.define([Page, Page, Page]);! bigpipe.define(__dirname +’/pages’);

Slide 61

Slide 61 text

◅ ▻ # var BigPipe = require(“bigpipe”);! ! var bigpipe = BigPipe.createServer(443, {! pages: __dirname +’/pages’,! dist: __dirname +’/dist’,! ! key: fs.readFileSync(‘ssl.key’),! cert: fs.readFileSync(‘cert.key’)! });

Slide 62

Slide 62 text

◅ ▻ # var BigPipe = require(“bigpipe”);! ! var bigpipe = BigPipe.createServer(443, {! pages: __dirname +’/pages’,! dist: __dirname +’/dist’,! ! key: fs.readFileSync(‘ssl.key’),! cert: fs.readFileSync(‘cert.key’),! redirect: 80! });

Slide 63

Slide 63 text

◅ ▻ # var BigPipe = require(“bigpipe”);! ! var bigpipe = BigPipe.createServer(443, {! key: fs.readFileSync(‘ssl.key’),! cert: fs.readFileSync(‘cert.key’),! spdy: { /* SPDY configuration */ }! });

Slide 64

Slide 64 text

# var BigPipe = require(“bigpipe”);! ! var bigpipe = BigPipe.createServer(8080, {! pages: __dirname +’/pages’,! dist: __dirname +’/dist’,! transformer: ‘engine.io’,! parser: ‘JSON’! }); primus The transforming real-time engine

Slide 65

Slide 65 text

primus Why is so damn _awesome_ - seamless switching
 
 - additional fixes - plugin support - custom encoders - reconnect that works - offline detection - build with ♥ engine.io, sockjs, socket.io, websockets and browserchannel

Slide 66

Slide 66 text

primus started out as a wrapper around engine.io

Slide 67

Slide 67 text

primus eventually got refactored to support more frameworks

Slide 68

Slide 68 text

primus and finally it got named as we know it

Slide 69

Slide 69 text

compiler optimising dependencies

Slide 70

Slide 70 text

# status page custom and default error pages 'use strict’;! ! var Page = require(‘bigpipe’).Page;! ! Page.extend({! path: ‘/404’,! statusCode: 404,! view: ‘404.ejs’! }).on(module);! ! ————————————————————————————————————————————! 'use strict’;! ! var Page = require(‘bigpipe’).Page;! ! Page.extend({! path: ‘/500’,! statusCode: 500,! view: ‘500.ejs’! }).on(module);

Slide 71

Slide 71 text

# plugins a great way to extend BigPipe 'use strict’;! ! bigpipe.use('ack', {! // Only ran on the server.! server: function (bigpipe, options) {},! ! // Runs on the client, it's automatically ! // bundled.! client: function (bigpipe, options) {},! ! // Optional library that needs to be! // bundled on the client! library: ‘',! ! // Optional plugin specific options, will! // be merged with Bigpipe.options! options: {}! });

Slide 72

Slide 72 text

# middleware for the sake of compatibility var BigPipe = require(“bigpipe”)! , serve = require(“static-serve”);! ! var bigpipe = BigPipe.createServer(8080, {! pages: __dirname +’/pages’,! dist: __dirname +’/dist’! });! ! bigpipe.before(‘static’, serve());

Slide 73

Slide 73 text

# middleware can be proxied to Primus var BigPipe = require(“bigpipe”)! , serve = require(“static-serve”);! ! var bigpipe = BigPipe.createServer(8080, {! pages: __dirname +’/pages’,! dist: __dirname +’/dist’! });! ! bigpipe.before(‘static’, serve(), {! primus: true! });

Slide 74

Slide 74 text

# middleware can be enabled/disabled at will var BigPipe = require(“bigpipe”)! , serve = require(“static-serve”);! ! var bigpipe = BigPipe.createServer(8080, {! pages: __dirname +’/pages’,! dist: __dirname +’/dist’! });! ! bigpipe.use(‘static’, serve());! bigpipe.disable(‘static’);! bigpipe.enable(‘static’);! bigpipe.remove(‘static’);! bigpipe.before(‘static’);

Slide 75

Slide 75 text

live demo *crosses fingers* ▶ !

Slide 76

Slide 76 text

browsenpm.org Open Source example of a BigPipe powered site

Slide 77

Slide 77 text

public package page

Slide 78

Slide 78 text

browsenpm.org github.com/nodejitsu/browsenpm.org ! github.com/nodejitsu/packages-pagelet github.com/nodejitsu/npm-dependencies-pagelet github.com/nodejitsu/npm-documentation-pagelet github.com/nodejitsu/registry-status-pagelet github.com/nodejitsu/npm-search-pagelet

Slide 79

Slide 79 text

future goals Quicklining or “turbo links”, pagelet & page cache, recursive/ nested pagelets, streaming/diff-able assets, more tests and benchmarking.

Slide 80

Slide 80 text

That’s all I got! Q/A: Tweet me @3rdEden or create github issues ;-) 3rdEden 3rd-Eden arnout.kazemier

Slide 81

Slide 81 text

bigpipe.io ! pagelet: github.com/bigpipe/paglet bigpipe: github.com/bigpipe/bigpipe pipe.js: github.com/bigpipe/pipe.js ! primus: github.com/primus/primus browsenpm: browsenpm.org 3rdEden 3rd-Eden arnout.kazemier