As our team’s grown up at Skillshare, we’ve had to learn quickly how to architect an engineering front-end that scales with our product. We’re proud of the fast-paced, but robust engineering culture that’s emerged, and I’d like to take the opportunity to share a high-level picture of our stack in a hope to surface some actionable takeaways, or if nothing more, offer an insightful view into our front-end world.
The Aesthetic Front-End
Writing CSS in a way that keeps files small and modular has been key to how this side of the FE has scaled with us, and thinking objectively about CSS has played a key role in preserving maintainability.
Our primary framework of choice to uphold these principles is Sass. Another popular alternative is Less, but ultimately frameworks like these promote two important factors; modularity and re-usability, which allow us to define a very simple rule – that any page on Skillshare should only serve up the CSS it needs. This may seem obvious, but it’s a rule that underpins hundreds of the CSS decisions we make daily, so it’s an important one to get right.
Example: The Skillshare Homepage
Our backend application works on a controller/view pattern. So when a user visits skillshare.com, this request maps to our application route, site/index and serves the homepage.
[code lang=”php”]
‘/’ => ‘site/index’,
[/code]
We thought this pattern would also be a scalable way to also map to our CSS. So when a user hits the site/index route, we know to serve up our index.css file located in the css/site/ directory.
This index.css file itself then houses a series of partial and component files specific to the homepage, all managed and packaged in development with Sass.
[code lang=”css”]
@import “../../base/variables”;
@import “../../base/mixins”;
@import “signup-form”;
#homepage {
//
}
[/code]
Of course, we still have a shared CSS file that’s always loaded alongside the specific page (responsible for more global attributes), but making this distinction has proved a powerful way to keep our files small and our application modular.
The Functional Front-End
When it comes to JavaScript, maintainability is everything to us. Indeed – we’re real advocates of performance too, but when shaping a fast-moving product, having adaptable code allows us to move fast whilst preserving a robust code-base.
Core Libs
Require.js helps to keep our code modular, giving us the ability to configure our JS application to handle libraries and dependencies without the overhead of managing JS files in the DOM.
We then tag-team Require with Backbone.js to compartmentalize our pages and site components as lightweight views, and to sync with our backend through models, all of which are treated as dependencies with Require.
[code lang=”js”]
define([
‘core/src/views/video-player-popup-view’
], function (VideoPlayerPopupView) {
var HomepagePageView = Backbone.View.extend({
el: ‘#homepage’,
events: {},
initialize: function() { new VideoPlayerPopupView(); },
});
new HomepagePageView(); return HomepagePageView; }); [/code]
Require also comes packaged with optimization tools that preps our application for deployment. We have our own compression wrapper around these tools that keeps our CSS and other libs separate, but we’ve found this level of optimization beneficial to both our workflow and to the efficiency of our production source.
Notable Secondary Libs
It goes without saying that our FE is also supported heavily with jQuery, but there are other libs that are worth a mention too:
- Moment.js – Date handling, but awesome.
- Backbone.Stickit – A model-view binding plugin for Backbone.
- MapBox – A flexible alternative to Google.
I hope that this paints a high-level picture of how our front-end fits together. With many new libraries in the headlines, it’s actually not important to us which libraries or frameworks we adopt. What’s most important for us is to align our day-to-day decisions with the principles of maintainability. This simple notion itself preserves our codebase and our engineering culture.
What’s interesting, is how this movement at the front-end has also inspired discussions about how to better communicate with the backend. Issues such as shared templates and persistent model data are topics we look forward to posting here in the future.
Love engineering the front-end? Join us to create a product with world-changing impact.
Written by: