惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cisco Talos Blog
Cisco Talos Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
爱范儿
爱范儿
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Jina AI
Jina AI
雷峰网
雷峰网
The Register - Security
The Register - Security
The Cloudflare Blog
博客园 - 【当耐特】
M
MIT News - Artificial intelligence
I
InfoQ
博客园 - 三生石上(FineUI控件)
H
Help Net Security
博客园 - 司徒正美
Vercel News
Vercel News
WordPress大学
WordPress大学
S
SegmentFault 最新的问题
云风的 BLOG
云风的 BLOG
B
Blog
Google DeepMind News
Google DeepMind News
B
Blog RSS Feed
L
LangChain Blog
人人都是产品经理
人人都是产品经理
GbyAI
GbyAI
T
The Blog of Author Tim Ferriss
T
Tailwind CSS Blog
aimingoo的专栏
aimingoo的专栏
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Recorded Future
Recorded Future
小众软件
小众软件
Martin Fowler
Martin Fowler
罗磊的独立博客
Stack Overflow Blog
Stack Overflow Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
酷 壳 – CoolShell
酷 壳 – CoolShell
腾讯CDC
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Apple Machine Learning Research
Apple Machine Learning Research
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - Franky
Hugging Face - Blog
Hugging Face - Blog
Y
Y Combinator Blog
V
Visual Studio Blog
F
Fortinet All Blogs
Microsoft Azure Blog
Microsoft Azure Blog
大猫的无限游戏
大猫的无限游戏
Engineering at Meta
Engineering at Meta
N
Netflix TechBlog - Medium
V
V2EX
Blog — PlanetScale
Blog — PlanetScale

Minko Gechev's blog

skillgrade Unit Tests for AI Agent Skills You Should Care About AI Generative Development LLM-first Web Framework Reactive framework in ~200 lines of JavaScript Managing Angular Are LLMs going to replace us? Prefetching Heuristics Design Patterns in Open Source Projects - Part II Design Patterns in Open Source Projects - Part I What I learned doing 125 public talks - Part I Dynamic imports solve all the problems, right? 5 Angular CLI Features You Didn't Know About Introducing Bazel Schematics for Angular CLI Building TypeScript Projects with Bazel Joining Google Playing Mortal Kombat with TensorFlow.js. Transfer learning and data augmentation Fast, extensible, configurable, and beautiful linter for Go Introducing Guess.js - a toolkit for enabling data-driven user-experiences on the Web Machine Learning-Driven Bundling. The Future of JavaScript Tooling. JavaScript Decorators for Declarative and Readable Code 3 Tricks For Using Redux and Immutable.js with TypeScript Follow Your Dream Career with Open Source. Personal Story. Redux Anti-Patterns - Part 1. State Management. Faster Angular Applications - Understanding Differs. Developing a Custom IterableDiffer Faster Angular Applications - Part 2. Pure Pipes, Pure Functions and Memoization Faster Angular Applications - Part 1. On Push Change Detection and Immutability Understanding Dynamic Scoping and TemplateRef Implementing a Simple Compiler on 25 Lines of JavaScript Developing Statically Typed Programming Language WebVR for a Gamified IDE 7 Angular Tools That You Should Consider Announcing ngrev - Reverse Engineering Tool for Angular Implementing Angular's Dependency Injection in React. Understanding Element Injectors. Distributing an Angular Library - The Brief Guide Angular in Production Ahead-of-Time Compilation in Angular 2.5X Smaller Angular 2 Applications with Google Closure Compiler Using Stripe with Angular (Deprecated) Building an Angular Application for Production Implementing the Missing "resolve" Feature of the Angular 2 Router Scalable Single-Page Application Architecture Managing ambient type definitions and dealing with the "Duplicate identifier" TypeScript error Static Code Analysis of Angular 2 and TypeScript Projects Enforcing Best Practices with Static Code Analysis of Angular 2 Projects ViewChildren and ContentChildren in Angular Dynamically Configuring the Angular's Router Angular 2 Hot Loader Lazy Loading of Route Components in Angular 2 Aspect-Oriented Programming in JavaScript Flux in Depth. Store and Network Communication. Using JSX with TypeScript Flux in Depth. Overview and Components. Even Faster AngularJS Data Structures Boost the Performance of an AngularJS Application Using Immutable Data - Part 2 Angular2 - First Impressions Build Your own Simplified AngularJS in 200 Lines of JavaScript Persistent State of ReactJS Component Boost the Performance of an AngularJS Application Using Immutable Data Processing Binary Protocols with Client-Side JavaScript Stream your Desktop to HTML5 Video Element Multi-User Video Conference with WebRTC Asynchronous calls with ES6 generators Binary Tree iterator with ES6 generators WebRTC chat with React.js AngularJS in Patterns (Part 3) AngularJS in Patterns (Part 2). Services. Using GitHub Pages with Jekyll! AngularJS in Patterns (Part 1). Overview of AngularJS Singleton in JavaScript Express over HTTPS What I get from the JavaScript MV* frameworks Remote Desktop Client with AngularJS and Yeoman The magic of $resource (or simply a client-side Active Record) AngularJS Inheritance Patterns AngularAOP v0.1.0 Advanced JavaScript at Sofia University AngularJS style guide Lazy prefetching of AngularJS partials VNC client on 200 lines of JavaScript Aspect-Oriented Programming with AngularJS CSS3 flipping effect Practical programming with JavaScript Why I should use publish/subscribe in JavaScript JavaScript, the weird parts Functional programming with JavaScript plainvm Looking for performance? Probably you should NOT use [].sort (V8) JavaScript image scaling ELang Caching CSS with localStorage Self-invoking functions in JavaScript (or Immediately Invoked Function Expressions) Asus N56VZ + Ubuntu 12.04 (en) Asus N56VZ + Ubuntu 12.04 Debian Squeeze + LXDE on Google Nexus S (or having some fun while suffering) HTML5 image editor Курсови проекти – ФМИ Carousel Gallery SofiaJS...
Angular quicklink Preloading Strategy
2018-12-24 · via Minko Gechev's blog

