From ccbaed208b5ea3d79bafed7267d644147308556a Mon Sep 17 00:00:00 2001 From: Connor Shea Date: Mon, 25 Jul 2016 12:15:09 -0600 Subject: [PATCH] Add more information on page-specific JS. [ci skip] --- doc/development/frontend.md | 64 ++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/doc/development/frontend.md b/doc/development/frontend.md index 39460b72ec0..c2dd130c258 100644 --- a/doc/development/frontend.md +++ b/doc/development/frontend.md @@ -5,17 +5,40 @@ consistent performance of GitLab. ## Performance -### Per-page JavaScript +### Page-specific JavaScript -Per-page JavaScript is JavaScript that is loaded only where necessary. +Certain pages may require the use of a third party library, such as [d3][d3] for +the User Activity Calendar and [Chart.js][chartjs] for the Graphs pages. These +libraries increase the page size significantly, and impact load times due to +bandwidth bottlenecks and the browser needing to parse more JavaScript. -There are some potential problems to per-page JavaScript as well. For one, +In cases where libraries are only used on a few specific pages, we use +"Page-specific JavaScript" to prevent the main `application.js` file from +becoming unnecessarily large. + +Steps to split page-specific JavaScript from the main `application.js`: + +1. Create a directory for the specific page(s), e.g. `graphs/`. +1. In that directory, create a `namespace_bundle.js` file, e.g. `graphs_bundle.js`. +1. Add the new "bundle" file to the list of precompiled assets in +`config/application.rb`. + - For example: `config.assets.precompile << "graphs/graphs_bundle.js"`. +1. Add any necessary libraries to `app/assets/javascripts/lib/`, all files directly descendant from this directory will be precompiled as separate assets. In this case, `chart.js` would be added. +1. In the relevant views, add the scripts to the page with the following: + +```haml +- content_for :page_specific_javascripts do + = page_specific_javascript_tag('lib/chart.js') + = page_specific_javascript_tag('graphs/graphs_bundle.js') +``` + +The above loads `chart.js` and `graphs_bundle.js` for only this page. `chart.js` is separated from the bundle file so it can be cached separately from the bundle and reused for other pages that also rely on the library. ### Minimizing page size A smaller page size means the page loads faster (especially important on mobile -and poor connections), the page is parsed faster by the browser, and less data is used for -users with capped data plans. +and poor connections), the page is parsed more quickly by the browser, and less +data is used for users with capped data plans. General tips: @@ -23,7 +46,7 @@ General tips: - Prefer font formats with better compression, e.g. WOFF2 is better than WOFF is better than TFF. - Compress and minify assets wherever possible (For CSS/JS, Sprockets does this for us). - If a piece of functionality can be reasonably done without adding extra libraries, prefer not to use extra libraries. -- Use per-page JavaScripts as described above to remove libraries that are only loaded on certain pages. +- Use page-specific JavaScripts as described above to dynamically load libraries that are only needed on certain pages. ## Accessibility @@ -35,27 +58,30 @@ Accessibility best-practices and more in-depth information is available on ## Security -### Content Security Policy - - - -### Subresource Integrity - - - ### Including external resources -External fonts, CSS, JavaScript should never be used with the exception of -Google Analytics - and only when the instance has enabled it. Assets should -always be hosted and served locally from the GitLab instance. Embedded resources -via `iframes` should never be used except in certain circumstances such as with -ReCaptcha, which cannot reasonably be used without an iframe. +External fonts, CSS, and JavaScript should never be used with the exception of +Google Analytics and Piwik - and only when the instance has enabled it. Assets +should always be hosted and served locally from the GitLab instance. Embedded +resources via `iframes` should never be used except in certain circumstances +such as with ReCaptcha, which cannot be used without an `iframe`. ### Avoiding inline scripts and styles +In order to protect users from [XSS vulnerabilities][xss], our intention is to +disable inline scripts entirely using Content Security Policy at some point in +the future. + While inline scripts can be useful, they're also a security concern. If user-supplied content is unintentionally left un-sanitized, malicious users can inject scripts into the site. +Inline styles should be avoided in almost all cases, they should only be used +when no alternatives can be found. This allows reusability of styles as well as +readability. + +[d3]: https://d3js.org/ +[chartjs]: http://www.chartjs.org/ [chrome-accessibility-developer-tools]: https://github.com/GoogleChrome/accessibility-developer-tools [audit-rules]: https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules +[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting