How to Improve Front-end Performance

In this blog , I focus on "angular performance". No matter what Web framework we use, the performance problems we face and the solutions we offer are almost the same.

Speed and stability are required by all apps and websites.  For delivering excellent web experiences for large audiences, we should try to :

1, Reduce network traffic

  • Bundling
  • Code Splitting
  • Minify: optimize and minify your CSS, Uglify: minify your JavaScript
  • Implement Gzip Compression to reduce the size of files
  • Tree-shaking
  • Use website caching
  • lazy loading modules
  • RxJS operators: debounce, ReplaySubject  
    debounce
    discard emitted values that take less than the specified time
    ReplaySubject, shareReplay ,etc.
    Replays or emits old values to new subscribers
  • *ngFor + TrackBy
  • Unsubscribe from Observables
  • Optimize the size of images on your website.Offer responsive images.
    <img sizes="(min-width: 1200px) 730w,
                (max-width: 1199px) 610w,
                (max-width: 380px) 350w"
         srcset="/img/blog/responsive-images-lg.png 730w,
                 /img/blog/responsive-images-md.png 610w,
                 /img/blog/responsive-images-sm.png 350w"
         src="/img/blog/reponsive-images.png"
         alt="responsive images">
    
    <img sizes="(min-width: 1200px) 730w,
                (max-width: 1199px) 610w,
                (max-width: 380px) 350w"
         srcset="/img/blog/responsive-images-lg.png 730w 1x,
                 /img/blog/responsive-images-lg@2x.png 730w 2x,
                 /img/blog/responsive-images-md.png 610w 1x,
                 /img/blog/responsive-images-md@2x.png 610w 2x,
                 /img/blog/responsive-images-sm.png 350w 1x,
                 /img/blog/responsive-images-sm@2x.png 350w 2x"
         src="/img/blog/reponsive-images.png"
         alt="responsive images">
                     
    <picture>
        <source sizes="(min-width: 1200px) 730w" srcset="/img/blog/responsive-images-lg.png 730w">
        <source sizes="(max-width: 1199px) 610w" srcset="/img/blog/responsive-images-md.png 610w">
        <source sizes="(max-width: 380px) 350w" srcset="/img/blog/responsive-images-sm.png 350w">
        <img src="/img/blog/reponsive-images.png" alt="responsive images" class="img-fluid rounded">
    </picture>
    // reference: https://www.keycdn.com/blog/responsive-images
                    
  • SSR: Server Side Rendering

2, Reduce the rendering time

It's commonly accepted that 60 frames per second is the rate at which animations will appear smooth. For a rate of 60 frames per second, the browser has 16.7 milliseconds to execute scripts, recalculate styles and layout if needed, and repaint the area being updated.
Repaint effects the visibility of an element but doe s not affects layout.   Reflow means re-calculating the positions and geometries of elements in the document, for the purpose of re-rendering part or all of the document.
  • preloading modules
  • AOT Compilation
  • Service Worker
  • Web Worker. OffscreenCanvas can allow us to paint on screen from within a web worker. So animation will not block the main tread.
  • Resolve guards
  • OnPush Change Detection for a component:  changeDetection: ChangeDetectionStrategy.OnPush
  • using pure pipes
  • minimize browser reflow and repaint css js render-tree
      The operations trigger reflow:
    1. add ,modify, delete DOM visible elements in Javascript code
    2. change size or position of an element
    3. change the content of an element, e.g. text length or image size
    4. change font-size
    5. use table layout
    6. activate CSS pseudo-classes,e.g. :hover
    7. query some properties or call some methods.
      → clientWidth、clientHeight、clientTop、clientLeft
      → offsetWidth、offsetHeight、offsetTop、offsetLeft
      → scrollWidth、scrollHeight、scrollTop、scrollLeft
      → scrollIntoView()、scrollIntoViewIfNeeded()
      → getComputedStyle()
      → getBoundingClientRect()
      → scrollTo()
                            
    The operations trigger repaint ( repaint is less expensive than reflow ):
    change color, background-color, visibility, etc.
  • Optimization methods:
    1. don't use table layout
    2. change the class of the lowest node of the DOM tree
    3. don't use multiple layer inline styles
    4. set the position of animations as absolute or fixed
    5. don't use CSS calculate, e.g. calc()
    6. call window.requestAnimationFrame() for animations
    7. replace style attribute with a common CSS class when styling elements
  • Eliminate render-blocking resources
    HTML markup is transformed into a Document Object Model (DOM); CSS markup is transformed into a CSS Object Model (CSSOM). DOM and CSSOM are independent data structures;the CSSOM and DOM trees are combined into a render tree
    JavaScript code block all constructing and rendering, CSS block a part of them
    • Javascript block DOM and CSSOM constructing, then block render-tree constructing and block download of static files, e.g. images. We should put the script tag just before body , if not, put them in head portion with "defer" or "async" attribute
      // a .html file
      //  async and defer attributes should put in head portion of the page.
      //  they are useless if you put the script in the body footer.
      
      // When a page loads a script with defer,
      // the script is fetched asynchronously, and it’s executed only after the HTML parsing is done.
      
      // When a page loads a script with async,
      // The script is fetched asynchronously, and when it’s ready the HTML parsing is paused to execute the script,
      // then it’s resumed.
      
      <head>
      
      
        <script defer src="some.js"></script>
        <script async src="some.js"></script>
        </head>
      <body>
        ...
        ...
        <script src="some.js"></script>
      </body>
            
    • CSS files block neither HTML files parsing or DOM constructing. They block CSSOM constructing, then block the render-tree constructing. We can put CSS link in head.
       // some.html
      <html>
         <head>
         <link
            href="xxxx.css"
            rel="stylesheet"
          />
         </head>
         <body>
      
         </body>
       </html>
                            
    • CSS files don't block others files executing. They block Javascript files executing.

Conclusion:

  • reduce network traffic
  • reduce rendering time
Reference: https://flaviocopes.com/javascript-async-defer/#async-and-defer