Edit · Dec 24, 2018 · 5 minutes read · Follow @mgechev Preloading Performance Router Angular

A few months ago I posted an article about Guess.js. Guess.js is a powerful library for predictive prefetching of JavaScript based on analytics data for a website. The library consumes reports from an analytics source (by default Google Analytics) and builds a basic machine learning model. When a user visits the site, based on the model Guess.js prefetches resources which are likely to be needed next. Thanks to the data-driven approach, Guess.js offers many benefits - reduces over fetching, does not perform aggressive prefetching on slow networks, etc.

In this blog post we’re going to look at another prefetching approach, which takes advantage of two heuristics:

  • Users are likely to visit links which are visible on the page
  • We do not want to prefetch aggressively if the user is using a poor data plan
  • We want to prefetch only when the browser is idle

GatsbyJS is a static site generator which is famous for producing high-speed progressive web applications. To get even faster, Gatsby uses aggressive link prefetching.

When a link is visible on the screen, Gatsby prefetches the content associated with it. This is achieved with an IntersectionObserver, using the mapping between a link and the related resource, that is available at build time.

A potential drawback of this approach is over fetching which can cause extra bandwidth consumption. Another minor problem is related to navigation to pages which are not directly linked on the page. This scenario is possible when the user updates the URL in the address bar manually, for instance. Guess.js handles both problems quite well, and fortunately, there’s a Guess.js plugin for Gatsby. To use Guess.js, however, one needs to have an analytics source. A good compromise which does not require any analytics is to prefetch resources only when the user uses a fast data plan.

quicklink is a project which implements this algorithm! The library prefetches the content associated with all links currently visible on the page, in case the user is on a fast network. quicklink does not perform any prefetching if they are on a 2G network or slower. To detect the user’s network, Guess.js and quicklink use navigator.connection.effectiveType.

quicklink is a script which you drop on the page and it does its job. Unfortunately, that’s not the case for frameworks which manage their own routing, creating indirection between a URL and content. Examples are Angular, React with React Router, etc.

