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

推荐订阅源

U
Unit 42
P
Proofpoint News Feed
The Last Watchdog
The Last Watchdog
S
Secure Thoughts
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
N
News | PayPal Newsroom
Application and Cybersecurity Blog
Application and Cybersecurity Blog
O
OpenAI News
S
Security @ Cisco Blogs
宝玉的分享
宝玉的分享
Hacker News: Ask HN
Hacker News: Ask HN
T
Troy Hunt's Blog
Google Online Security Blog
Google Online Security Blog
WordPress大学
WordPress大学
有赞技术团队
有赞技术团队
TaoSecurity Blog
TaoSecurity Blog
Help Net Security
Help Net Security
Latest news
Latest news
NISL@THU
NISL@THU
S
Security Affairs
博客园_首页
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园 - 聂微东
AI
AI
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Recent Announcements
Recent Announcements
P
Privacy & Cybersecurity Law Blog
小众软件
小众软件
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Hugging Face - Blog
Hugging Face - Blog
博客园 - 司徒正美
AWS News Blog
AWS News Blog
W
WeLiveSecurity
Google DeepMind News
Google DeepMind News
I
InfoQ
Schneier on Security
Schneier on Security
Recent Commits to openclaw:main
Recent Commits to openclaw:main
T
The Exploit Database - CXSecurity.com
IT之家
IT之家
T
Threatpost
Scott Helme
Scott Helme
L
LINUX DO - 热门话题
腾讯CDC
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
N
News and Events Feed by Topic
L
LINUX DO - 最新话题
F
Full Disclosure
大猫的无限游戏
大猫的无限游戏
H
Heimdal Security Blog
S
SegmentFault 最新的问题

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.