js-at-sc



js-at-sc

1 1


js-at-sc

Presentation slides for budapest.js, February 14, 2013.

On Github salomvary / js-at-sc

JavaScript at SoundCloud

budapest.js, February 14, 2013

Márton Salomváry salomvary@soundcloud.com

What is SoundCloud?

The Product(s)

A social sound platform for music & audio creators and consumers.
  • 10 hours of music and audio uploaded every minute.
  • Reaches 180 million people.
  • Present on the web (+mobile), iOS, Android.
  • API, platform integrations (Twitter, FB, Flipboard, etc.)
  • Your app!

The company

  • Launched in 2008
  • Berlin (HQ), London, Sofia, and San Francisco
  • 170 full-time staff, 30 nationalities, still growing

Technology

Past

  • Used to be a huge Rails application.
  • The whole stack went through an evolution.
  • Deconstruction of the Death Star.

Technology

Future

  • Smaller, independent components.
  • Internal HTTP API.
  • Multilingual
    • Ruby
    • JavaScript
    • Go
    • Java
    • Scala
    • Objective-C

Technology

Repositories and files by language

Aaaand JavaScript!

The most relevant projects

  • New SoundCloud - the new frontend
  • Widget - embeddable player
  • Mobile - m.soundcloud.com
  • Deck - tool for content partners

How do we write JavaScript?

  • We ❤ semicolons ;)
  • We ❤ modularization.
  • We ❤ MVC and Backbone.
  • We ❤ writing JavaScript in JavaScript syntax.

Huh, no transpilers?

  • Nope.
  • But:
    • The AMD syntax is ugly.
    • → Generate a wrapper on the server!

The AMD wrapper

The ugly way
define(['foo', 'bar'], function(foo, bar) {

  // stuff..

  return { /* module definition */ };
});
The pretty way
define(function(require, exports, module) {

var foo = require('foo'),
    bar = require('bar');

// stuff..

module.exports = /* module definition */;

});

CommonJS wrapper is generated on the server

Tools

  • Node.js and/or Ruby + Sprockets
  • Development server (run-time rewriting)
  • Build tasks
    • Preprocess (JS, CSS, templates)
    • Optimize
    • Bundle
  • JSHint with custom config

Third party libraries

  • Backbone + Underscore
  • Handlebars
  • jQuery 1.7
  • Resig's class.js
  • SoundManager 2

Our libraries

  • Additions to Backbone
  • Mixin
  • Singleton
  • View
  • Subview for Handlebars

Views, SubViews and Singletons

Template

<button>Play!</button>
<audio></audio>
{{ view 'views/comments' resourceId=id }}

Model and view

var Sound = Model.extend({
  // model implementation
}, {
  hashFn: function(attributes) {
    return attributes.id;
  }
});

var SoundView = View.extend({
  ModelClass: Sound,
  template: require('sound.hbs')
  // view implementation
});

Singleton models and collections

  • new Sound({id:1}) == new Sound({id:1})
  • If already fetched: no need to fetch!
  • Simple reference counting GC.
  • View calls sound.hold() and sound.release()

Testing

  • Tyrtle JS testing framework
  • Nodejs and Phantomjs runners
  • Sinon.js FakeXMLHTTPRequest
  • Selenium browser automation (on the way)
  • Jenkins CI

Exception tracking

  • Errorception.com (great for low traffic)
  • Problems
    • High traffic & diversity
    • Smart grouping of exceptions
    • Ignore by patterns
  • Google Analytics + custom events for statistical trends

Built on this…

The new soundcloud.com

  • 516 js files
  • 42 500 lines of code
  • 186 'vendor' files (64 097 loc)

The frontend

  • Separete, frontend-only codebase.
  • Uses the public API.
  • Created by a team of 6 JS engineers.
  • Took more than a year.

Further reading

And btw,

we are hiring

all kinds of engineers and more!

soundcloud.com/jobs

Thanks!

Márton Salomváry salomvary@soundcloud.com