From d454a7c1d99f2f5b859fbe0d2e1f99863970c60d Mon Sep 17 00:00:00 2001 From: Jonathan Gray Date: Thu, 19 Jan 2017 13:19:26 -0800 Subject: [PATCH 01/14] added a few things to front-end README and starting javascript styleguide --- front-end/README.md | 9 ++++++++- front-end/javascript-styleguide.md | 0 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 front-end/javascript-styleguide.md diff --git a/front-end/README.md b/front-end/README.md index 8230620..1ddcda1 100644 --- a/front-end/README.md +++ b/front-end/README.md @@ -20,7 +20,7 @@ * Strive to create loosely coupled, highly reusable code. * Always keep extensibility in mind. * Maintain code that is easy read and understand. -* All code in any code-base should look like a single person wrote it, even on a team +* All code in any code-base should look like a single person wrote it, even on a team with many contributors. * When trying to fix an issue, consider removing code before adding to it. * It is important to strictly enforce the agreed-upon standards. @@ -47,6 +47,8 @@ * Syntax: **ES6** * Dom Manipulation Framework: **jQuery** * UI Framework: **ReactJS** +* Style Guide: [View Guide](https://github.com/canvasnyc/code-standards/blob/master/front-end/javascript-styleguide.md) + #### * When Rails is *Not* Avialable * Compiler: **Webpack** @@ -61,3 +63,8 @@ * **Fastclick**: removes 300ms delay on touch devices [source](https://github.com/ftlabs/fastclick) * **Modernizr**: feature testing [source](https://modernizr.com/) * **HammerJS**: adds touch gestures [source](http://hammerjs.github.io/) +* **Waypoints**: useful for events triggered by scroll points [source](http://imakewebthings.com/waypoints/) + +#### * Common ES6 Polyfills +* `Array.from()`: Needed for IE11 [source](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#Polyfill) +* `Object.assign()`: Needed for IE11 [source](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill) diff --git a/front-end/javascript-styleguide.md b/front-end/javascript-styleguide.md new file mode 100644 index 0000000..e69de29 From 6e4364a3ce62d7e27061203ca9880853f111cfe0 Mon Sep 17 00:00:00 2001 From: Jonathan Gray Date: Thu, 19 Jan 2017 13:36:41 -0800 Subject: [PATCH 02/14] adding base for javascript styleguide --- front-end/css-styleguide.md | 141 +++++++++++++++-------------- front-end/javascript-styleguide.md | 50 ++++++++++ 2 files changed, 125 insertions(+), 66 deletions(-) diff --git a/front-end/css-styleguide.md b/front-end/css-styleguide.md index 65395ff..e16522c 100644 --- a/front-end/css-styleguide.md +++ b/front-end/css-styleguide.md @@ -11,14 +11,15 @@ 6. [Responsive](#responsive) 7. [SCSS](#scss) 8. [File Organization](#organization) -9. [Resets](#resets) -10. [Sources](#sources) +9. [Resets](#resets) +10. [Notes on performance](#performance) +11. [Sources](#sources) ## Whitespace -* Configure your IDE to use soft-tabs with a two space indent. Spaces guarantee code +* Configure your IDE to use soft-tabs with a two space indent. Spaces guarantee code will renders the same all environment. * Trim trailing white spaces. * Add a space after the `:` in property declarations. @@ -26,7 +27,7 @@ * One selector per line, one rule per line * Place closing braces of selectors on their own line. * Include a space after each comma in comma-separated property or function values. -* Large blocks of single declarations can use a single-line format. In this case, a +* Large blocks of single declarations can use a single-line format. In this case, a space should be included after the opening brace and before the closing brace. @@ -34,7 +35,7 @@ * Always use #hex color codes, unless using rgb/rgba. * Do not specify units for 0 values. `margin: 0;` -* Try to limit use of shorthand declarations to instances where you must explicitly set +* Try to limit use of shorthand declarations to instances where you must explicitly set all the available values. * Order properties _alphabetically_. * Use unit-less line-height. `line-height: 1.5;` @@ -57,7 +58,7 @@ margin: 0; padding-bottom: 0; @include mixin(example-mixin); - + .example__component { background: #AAA; display: block; @@ -81,7 +82,7 @@ * Use [BEM](http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/) naming conventions. * Provide clear names for your selectors. * Do not unnecessarily abriviate selectors, and reduce readability. -* Strive to create loosely coupled, modular code that can be easily reused regardless of +* Strive to create loosely coupled, modular code that can be easily reused regardless of its container or contents. * Avoid the use of ID’s. The negligible performance difference is not worth the limitations. * When a class is applied or used as a selector for JavaScript, prefix the class with js-. @@ -93,13 +94,13 @@ ## Comments -* Well commented code is extremely important. Take time provide information about your +* Well commented code is extremely important. Take time provide information about your code, it’s limitations, and any non-obvious information. -* Always add an introductory comment to all partials to provide clarity about the files +* Always add an introductory comment to all partials to provide clarity about the files contents and purpose. * Use consistent, hierarchical comments to divide and organize your files. * Try to make comments concise and intuitive. -* It’s a good idea to configure your editor to provide you with shortcuts to output +* It’s a good idea to configure your editor to provide you with shortcuts to output agreed-upon comment patterns. #### Example: @@ -129,12 +130,12 @@ // ------------------------------------------ // // Comment on multiple lines -// +// // This is an Example of a long comment that // spans multiple line. -// -// Use this format for long descriptions and -// more detailed documentation +// +// Use this format for long descriptions and +// more detailed documentation // // ------------------------------------------ @@ -147,7 +148,7 @@ * Avoid using `!important` unless __absolutely necessary__. * Try to work with the cascade and avoid unecessary overrides. -* Try to avoid chaining selectors `.myselector.another.and-another` but +* Try to avoid chaining selectors `.myselector.another.and-another` but rather create a new specific class. * Use .ie conditionals to set IE specific code. * Use Modernizr when necessary to provide feature classes and overrides. @@ -156,11 +157,11 @@ ## Responsive -* Always build mobile first. This will greatly reduce the weight on mobile and +* Always build mobile first. This will greatly reduce the weight on mobile and significantly reduces necessary overrides through media queries. * Always specify your media query breakpoints via variables. * Nest media queries inside the original selector, allow them to be easily located - and modified. If Sprockets is available combine all media queries for production + and modified. If Sprockets is available combine all media queries for production with: [Sprockets Media Query Combiner.](https://github.com/aaronjensen/sprockets-media_query_combiner.) * When nesting creates readability issues, include your media quierys at the bottom of that partial. @@ -213,7 +214,7 @@ $breakpoints: ( * Always place nested selectors after it's parents. * Use variables for all common numbers, and numbers with meaning. * Use Compass for all vendor prefixing -* Consolodate all global Variables and Mixins into their own files. +* Consolodate all global Variables and Mixins into their own files. @@ -222,52 +223,52 @@ $breakpoints: ( #### Folder Structure: ``` -sass/ -| -|– base/ -| |– _reset.scss # Reset/normalize -| |– _typography.scss # Typography rules -| ... # Etc… -| -|– components/ -| |– _buttons.scss # Buttons -| |– _carousel.scss # Carousel -| |– _cover.scss # Cover -| |– _dropdown.scss # Dropdown -| |– _navigation.scss # Navigation -| ... # Etc… -| -|– helpers/ -| |– _variables.scss # Sass Variables -| |– _functions.scss # Sass Functions -| |– _mixins.scss # Sass Mixins -| |– _helpers.scss # Class & placeholders helpers -| ... # Etc… -| -|– layout/ -| |– _grid.scss # Grid system -| |– _header.scss # Header -| |– _footer.scss # Footer -| |– _sidebar.scss # Sidebar -| |– _forms.scss # Forms -| ... # Etc… -| -|– pages/ -| |– _home.scss # Home specific styles -| |– _contact.scss # Contact specific styles -| ... # Etc… -| -|– themes/ -| |– _theme.scss # Default theme -| |– _admin.scss # Admin theme -| ... # Etc… -| -|– vendors/ -| |– _bootstrap.scss # Bootstrap -| |– _jquery-ui.scss # jQuery UI -| ... # Etc… -| -| +sass/ +| +|– base/ +| |– _reset.scss # Reset/normalize +| |– _typography.scss # Typography rules +| ... # Etc… +| +|– components/ +| |– _buttons.scss # Buttons +| |– _carousel.scss # Carousel +| |– _cover.scss # Cover +| |– _dropdown.scss # Dropdown +| |– _navigation.scss # Navigation +| ... # Etc… +| +|– helpers/ +| |– _variables.scss # Sass Variables +| |– _functions.scss # Sass Functions +| |– _mixins.scss # Sass Mixins +| |– _helpers.scss # Class & placeholders helpers +| ... # Etc… +| +|– layout/ +| |– _grid.scss # Grid system +| |– _header.scss # Header +| |– _footer.scss # Footer +| |– _sidebar.scss # Sidebar +| |– _forms.scss # Forms +| ... # Etc… +| +|– pages/ +| |– _home.scss # Home specific styles +| |– _contact.scss # Contact specific styles +| ... # Etc… +| +|– themes/ +| |– _theme.scss # Default theme +| |– _admin.scss # Admin theme +| ... # Etc… +| +|– vendors/ +| |– _bootstrap.scss # Bootstrap +| |– _jquery-ui.scss # jQuery UI +| ... # Etc… +| +| `– style.scss # primary Sass file ``` [Reference](http://www.sitepoint.com/architecture-sass-project/) @@ -288,14 +289,22 @@ html { @include box-sizing(border-box); } -*, -*:before, +*, +*:before, *:after { @include box-sizing(inherit); } ``` + +## Notes on performance +- simplify selectors +- animate with transforms and opacity whenever possible (including sprites) +- avoid frequent changes of classes on top level elements such as html and body + + + ## Sources diff --git a/front-end/javascript-styleguide.md b/front-end/javascript-styleguide.md index e69de29..f52eadb 100644 --- a/front-end/javascript-styleguide.md +++ b/front-end/javascript-styleguide.md @@ -0,0 +1,50 @@ +# JavaScript Style Guide + + +## Table of contents + +1. [Whitespace](#whitespace) +2. [Formatting](#formatting) +3. [Naming Conventions](#naming-conventions) +4. [Comments](#comments) +5. [File Organization](#organization) +6. [Variables](#variables) +7. [Notes on performance](#performance) +8. [Sources](#sources) + + + +## Whitespace + + + +## Formatting + + + +## Naming Conventions + + + +## Comments + + + +## File Organization + + + +## Variables + + + +## Notes on performance +- caching selectors +- removing reference to detached elements +- adding/removing event listeners +- avoid DOM read/write loops +- no unused variables + + + +## Sources From a3ac17723fe11303c122a0984b977d3c872ff78c Mon Sep 17 00:00:00 2001 From: Jonathan Gray Date: Fri, 20 Jan 2017 11:29:14 -0800 Subject: [PATCH 03/14] added velocity to js plugins --- front-end/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/front-end/README.md b/front-end/README.md index 1ddcda1..b388526 100644 --- a/front-end/README.md +++ b/front-end/README.md @@ -63,7 +63,10 @@ * **Fastclick**: removes 300ms delay on touch devices [source](https://github.com/ftlabs/fastclick) * **Modernizr**: feature testing [source](https://modernizr.com/) * **HammerJS**: adds touch gestures [source](http://hammerjs.github.io/) +* **VelocityJS**: accelerated JavaScript animations with or without jQuery [source](http://velocityjs.org/) * **Waypoints**: useful for events triggered by scroll points [source](http://imakewebthings.com/waypoints/) +* **Underscore**: great set of utility functions (including debounce and throttle) [source](http://underscorejs.org/) + #### * Common ES6 Polyfills * `Array.from()`: Needed for IE11 [source](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#Polyfill) From f71ad0c57b53d88d55893f9cfc5c01dd55f04749 Mon Sep 17 00:00:00 2001 From: Jonathan Gray Date: Fri, 20 Jan 2017 11:29:29 -0800 Subject: [PATCH 04/14] added some performance notes to js --- front-end/javascript-styleguide.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/front-end/javascript-styleguide.md b/front-end/javascript-styleguide.md index f52eadb..bc03402 100644 --- a/front-end/javascript-styleguide.md +++ b/front-end/javascript-styleguide.md @@ -39,11 +39,15 @@ ## Notes on performance +- use chrome DevTools [timeline](https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/timeline-tool) - caching selectors - removing reference to detached elements - adding/removing event listeners - avoid DOM read/write loops - no unused variables +- throttle and debounce +- stores measurements and only measure again after a debounced resize event + - each measurement forces style recalculation which forces layout From 599a634e49c2584e49569169ddca70391955feb0 Mon Sep 17 00:00:00 2001 From: Jonathan Gray Date: Fri, 20 Jan 2017 11:36:54 -0800 Subject: [PATCH 05/14] changed link description for timeline --- front-end/javascript-styleguide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front-end/javascript-styleguide.md b/front-end/javascript-styleguide.md index bc03402..4ef426d 100644 --- a/front-end/javascript-styleguide.md +++ b/front-end/javascript-styleguide.md @@ -39,7 +39,7 @@ ## Notes on performance -- use chrome DevTools [timeline](https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/timeline-tool) +- use chrome DevTools [intro to the timeline](https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/timeline-tool) - caching selectors - removing reference to detached elements - adding/removing event listeners From 7429c2ab1b0ce46bf0dfa845dcd6a986eea0eccc Mon Sep 17 00:00:00 2001 From: Jonathan Gray Date: Sat, 21 Jan 2017 19:36:03 -0800 Subject: [PATCH 06/14] added some css performance tips --- front-end/css-styleguide.md | 45 ++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/front-end/css-styleguide.md b/front-end/css-styleguide.md index e16522c..405ee40 100644 --- a/front-end/css-styleguide.md +++ b/front-end/css-styleguide.md @@ -299,9 +299,42 @@ html { ## Notes on performance -- simplify selectors -- animate with transforms and opacity whenever possible (including sprites) -- avoid frequent changes of classes on top level elements such as html and body +* Try to stick with simple and clear selectors whenever possible. + +#### Example: +In the simplest case you reference an element in your CSS with just a class: +``` +.title { + /* styles */ +} +``` +But, as any project grows, it will likely result in more complex CSS, such that you may end up with selectors that look like this: +``` +.box:nth-last-child(-n+1) .title { + /* styles */ +} + +``` +In order to know that the styles need to apply the browser has to effectively ask “is this an element with a class of title which has a parent who happens to be the minus nth child plus 1 element with a class of box?” Figuring this out can take a lot of time, depending on the selector used and the browser in question. The intended behavior of the selector could instead be changed to a class: +``` +.final-box-title { + /* styles */ +} +``` +You can take issue with the name of the class, but the job just got a lot simpler for the browser. In the previous version, in order to know, for example, that the element is the last of its type, the browser must first know everything about all the other elements and whether the are any elements that come after it that would be the nth-last-child, which is potentially a lot more expensive than simply matching up the selector to the element because its class matches. [Source](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) + +* When animating, the 4 properties browsers can animation most cheaply are position, scale, rotation and opacity. +``` +.animating-item { + transform: translate(npx, npx); + transform: scale(npx); + transform: rotate(ndeg); + opacity: 0...1; +} +``` +Browsers have 5 steps in rendering pixels on the screen: JavaScript, Style, Layout, Paint, and Composite. JavaScript and Style are pretty straightforward. Layout is where everything goes and their sizes. Paint is where pixels start to get filled in such as drawing text, borders, colors, images, and shadows. Composite makes sure that everything was layered correctly. Those 4 properties only trigger an update in the composite step while all others either enact a re-paint or a re-layout. If a change is made in any step, all the steps after need to be re-exectued. +* Avoid frequent changes of classes on top level elements such as html and body. +This harkens to the previous topic of how a browser renders a pixel because if you change a class on the body element, it has to go through every child element and make any updates that may reflect the newly added/removed class. @@ -324,3 +357,9 @@ html { * [SMACSS](http://smacss.com/) * [Atomic CSS](http://bradfrostweb.com/blog/post/atomic-web-design/) * [OOCSS](http://www.smashingmagazine.com/2011/12/12/an-introduction-to-object-oriented-css-oocss/) + +#### Performance Links + +* [High Performance Animations](https://www.html5rocks.com/en/tutorials/speed/high-performance-animations/) +* [CSS Triggers](https://csstriggers.com/) +* [Rendering Performance](https://developers.google.com/web/fundamentals/performance/rendering/) From df6ed94358b1991604200aedbbb64794d06ed6ff Mon Sep 17 00:00:00 2001 From: Jonathan Gray Date: Sat, 21 Jan 2017 19:40:14 -0800 Subject: [PATCH 07/14] adjusted some formatting --- front-end/css-styleguide.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/front-end/css-styleguide.md b/front-end/css-styleguide.md index 405ee40..aa1a699 100644 --- a/front-end/css-styleguide.md +++ b/front-end/css-styleguide.md @@ -321,7 +321,7 @@ In order to know that the styles need to apply the browser has to effectively as /* styles */ } ``` -You can take issue with the name of the class, but the job just got a lot simpler for the browser. In the previous version, in order to know, for example, that the element is the last of its type, the browser must first know everything about all the other elements and whether the are any elements that come after it that would be the nth-last-child, which is potentially a lot more expensive than simply matching up the selector to the element because its class matches. [Source](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) +You can take issue with the name of the class, but the job just got a lot simpler for the browser. In the previous version, in order to know, for example, that the element is the last of its type, the browser must first know everything about all the other elements and whether there are any elements that come after it that would be the nth-last-child, which is potentially a lot more expensive than simply matching up the selector to the element because its class matches. [Source](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) * When animating, the 4 properties browsers can animation most cheaply are position, scale, rotation and opacity. ``` @@ -334,6 +334,7 @@ You can take issue with the name of the class, but the job just got a lot simple ``` Browsers have 5 steps in rendering pixels on the screen: JavaScript, Style, Layout, Paint, and Composite. JavaScript and Style are pretty straightforward. Layout is where everything goes and their sizes. Paint is where pixels start to get filled in such as drawing text, borders, colors, images, and shadows. Composite makes sure that everything was layered correctly. Those 4 properties only trigger an update in the composite step while all others either enact a re-paint or a re-layout. If a change is made in any step, all the steps after need to be re-exectued. * Avoid frequent changes of classes on top level elements such as html and body. + This harkens to the previous topic of how a browser renders a pixel because if you change a class on the body element, it has to go through every child element and make any updates that may reflect the newly added/removed class. From e9d81d75ac007cbff41339d68b9db3d0a957cb5c Mon Sep 17 00:00:00 2001 From: Jonathan Gray Date: Sat, 21 Jan 2017 20:44:26 -0800 Subject: [PATCH 08/14] added some javascript styleguide notes --- front-end/css-styleguide.md | 2 + front-end/javascript-styleguide.md | 126 ++++++++++++++++++++++++++--- 2 files changed, 119 insertions(+), 9 deletions(-) diff --git a/front-end/css-styleguide.md b/front-end/css-styleguide.md index aa1a699..6d18c68 100644 --- a/front-end/css-styleguide.md +++ b/front-end/css-styleguide.md @@ -299,6 +299,7 @@ html { ## Notes on performance + * Try to stick with simple and clear selectors whenever possible. #### Example: @@ -333,6 +334,7 @@ You can take issue with the name of the class, but the job just got a lot simple } ``` Browsers have 5 steps in rendering pixels on the screen: JavaScript, Style, Layout, Paint, and Composite. JavaScript and Style are pretty straightforward. Layout is where everything goes and their sizes. Paint is where pixels start to get filled in such as drawing text, borders, colors, images, and shadows. Composite makes sure that everything was layered correctly. Those 4 properties only trigger an update in the composite step while all others either enact a re-paint or a re-layout. If a change is made in any step, all the steps after need to be re-exectued. + * Avoid frequent changes of classes on top level elements such as html and body. This harkens to the previous topic of how a browser renders a pixel because if you change a class on the body element, it has to go through every child element and make any updates that may reflect the newly added/removed class. diff --git a/front-end/javascript-styleguide.md b/front-end/javascript-styleguide.md index 4ef426d..909c4c2 100644 --- a/front-end/javascript-styleguide.md +++ b/front-end/javascript-styleguide.md @@ -11,11 +11,52 @@ 6. [Variables](#variables) 7. [Notes on performance](#performance) 8. [Sources](#sources) +9. [Resources](#resources) ## Whitespace +* Use soft tabs set to 2 spaces. +* Place 1 space before the leading brace. +* Place 1 space before the opening parenthesis in control statements (`if`, `while` etc.). Place no space between the argument list and the function name in function calls and declarations. + + ```javascript + // bad + if(isJedi) { + fight (); + } + + // good + if (isJedi) { + fight(); + } + + // bad + function fight () { + console.log ('Swooosh!'); + } + + // good + function fight() { + console.log('Swooosh!'); + } + ``` + +* Set off operators with spaces. + + ```javascript + // bad + const x=y+5; + + // good + const x = y + 5; + ``` + +* Leave a blank line after blocks and before the next statement. +* Do not add spaces inside parentheses or brackets +* Add spaces inside curly braces. + ## Formatting @@ -24,6 +65,36 @@ ## Naming Conventions +* Avoid single letter names. Be descriptive with your naming. +* Use camelCase when naming objects, functions, and instances. +* Use PascalCase only when naming constructors or classes. +* Do not use trailing or leading underscores. +* Don't save references to `this`. Use arrow functions or [Function#bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind). + + ```javascript + // bad + function foo() { + const self = this; + return function () { + console.log(self); + }; + } + + // bad + function foo() { + const that = this; + return function () { + console.log(that); + }; + } + + // good + function foo() { + return () => { + console.log(this); + }; + } + ``` ## Comments @@ -39,16 +110,53 @@ ## Notes on performance -- use chrome DevTools [intro to the timeline](https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/timeline-tool) -- caching selectors -- removing reference to detached elements -- adding/removing event listeners -- avoid DOM read/write loops -- no unused variables -- throttle and debounce -- stores measurements and only measure again after a debounced resize event - - each measurement forces style recalculation which forces layout +* Use chrome DevTools to identify bottlenecks and areas for improvement. [intro to the timeline](https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/timeline-tool) +* Cache all the selectors needed at the start so as to not repeatadly query the DOM for the same element. +* Remove reference to detached elements (elements that no longer exist in the DOM but are still referenced by a variable). This causes DOM leaks because they cannot be taken care of through garbage collection. [Memory Problems](https://developers.google.com/web/tools/chrome-devtools/memory-problems/heap-snapshots) +* Add and remove event listeners on module initialization and teardown respectively. + Additionally, remove an event listener when no longer needed. To ensure an event listener is properly removed, the reference to the callback has to be the exact same as what was added. For example: + + ```javascript + let button = document.getElementById('button'); + + let myClickCallback = () => { + // `this` needs to be a reference to the outer scope, not the element clicked + console.log('You clicked ', this); + } + + // Bad + button.addEventListener('click', myClickCallback.bind(this)); + button.removeEventListener('click', myClickCallback.bind(this)); + + // Good + let myClickCallbackHandler = myClickCallback.bind(this); + + button.addEventListener('click', myClickCallbackHandler); + button.removeEventListener('click', myClickCallbackHandler); + ``` + +* Avoid DOM read/write loops. + Measuring the size of an element forces a relayout in the browser which, if then invalidated by updating styles, requires an additional relayout if more measurements are needed. See [On Layout and Web Performance](https://kellegous.com/j/2013/01/26/layout-performance/). +* When possible, get and store measurements as early as possible so as to avoid unnecessary forced relayouts. +* Declare only needed variables + In the spirit of minimizing use of memory, only declare a variable if needed. The 'gotcha' here is having `e` as a parameter in an event callback and then not using it. +* Always use `throttle` and `debounce` for repeated events such as scroll and resize. + This limits the rate at which an event callback gets executed. Unless a faster response is needed, our default delay value is 300. ## Sources + +* [On Layout and Web Performance](https://kellegous.com/j/2013/01/26/layout-performance/) +* [Analyzing Runtime Performance](https://developers.google.com/web/tools/chrome-devtools/rendering-tools/) +* [Debouncing and Throttling Explained](https://css-tricks.com/debouncing-throttling-explained-examples/) + + +## Resources + +**Learning ES6** + + - [Draft ECMA 2015 (ES6) Spec](https://people.mozilla.org/~jorendorff/es6-draft.html) + - [ExploringJS](http://exploringjs.com/) + - [ES6 Compatibility Table](https://kangax.github.io/compat-table/es6/) + - [Comprehensive Overview of ES6 Features](http://es6-features.org/) From ae11658a42fb21536f18128314e4bbb35d8c61d7 Mon Sep 17 00:00:00 2001 From: Jonathan Gray Date: Sat, 21 Jan 2017 21:06:19 -0800 Subject: [PATCH 09/14] added more js styleguide --- front-end/javascript-styleguide.md | 58 ++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/front-end/javascript-styleguide.md b/front-end/javascript-styleguide.md index 909c4c2..43d4f88 100644 --- a/front-end/javascript-styleguide.md +++ b/front-end/javascript-styleguide.md @@ -4,11 +4,11 @@ ## Table of contents 1. [Whitespace](#whitespace) -2. [Formatting](#formatting) -3. [Naming Conventions](#naming-conventions) -4. [Comments](#comments) -5. [File Organization](#organization) -6. [Variables](#variables) +2. [Naming Conventions](#naming-conventions) +3. [Comments](#comments) +4. [File Organization](#organization) +5. [Variables](#variables) +6. [Comparison Operators](#comparison-operators) 7. [Notes on performance](#performance) 8. [Sources](#sources) 9. [Resources](#resources) @@ -58,10 +58,6 @@ * Add spaces inside curly braces. - -## Formatting - - ## Naming Conventions @@ -96,25 +92,52 @@ } ``` + ## Comments +* Use /** ... */ for multi-line comments. +* Use // for single line comments. Place single line comments on a newline above the subject of the comment. Put an empty line before the comment unless it's on the first line of a block. +* Start all comments with a space to make it easier to read. +* Prefixing your comments with FIXME or TODO helps other developers quickly understand if you're pointing out a problem that needs to be revisited, or if you're suggesting a solution to the problem that needs to be implemented. These are different than regular comments because they are actionable. The actions are FIXME: -- need to figure this out or TODO: -- need to implement. + ## File Organization +* Group controllers, modules, and utility files into their respective directories. +* File names should match what is exported. + ## Variables +* Always use `const` to declare variables. Not doing so will result in global variables. We want to avoid polluting the global namespace. +* Use one `const` declaration per variable. +* Group all your `const`s and then group all your `let`s. + + + +## Comparison Operators & Equality + +* Use `===` and `!==` over `==` and `!=` +* Conditional statements such as the if statement evaluate their expression using coercion with the `ToBoolean` abstract method and always follow these simple rules: + - Objects evaluate to true + - Undefined evaluates to false + - Null evaluates to false + - Booleans evaluate to the value of the boolean + - Numbers evaluate to false if +0, -0, or NaN, otherwise true + - Strings evaluate to false if an empty string '', otherwise true +* Use shortcuts for booleans, but explicit comparisons for strings and numbers. +* For more information see [Truth Equality and JavaScript](https://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/#more-2108) by Angus Croll. ## Notes on performance -* Use chrome DevTools to identify bottlenecks and areas for improvement. [intro to the timeline](https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/timeline-tool) -* Cache all the selectors needed at the start so as to not repeatadly query the DOM for the same element. + +* Use chrome DevTools to identify bottlenecks and areas for improvement. [Intro to the Timeline](https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/timeline-tool) +* Cache all the selectors needed at the start so as to not repeatedly query the DOM for the same element. * Remove reference to detached elements (elements that no longer exist in the DOM but are still referenced by a variable). This causes DOM leaks because they cannot be taken care of through garbage collection. [Memory Problems](https://developers.google.com/web/tools/chrome-devtools/memory-problems/heap-snapshots) -* Add and remove event listeners on module initialization and teardown respectively. - Additionally, remove an event listener when no longer needed. To ensure an event listener is properly removed, the reference to the callback has to be the exact same as what was added. For example: +* Add and remove event listeners on module initialization and teardown respectively. Additionally, remove an event listener when no longer needed. To ensure an event listener is properly removed, the reference to the callback has to be the exact same as what was added. For example: ```javascript let button = document.getElementById('button'); @@ -135,13 +158,10 @@ button.removeEventListener('click', myClickCallbackHandler); ``` -* Avoid DOM read/write loops. - Measuring the size of an element forces a relayout in the browser which, if then invalidated by updating styles, requires an additional relayout if more measurements are needed. See [On Layout and Web Performance](https://kellegous.com/j/2013/01/26/layout-performance/). +* Avoid DOM read/write loops. Measuring the size of an element forces a relayout in the browser which, if then invalidated by updating styles, requires an additional relayout if more measurements are needed. See [On Layout and Web Performance](https://kellegous.com/j/2013/01/26/layout-performance/). * When possible, get and store measurements as early as possible so as to avoid unnecessary forced relayouts. -* Declare only needed variables - In the spirit of minimizing use of memory, only declare a variable if needed. The 'gotcha' here is having `e` as a parameter in an event callback and then not using it. -* Always use `throttle` and `debounce` for repeated events such as scroll and resize. - This limits the rate at which an event callback gets executed. Unless a faster response is needed, our default delay value is 300. +* Declare only needed variables In the spirit of minimizing use of memory, only declare a variable if needed. The 'gotcha' here is having `e` as a parameter in an event callback and then not using it. +* Always use `throttle` and `debounce` for repeated events such as scroll and resize. This limits the rate at which an event callback gets executed. Unless a faster response is needed, our default delay value is 300. From 9d1249340118bdb4673b05afd67ab030134ef613 Mon Sep 17 00:00:00 2001 From: Jonathan Gray Date: Sat, 21 Jan 2017 21:11:49 -0800 Subject: [PATCH 10/14] added a js perf guideline and changed some verbage --- front-end/javascript-styleguide.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/front-end/javascript-styleguide.md b/front-end/javascript-styleguide.md index 43d4f88..43a1d5c 100644 --- a/front-end/javascript-styleguide.md +++ b/front-end/javascript-styleguide.md @@ -142,7 +142,7 @@ ```javascript let button = document.getElementById('button'); - let myClickCallback = () => { + const myClickCallback = () => { // `this` needs to be a reference to the outer scope, not the element clicked console.log('You clicked ', this); } @@ -152,7 +152,7 @@ button.removeEventListener('click', myClickCallback.bind(this)); // Good - let myClickCallbackHandler = myClickCallback.bind(this); + const myClickCallbackHandler = myClickCallback.bind(this); button.addEventListener('click', myClickCallbackHandler); button.removeEventListener('click', myClickCallbackHandler); @@ -161,7 +161,8 @@ * Avoid DOM read/write loops. Measuring the size of an element forces a relayout in the browser which, if then invalidated by updating styles, requires an additional relayout if more measurements are needed. See [On Layout and Web Performance](https://kellegous.com/j/2013/01/26/layout-performance/). * When possible, get and store measurements as early as possible so as to avoid unnecessary forced relayouts. * Declare only needed variables In the spirit of minimizing use of memory, only declare a variable if needed. The 'gotcha' here is having `e` as a parameter in an event callback and then not using it. -* Always use `throttle` and `debounce` for repeated events such as scroll and resize. This limits the rate at which an event callback gets executed. Unless a faster response is needed, our default delay value is 300. +* Always use `throttle` and `debounce` for repeated events such as scroll and resize. This limits the rate at which an event callback gets executed. Unless a faster response is needed, default to a delay value of 300. +* Pre-calculate style changes for animatinos by way of the [FLIP method](https://aerotwist.com/blog/flip-your-animations/) so as to not be making them during the animation. From 0a2cef2407aa741aeccc8308237a2717af3115c1 Mon Sep 17 00:00:00 2001 From: Jonathan Gray Date: Mon, 23 Jan 2017 09:34:32 -0800 Subject: [PATCH 11/14] added whitespace rule to js --- front-end/javascript-styleguide.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/front-end/javascript-styleguide.md b/front-end/javascript-styleguide.md index 43a1d5c..313cdc9 100644 --- a/front-end/javascript-styleguide.md +++ b/front-end/javascript-styleguide.md @@ -92,6 +92,21 @@ } ``` +* 1 line `if`s are fine, 3 or more are preferred. No 2 line `if` statements + + ```javascript + // bad + if (condition) + doSomething(); + + // good + if (condition) doSomething(); + + // good + if (condition) { + doSomething(); + } + ``` ## Comments From 2343e592b3f677adfe2c8f2cb25e26038a9c11b0 Mon Sep 17 00:00:00 2001 From: Jonathan Gray Date: Tue, 24 Jan 2017 14:27:54 -0800 Subject: [PATCH 12/14] swapped underscore for lodash --- front-end/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/front-end/README.md b/front-end/README.md index b388526..102c33d 100644 --- a/front-end/README.md +++ b/front-end/README.md @@ -1,4 +1,4 @@ -# Front-end Core Standards +–# Front-end Core Standards ## Table of Contents @@ -65,7 +65,7 @@ * **HammerJS**: adds touch gestures [source](http://hammerjs.github.io/) * **VelocityJS**: accelerated JavaScript animations with or without jQuery [source](http://velocityjs.org/) * **Waypoints**: useful for events triggered by scroll points [source](http://imakewebthings.com/waypoints/) -* **Underscore**: great set of utility functions (including debounce and throttle) [source](http://underscorejs.org/) +* **Lodash**: great set of utility functions included as needed (including debounce and throttle) [source](https://lodash.com/) #### * Common ES6 Polyfills From 8b8f7b4787bf26c4778615069fc365f79ebe057b Mon Sep 17 00:00:00 2001 From: Jonathan Gray Date: Tue, 24 Jan 2017 15:29:36 -0800 Subject: [PATCH 13/14] added requestAnimation polyfill --- front-end/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/front-end/README.md b/front-end/README.md index 102c33d..e2b07e0 100644 --- a/front-end/README.md +++ b/front-end/README.md @@ -67,6 +67,8 @@ * **Waypoints**: useful for events triggered by scroll points [source](http://imakewebthings.com/waypoints/) * **Lodash**: great set of utility functions included as needed (including debounce and throttle) [source](https://lodash.com/) +#### * Common Polyfills +* `requestAnimationFrame`: Needs to be vender prefixed in JavaScript [source](https://gist.github.com/paulirish/1579671) #### * Common ES6 Polyfills * `Array.from()`: Needed for IE11 [source](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#Polyfill) From 5a7421bc262118b891826bd6ab8508f83fdf1baa Mon Sep 17 00:00:00 2001 From: jon Date: Wed, 25 Jan 2017 15:09:19 -0800 Subject: [PATCH 14/14] Update README.md --- front-end/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front-end/README.md b/front-end/README.md index e2b07e0..2f6bd51 100644 --- a/front-end/README.md +++ b/front-end/README.md @@ -1,4 +1,4 @@ -–# Front-end Core Standards +# Front-end Core Standards ## Table of Contents