| OEP | :doc:`OEP-11 </oeps/oep-0011>` |
| Title | Front End Best Practices |
| Last Modified | 2016-10-19 |
| Author | Andy Armstrong <andya@edx.org> |
| Arbiter | TBD |
| Status | Draft |
| Type | Best Practice |
| Created | 2016-10-19 |
This document describes the best practices for developing front end applications and components for Open edX. It covers the techniques and approaches that are currently recommended, as well as the suggested technologies and libraries that should be used.
The front end landscape is large, confusing and constantly changing. A good place to get an overview of the industry's current best practices is The State of JavaScript 2016 Survey.
Open edX is a large platform that provides its front end functionality in a variety of ways. The major applications (Studio, LMS, Insights, Otto) are built as Django views that return rendered pages consisting of HTML, CSS and JavaScript. In addition, components can be created with XBlocks which use Python code to render themselves as HTML fragments along with their CSS and JavaScript dependencies.
Within this document, the phrase "front end" is used to mean any part of the platform that is shown to users. This phrase is a little confusing as the front end is generated by Django views which are implemented as Python code running on a "back end" server. The true back end is the APIs that the front end communicates with to access and update information on behalf of the user.
Note: this document provides many recommendations which are provided as guides when developing new front ends. It is important to always use the best tool for the job, so there will be situations where an alternative approach or technology should be adopted.
Use server-side rendering whenever possible
Rationale: Server-side rendering gives the content to the user immediately without requiring additional round-trips. This can make for large performance improvements on slow networks or mobile devices.
When a dynamic client-side experience is required, then the server-side page should include JavaScript code along with the HTML. See the technical recommendations below for more detail.
Front-ends should be self-contained
Rationale: Front end applications require a variety of types of assets that need to be managed together, including code, styles, templates, and images. For Django apps and XBlocks, all of these assets should live within the app's or block's own directory rather than being located in shared locations within the consuming application. Ideally, apps or blocks should live in their own repository and should be pip installed into and should be pip installed into the main application.
Designs should be built upon patterns from the edX Pattern Library
Rationale: The edX Pattern Library is a collection of web application components and visual styles that can be used to develop UIs that are consistent with the edX platform. Using the pattern library ensures that web applications follow best practices for user experience, theming, and accessibility.
You can learn more about building user interfaces with the pattern library in the Developer's Guide chapter Developing User Interfaces.
Front-ends should consume and extract reusable UI components
Rationale: when developing new applications, developers should prefer reuse of existing components over building custom front end logic. If a new component is required, it should be built as a new reusable addition to the edX UI Toolkit, based upon patterns from the edX Pattern Library. This ensures that future development can reuse this component, while also standardizing how it behaves for the user in terms of user interface, accessibility, theming and so on.
Front-ends should manage history consistently
Rationale: it is important that rich-client applications provide a consistent history to their users. This includes both the ability to use the back button in a natural way, and to be able to use URLs to deep link to any part of the application. History should be updated for every action that feels to the user that they are on a new page.
Features should work equally well on mobile and web platforms
Rationale: Open edX provides iOS and Android applications in addition to its web applications, and so new learner features need to be implemented for all three platforms. The simplest way to achieve feature parity is to provide a responsive web experience that can be used on phones and tablets as well as on desktops and laptops. The edx Pattern Library helps with this by providing a responsive grid system along with components that work equally well on mobile and web.
Designs should be fully accessible
Rationale: Open edX measures and evaluates accessibility using the World Wide Web Consortium’s Web Content Accessibility Guidelines (WCAG) 2.0. All features merged into edX repositories are expected to conform to Level AA of this specification and to satisfy the requirements outlined in the edX Website Accessibility Policy.
You can learn more about developing accessible applications with the Developer's Guide chapter edX Accessibility Guidelines.
Front end applications should support localization
Rationale: Open edX is used by learners all over the world, and so it is critical that all new functionality support localization. This means that every string in an application should be marked for translation, and it also includes ensuring that all new user interfaces will switch to right-to-left mode when the language requires it.
You can learn more about localization with the Developer's Guide chapter edX Internationalization.
Front end implementations should support theming
Rationale: Open edX is used by organizations around the world, and each one requires that the user experience is based upon their own brand. This includes elements as simple as overriding the fonts, imagery and color schemes, to more complex customization of headers, footers and registration flows.
You can learn more about how Open edX supports theming with the guide Changing Themes for an Open edX Site. One simple way to make your interface themeable is to use patterns from the edX Pattern Library as they already support theming.
- Front end code should be safe from cross site scripting
Cross Site Scripting (XSS) vulnerabilities allow user-supplied data to be incorrectly executed as code in a web browser. This can allow an attacker to inject malicious scripts, which in the worst case can cause the loss of private user data.
In order to keep your code safe from such attackers, you should follow the best practices laid out in the guide Preventing Cross Site Scripting Vulnerabilities.
Server-side content should be rendered with Django Templates
Rationale: There are many template languages available for Django, but the simplest option is to use the built-in Django template engine. The Open edX codebase has a mixture of Django and Mako templates, but the former are easier to reason about because they don't support arbitrary code evaluation. See Reasons for rejecting Mako for a more detailed explanation.
Exception: Mako templates can continue to be used within edx-platform for consistency with the existing code base. This is because the base templates and theming support are all provided via Mako, so it is too much to expect a new feature to be implemented with a different framework. There is much desire to replace Mako within edx-platform so this exception may eventually be removed.
ECMAScript 2015 should be the supported version of JavaScript
Rationale: ECMAScript is the standardized version of JavaScript, and modern front end libraries typically use ES2015 (aka ES6). Most browsers now provide native support for ES2015, but to support ES2016 or older browsers it is recommended to use Babel which can transpile various JavaScript dialects into ES5 (or ES2015, in the future).
Note: use of ES2015 features should be preferred to the use of older libraries such as CoffeeScript and Underscore which have been subsumed into the newer standard.
JavaScript libraries should be installed via npm
Rationale: It is important that JavaScript libraries are kept up-to-date, and one key component is to make it as simple as possible to perform upgrades. Projects that use npm maintain all of their library requirements in a single package.json file, which can be easily changed as the versions change.
JavaScript code should follow the edX ESLint configuration
Rationale: In order to standardize and enforce Open edX's JavaScript coding style across multiple codebases, edX has published an ESLint configuration that provides an enforceable specification. The edX ESLint Config is made available as an npm package that can be installed into any Open edX package.
Use React and Redux when building new client-side applications
Rationale: There are a large number of JavaScript libraries for building rich client applications, but many of them are too rigid for a flexible, extensible codebase like Open edX. The edX front end working group (aka FedX) has chosen the combination of React and Redux as the optimal way to build new client-side applications. A great primer on the benefits of this approach is A Study Plan to Cure JavaScript Fatigue.
An interesting area for future exploration is React Native which is a variant of React that can be used to render native iOS and Android applications. This could be a potential solution to build consistent experiences more efficiently across web and mobile. See React at edX for more details.
Note: the other modern library that many organizations are using is Angular 2. See Reasons for rejecting Angular for an exploration as to why this does not work as well as React for edX.
Exception: when building new applications within edx-platform, it is currently acceptable to use Backbone. Backbone is a somewhat old technology in the JavaScript world and has seen a rapid drop off in usage within the community. The plan is to incrementally adopt React within edx-platform as it can interoperate cleanly with Backbone.
JavaScript dependencies should be managed with AMD modules
Rationale: Open edX is a large, complicated code base, and it is getting more tangled over time. It is important that applications be composed as modules, and AMD is the standard module system for JavaScript. It allows code to declare the dependencies it requires, rather than forcing every page to load all possible libraries.
A majority of edX code uses `RequireJS`_ (and its associated libraries RequireJS Text and RequireJS Optimizer) to handle AMD modueles. In particular, RequireJS Optimizer supports intelligent bundling to package together all required libraries into a single file for faster performance. Note that other edX applications use Webpack which can also process RequireJS-style dependencies as well as the newer Common JS standard.
CSS should be generated using SASS
Rationale: Sass is an extension of CSS that adds power and elegance to the basic language. It makes the maintenance of large CSS files more manageable though the ability to use variables, mixins, imports and more. In particular, it makes theming possible with the ability to override variables that define colors, fonts etc.
You can find out more about Sass with the official documentation here: Sass.
Applications should be built for production using Webpack
Rationale: Webpack is the tool of choice for code optimization and bundling, as it is widely used throughout the industry, and because it seamlessly handles modern code bases as well as all of the older technologies used by edX, such as `RequireJS`_.
Note: There are already a variety of technologies used within Open edX, none of which is a clear winner. RequireJS Optimizer is used for bundling, Django Pipeline is used by edx-platform, Django Compressor is used by some of the Ecommerce applications, and Webpack is prevalent in pure front-end implementations.
Which more modern JavaScript framework should be supported?
The JavaScript space is very fast moving as can be seen in The State of JavaScript 2016 Survey. There is a lot of momentum around React, and it appears to have many qualities that would make it a good fit for edX. It is too early to make this call, but plans are being made to evaluate its usage. See React at edX for more details.
How should offline support be provided?
For many mobile users, it would be very useful if they could continue their Open edX courses while offline. This is true both for true mobile apps as well as for responsive web applications. This is an area that has not been explored much up to now, but which will only become more important going forward. In particular, we should look at the great capabilities provided by service workers. See the article `Service Workers: An Introduction`_ for a good starting point.
Should Universal JavaScript be considered?
There are many companies that are seeing performance benefits by pre-rendering their dynamic client-side applications on the server first. The most common approach is to run the same JavaScript code both in the browser and using Node on the server. This requires the use of a JavaScript framework that does not perform direct manipulation of the DOM, but instead works with an abstraction of the desired HTML. For example, Netflix is seeing great performance gains by using React in this way, as can be seen in the blog post Making Netflix Faster.
Where do web components fit with Open edX applications?
Web Components is a W3C recommendation that allows developers to create custom HTML elements for use within their web applications. The Polymer Project provides a library that allows web components to be built in most modern browsers. It seems that there is a useful overlap between web components and Open edX's XBlocks
Should HTTP/2 be used in preference to asset bundling?
The Hypertext Transfer Protocol Version 2 (HTTP/2) enables more efficient network communication between clients and servers. In particular, it allows for multiple requests to be handled with the same TCP connection, which removes most of the benefits of asset bundling. It is not yet clear whether this is ready for full scale adoption, but it would reduce a lot of complexity from application's asset pipelines.
Should Jinja2 be considered in preference to Django Templates?
Jinja2 is a popular alternative to Django Templates, that has not been evaluated for use within Open edX.
Note: this section needs fleshing out...
Angular
Needs fleshing out...
Bootstrap
An evaluation was performed,
size
not accessible (although there is this an accessibility plugin)
too inflexible
might want to consider compatibility to allow mixing Bootstrap components into pattern library pages. See the edX Bootstrap theme provided by the community as one approach.
Needs fleshing out...
CoffeeScript
The Open edX codebase made heavy use of CoffeeScript for several years, but it has now been officially deprecated. Most of the language benefits of CoffeeScript are now made available via ES2015.
Mako
There are a number of reasons why Django templates is preferred to Mako:
- Mako templates are not safe by default, meaning that it is very easy
to introduce cross-site scripting vulnerabilities. * Mako templates are hard to unit test because they require that the whole Django context be available in case the template tries to access it. Django templates only have access to the context object that is passed to it, so it is very easy to simulate all possible scenarios.
Needs fleshing out...