This repo contains a project from the Udacity Front-End Web Developer nanodegree aimed at demonstrating mastery in performance optimization.
To get started, check out the repository, inspect the code,
- Clone the repo
cd Your/Target/Directory
git clone https://github.com/christopher-taylor/udacity-fend-mobile-portfolio
The pages optimized for performance are index.html and pizza.html. index.html has been optimized to achieve a PageSpeed Insights score of 90 on desktop and mobile. pizza.html has been optimized to hit 60FPS.
A list of full optimizations follows:
- Used defer to defer the execution of analytics.js and perfmatters.js until the page is loaded.
- Created a version of pizzeria.jpg that was 100px wide and loaded that instead since the image has a fixed width.
- Added media print/screen attributes to the css files so the browser only loads what is neeeded to render.
- Added will-change to force the moving pizzas into a seperate layer so we wouldn't repaint the whole page.
- Added transform: translateZ to engage the GPU for a better framerate.
- Added "use strict"; for safer code.
- Moved the pizzasDiv declaration outside of the for loop to reduce the number of DOM calls and as a result the pages load time.
- Added latestKnownScrollY and ticking.
- Created onScroll which when called adds the window.ScrollY to latestKnownScrollY and calls requestTick()
- Added requestTick so if the browser is not currently working on updatePositions it will request an animation frame and run updatePositions
- scroll event now triggers onScroll instead of updatePositions.
Changes 3-6 are linked. Combined they have the effect of decouppling updatePositions from the scroll browser event and adds a middleman who detects if we're already processing a frame, and if so just waits. This managed approach to requesting animation frames prevents very long frames from happening when the browser decides to process multiple scroll events and as a result multiple calls to updatePositions in a frame. Learn more here.
- Get the pizzaSizeElement outside of the switch just to make the code less ugly.
- Changed elements size to a % instead of a fixed size. As a result determineDx() has been folded into changePizzaSizes and no longer exists
- Pulled the query selector statement outside of the loop to reduce the number of dom calls and changed if from QueryAll to getElementById for speed.
- The switch from determineDx has been moved here and made an if block because switches are kind of fugly.
- We are now determining newWidth outside of the loop since it is the same for all elements and to do it otherwise is bad.
- Loop changed to a forEach because it looks so much nicer.
- Added ticking = false, this tells the code that is okay to request another frame.
- Changed items declaration from querySelectorAll to getElementsByClassName for speed.
- mathTerm is now determined by using latestKnownScrollY instead of document.body.scrollTop. This eliminates a dom call and is also part of decoupling our scroll animation from the actual scroll input.
- Phase is delcared outside of the loop to eliminate a variable being created every iteration of the loop.
- Reduced the number of cols from 8 to 6
- Added rows which are dynamically determined based on screen height.
- We are now creating row * cols pizzas instead of 200.
- Declared the elem variable outside of the loop to remove the declaration from inside the loop.
- Fetch the movingPizzas1 query outside of the loop to reduce DOM calls and changed it to getElementById for speed.
- Added to force devices that support GPU rasterization to use it.