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

The Bits Behind JS Bin

The Bits Behind JS Bin

The story behind JS Bin, how it came to be, why it moved to Node, the drivers and some of the challenges in running the app.

Remy Sharp

June 10, 2014
Tweet

More Decks by Remy Sharp

Other Decks in Technology

Transcript

  1. The Bits
    Behind
    JS Bin
    Remy Sharp — @rem

    View Slide

  2. Hi.
    Mine:
    nodemon
    5minfork.com
    Full Frontal
    Me:
    @rem
    [email protected]
    remysharp.com

    View Slide

  3. JS Bin?

    View Slide

  4. • 415,000 uniques/month (2mil page views)
    • 30-35 queries per second
    • 69,000+ registered users
    • 9.6mil bins in total / 1.5mil "owned" bins
    • 48 timers & lots of iframes!

    View Slide

  5. BACKSTORY

    View Slide

  6. Originally a PHP hack
    • Inspired by XHR insolation issues
    • Proceeded by ugliness (codedumper.com)
    • Tipping point: John Resig's http://ejohn.org/apps/learn/
    • Approximately 4 hours of dev to live

    View Slide

  7. Workshop in Iceland

    View Slide

  8. Code Casting
    I wanted to create

    View Slide

  9. jsconf.eu 2009

    View Slide

  10. Förbind http://forbind.net

    View Slide

  11. View Slide

  12. Pre-decent require

    View Slide

  13. Pre-package knowledge

    View Slide

  14. Straight up nutty

    View Slide

  15. 2 hours later...

    View Slide

  16. View Slide

  17. Förbind: how it works
    express socket.io mongodb ejs
    Tightly coupled collections listening for
    messages, then firing it on all open connections.
    Restart and it all breaks...

    View Slide

  18. April 2012 & @aron

    View Slide

  19. 100%
    JavaScript

    View Slide

  20. View Slide

  21. Pros of Node for JS Bin
    • CodeCasting & live reload (across all platforms)
    • Easy local and dependency free installs
    • Some code reuse, lots of knowledge reuse.

    View Slide

  22. The Spike

    View Slide

  23. Thank you Boris Grishenko

    View Slide

  24. Author JS Bin
    XHR save
    on keypress
    DB
    spike.js
    update
    event
    IE8
    Chrome
    xbox
    iOS
    Firefox
    OS
    etc
    SSE push
    The Spike

    View Slide

  25. • Client saves on keypress
    • Server on save triggers "spike update" event with
    bin passed to event
    • Spike searches for sessions interested in that
    bin, and sends the updated panel

    View Slide

  26. All authored content is streamable
    •CodeCasting is easy
    •LiveReload is easy
    •Live injection into PhoneGap is easy

    View Slide

  27. Good Side Effect
    • XSS recently fixed using postMessage & run.jsbin.com
    • IE7 doesn't support postMessage
    • But IE7 does LiveReload - so IE still works & securely

    View Slide

  28. View Slide

  29. View Slide

  30. if (res.connection.writable === false) {
    // remove cached connection
    }
    Is the connection open?

    View Slide

  31. Testing event source
    • Sadly no devtools (http://crbug.com/254973)
    • curl --header "Accept: text/event-stream"

    View Slide

  32. View Slide

  33. No WebSockets?
    •EventSource is polyfilled only with JS
    •IE6-9
    •Android Browser

    View Slide

  34. View Slide

  35. Local installs
    • Always possible since day #1 on github
    • Now via `npm install -g jsbin`
    • Windows support is (now) pretty solid

    View Slide

  36. Database upgrades via npm
    • Package.json
    "scripts": {
    "install": "build/install.js",
    "preupdate": "build/pre-update.js",
    "postupdate": "build/post-update.js"
    },
    • Pre-update - saves current version
    • Post-update - uses semver & checks upgrade//*.sql

    View Slide

  37. Dependency free
    •USB contains Node binaries for all
    platforms, code & dependancies
    •Saves to raw HTML files on USB stick
    •For teaching in strict tech environment

    View Slide

  38. todo
    •Add update-notifier for prompted updates
    •Get visibility on local installs
    •Release to npm frequently

    View Slide

  39. Features

    View Slide

  40. View Slide

  41. View Slide

  42. • Paid/donated
    • Alternative domain (ie. jsbin.leftlogic.com)
    • Each dev runs under rem.jsbin.leftlogic.com
    • Now we can remotely view each other's work
    ngrok

    View Slide

  43. Production

    View Slide

  44. scripts.json

    View Slide

  45. index template

    View Slide

  46. Grunt build generates
    concat & uglified.
    Triggered by...

    View Slide

  47. .git/hooks/post-merge
    [email protected]:/WWW/jsbin$ git pull
    remote: Counting objects: 19, done.
    remote: Compressing objects: 100% (7/7), done.
    remote: Total 11 (delta 8), reused 7 (delta 4)
    Unpacking objects: 100% (11/11), done.
    From git://github.com/remy/jsbin
    a7bf4f8..f99beff master -> origin/master
    * [new branch] feature/menu-update -> origin/feature/menu-up
    Merge made by the 'recursive' strategy.
    test/loop_detection_test.js | 12 +++++++++++-
    1 file changed, 11 insertions(+), 1 deletion(-)
    rebuild jsbin.js? [Y/n] y
    building public js
    Running "concat:dist" (concat) task
    File "public/js/prod/jsbin-3.4.8.js" created.
    Running "concat:runner" (concat) task
    File "public/js/prod/runner-3.4.8.js" created.
    Running "uglify:dist" (uglify) task
    Source Map "public/js/prod/jsbin.map.json" created.
    File "public/js/prod/jsbin-3.4.8.min.js" created.
    Running "uglify:runner" (uglify) task
    File "public/js/prod/runner-3.4.8.min.js" created.
    Done, without errors.
    restart jsbin? [Y/n] y
    restarting forever
    info: Forever restarted processes:
    data: uid command script forever pid logfile

    View Slide

  48. Upstart
    console log
    stop on shutdown
    respawn
    respawn limit 20 5
    post-start script
    # log that we restarted
    logger -is -t "$UPSTART_JOB" ">>>>>>>> jsbin restart"
    # email the last 100 lines from the log
    tail -100 /var/log/upstart/jsbin.log |
    mail -s "ALARM: jsbin restart" [email protected]
    end script
    script
    set -e
    # make sure you only write out to /var/log/upstart/
    exec sudo -u www-data PORT=8000 /usr/local/bin/node /WWW/jsbin/ 2>&1
    end script
    https://github.com/jsbin-org/production/blob/master/apps.jsbin.com/etc/init/jsbin.conf

    View Slide

  49. •URLs - probably not fixable
    •Database choice - fixable hard
    •Database adapter logic - fixable easy
    •Near total lack of tests - fix in progress
    Mistakes

    View Slide

  50. It's hard
    •Memory leaks
    •CPU loops
    •Easy to get lazy

    View Slide

  51. gdb ftw
    http://remysharp.com/2013/09/11/how-i-fixed-an-anonymous-infinite-loop-in-jsbin/

    View Slide

  52. Sustainability: Pro
    • Dropbox support & live syncing
    • Bin playback & annotation
    • Sass, SCSS, smart screenshots...
    • Branded JS Bin's
    ala http://emberjs.jsbin.com

    View Slide


  53. View Slide