Let’s take a look at an Angular example:

import { Routes } from "@angular/router";

export const routes: Routes = [{
  path: 'about',
  loadChildren: './about/about.module#AboutModule'
}, {
  path: 'contact',
  loadChildren: './contact/contact.module#ContactModule'
}, {
  path: '',
  redirectTo: '',
  pathMatch: 'full'
}];

With the following routing definition, we can link to the page that the AboutModule is going to render using routerLink:

<a routerLink="/about">About</a>

quicklink will find all the a elements on the page at idle time and prefetch the page associated with their href attribute. Given the template above, this is not going to work as expected. quicklink will not be able to find the bundle associated with the /about page.

To let all Angular developers take advantage of the powerful prefetching strategy that quicklink provides, I developed ngx-quicklink.

How to use

ngx-quicklink has two main pieces:

  1. QuicklinkModule - includes a few internal services and a directive that first finds all the router links, and after that detects when they are visible on the screen.
  2. PreloadingStrategy - implementation of the PreloadingStrategy interface exposed by the @angular/router. It provides an abstraction for a service that decides if given route needs to be prefetched at given point.

You can read more about module preloading and the Angular’s PreloadingStrategy here.

To use ngx-quicklink, first, make sure you install the package:

npm i ngx-quicklink --save

Here’s how you can integrate the QuicklinkModule with your existing application:

import { QuicklinkModule } from 'ngx-quicklink';
...

@NgModule({
  imports: [QuicklinkModule],
  declarations: [...],
  exports: [QuicklinkModule]
})
export class SharedModule {}

The snippet above adds the QuicklinkModule to the list of imports and exports of a SharedModule. This module should be later imported in your AppModule and all the lazy-loaded modules. You don’t have to create a new shared module if you already have one.

Next, in your routing module set the preloading strategy:

import { QuicklinkStrategy } from 'ngx-quicklink';
...

@NgModule({
  imports: [RouterModule.forRoot(routes, {
    preloadingStrategy: QuicklinkStrategy
  })],
  exports: [RouterModule]
})
export class AppRoutingModule {}

On this link, you can find an integration of ngx-quicklink with the angular-realworld-example-app.

How it works

Here are the key features of ngx-quicklink:

  • Detects routerLinks within the viewport (using Intersection Observer)
  • Waits until the browser is idle (using requestIdleCallback)
  • Checks if the user isn’t on a slow connection (using navigator.connection.effectiveType) or has data-saver enabled (using navigator.connection.saveData)
  • Prefetches the lazy loaded modules using Angular’s prefetching strategy)

There are three main differences between the original quicklink implementation and ngx-quicklink:

  1. quicklink prefetches resources with link[rel="prefetch"] if available and fallbacks to XMLHttpRequest. ngx-quicklink uses only XMLHttpRequest because of the current module preloading mechanism of the Angular router. Although link[rel="prefetch"] is a better alternative, also used by Guess.js, most likely your users will not notice a difference.
  2. ngx-quicklink not only downloads the associated JavaScript bundles but also parses and evaluates the content. This will allow even further performance boost when the user changes the page.
  3. ngx-quicklink will download all parent modules of the requested module to prefetch.

Let us take a look at the last point. Suppose that we have the following routing definition:

export const routes: Routes = [{
  path: 'about',
  loadChildren: './about/about.module#AboutModule'
},
...
];

In the AboutModule we have the following route:

export const routes: Routes = [{
  path: 'team',
  loadChildren: './team/team.module#TeamModule'
},
...
];

If on the page there’s a routerLink="/about/team", ngx-quicklink will first download the AboutModule and after that will proceed with the TeamModule.

Conclusion

In this article, we talked about prefetching in web applications. We discussed the quicklink prefetching strategy and where it originates from. After that, we discussed what’s the difference between predictive prefetching and quicklink.

In the next section, we put quicklink into the context of Angular, and discussed the limitations of the original implementation. Combining Angular’s routerLink directive with the framework’s PreloadingStrategy, we introduced ngx-quicklink - quicklink implementation for Angular.