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

BigPipe

Arnout Kazemier
May 06, 2014
1.2k

 BigPipe

This talk introduced a brand new framework for Node.js which is based on the Blog post that facebook did back in 2010.

BigPipe allows you to slice up your side in re-usable components called pagelets which are flushed to the page fully async. These components can be released in to npm and re-mixed. Creating a full front to back npm experience.

Checkout the documentation on http://bigpipe.io

Arnout Kazemier

May 06, 2014
Tweet

Transcript

  1. <html> <head> <meta charset=“utf-8”> <script src=“{bigpipe.js}”></script> <noscript> <meta http-equiv=“refresh” content=“/?no_pagelet_js=1”>

    </noscript> ! … ! </head> <body> ! … ! <header data-pagelet=“header”></header> <section data-pagelet=“feed”></section> <footer data-pagelet=“recommended”></section> ! … ! </body>
  2. <code data-pagelet-fragment="login" style=“display:none"> <!-- <section class="row"><form method="post" action="/" class="fivecol"><h1><img src="/npmjitsu.png"

    width="90%" alt="Login to your private npm registry”/> .. </form></section> --></code> <script> pipe.arrive("login", { “css":["/b04d448dd7b67c3bdb2a75ff79198c840df88954.css"], “js":[], “processed”:1, “id":"0FWH-EFC8MTOQ-OLXRO9HG5H2-992RO1OR", “rpc":[], “remove":false, “authorized":true, “streaming":false, “data":{} }); </script>
  3. <code data-pagelet-fragment="login" style=“display:none"> <!-- <section class="row"><form method="post" action="/" class="fivecol"><h1><img src="/npmjitsu.png"

    width="90%" alt="Login to your private npm registry”/> .. </form></section> --></code> <script> pipe.arrive("login", { “css":["/b04d448dd7b67c3bdb2a75ff79198c840df88954.css"], “js":[], “processed”:1, “id":"0FWH-EFC8MTOQ-OLXRO9HG5H2-992RO1OR", “rpc":[], “remove":false, “authorized":true, “streaming":false, “data":{} }); </script>
  4. ◅ ▻ # & & & & & & &

    & & & & & optimal usage/performance
  5. ◅ ▻ # 'use strict';! ! var Pagelet = require(“bigpipe”).Pagelet;!

    ! //! // Alternatively, only depend on Pagelet! //! Pagelet = require(“pagelet”);
  6. ◅ ▻ # 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);
  7. ◅ ▻ # 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);
  8. 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);
  9. 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);
  10. 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);
  11. 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);
  12. 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);
  13. styling Name-spacing, pre- processing all happening transparently ◅ ▻ 'use

    strict';! ! var Pagelet = require(“bigpipe”).Pagelet;! ! Pagelet.extend({! css: “my-file.css“! }).on(module);
  14. 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;! }
  15. 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!
  16. 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);
  17. 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’)! });
  18. 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);
  19. ◅ ▻ # 'use strict';! ! pipe.once(“<name>::render”, function (pagelet) {!

    //! // You can access the initialised pagelet here! //! });!
  20. # 'use strict';! ! pagelet.search(‘foo’, function (err, row) {! console.log(err,

    row);! }); rpc Simply call the same method name on the client
  21. ◅ ▻ # 'use strict';! ! var Page = require(“bigpipe”).Page;!

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

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

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

    path: /^\/foo\/bar/i! }).on(module); path regexp based routing
  25. # path xRegExp name based routing 'use strict’;! ! var

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

    path: “/“,! view: “index.ejs”! }).on(module); view The first chunk and placeholders
  27. # <!doctype html>! <html class="no-js">! <head>! <%- bootstrap %>! </head>!

    <body>! <div data-pagelet="sidebar"></div>! ! <section class="documentation">! <article data-pagelet=“bigpipe">! </article>! <article data-pagelet=“pagelet">! </article>! <article data-pagelet=“client">! </article>! </section>! </body>! </html> view Manually include the {bootstrap} code
  28. # '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.
  29. # '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.
  30. # '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
  31. # '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.
  32. # '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
  33. # '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
  34. ◅ ▻ # var BigPipe = require(“bigpipe”);! ! var bigpipe

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

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

    = BigPipe.createServer(8080, {! pages: __dirname +’/pages’,! dist: __dirname +’/dist’! });! ! bigpipe.define([Page, Page, Page]);! bigpipe.define(__dirname +’/pages’);
  37. ◅ ▻ # 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’)! });
  38. ◅ ▻ # 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! });
  39. ◅ ▻ # var BigPipe = require(“bigpipe”);! ! var bigpipe

    = BigPipe.createServer(443, {! key: fs.readFileSync(‘ssl.key’),! cert: fs.readFileSync(‘cert.key’),! spdy: { /* SPDY configuration */ }! });
  40. # 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
  41. 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
  42. # 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);
  43. # 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: {}! });
  44. # 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());
  45. # 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! });
  46. # 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’);
  47. future goals Quicklining or “turbo links”, pagelet & page cache,

    recursive/ nested pagelets, streaming/diff-able assets, more tests and benchmarking.
  48. That’s all I got! Q/A: Tweet me @3rdEden or create

    github issues ;-) 3rdEden 3rd-Eden arnout.kazemier