webpack / webpack-pwa

Example for a super simple PWA with webpack.
https://webpack.github.io/webpack-pwa/page-shell/dashboard.html
808 stars 52 forks source link

The learnings from the app-shell and page-shell structure #1

Open ritz078 opened 7 years ago

ritz078 commented 7 years ago

Hi,

We have experimented with app-shell and are using page-shell currently (with a slight modification - loading the whole view in advance).

App Shell It gave us better time to first paint but the time to first meaningful paint was delayed. Here's what we found in our experiment.

cxabh40uuaamded

As a user you get a faster first paint but the time to first meaningful content is what we are looking to optimize so we tried to fix that.

Solution We got rid of app shell and implemented SSR with HTML streaming in combination with preload. And the result was :

201 1 - how we built it - part 1 housing

This way we were able to improve the time to first meaningful paint which made more sense than just improving the time to first paint.

Page Shell Since we had implemented SSR and the idea of page-shell is same as that of app-shell, we used the idea rather than the implementation.

Case 1: Implement page-shell -> First meaningful paint still suffers. 2 JS files to load and when you navigate from another URL, loading multiple files (we also have separate CSS to prevent FOUC) didn't seem to be a good idea.

Case 2: Implement SSR -> Let the view have 2 files (JS and CSS). When the user lands directly on the page you don't need any shell due to SSR. When you are on a different page and the next intent of the user is to come on that page, load the view of current page in the idle time of previous page.

Implementing these we were able to solve for :

All of these were more about the implementation rather than webpack bundling.

webpack was mainly optimized to implement long term caching, manifest and chunking.

Intent based chunks We implement route based chunks but we often ignore this. This is one important implementation that can reduce the size of a view bundle. There are certain parts of a view that are not always needed like a modal or anything that doesn't show up everytime. That can be made into a different chunk and loaded on demand. For example:

201 1 - how we built it - part 1 housing

The size in the above image is non-gzipped (around 9KB gzipped).

We are using 2 types of intent based chunks which are loaded in idle time or as per need.

Type 1 : Those which have a chance of being visible but not immediately. They are loaded in idle time like some frequently visited modals. (driven by analytics)

Type 2: Those which have less chance of being visible or once in many sessions. Load when actually required. Most of the times its not needed. (as per our analytics data)

We have to take care of bandwidth consumption of the user. Loading lot of chunks in idle time also may not be a good idea for people with slow internet connection.

I hope these are useful for developers who are trying to make a PWA. So in both cases out time to first paint was around 2.2-2.3s so it was better that we implement the 2nd solution.

Its not always necessary that these will work for you so experiment and then implement.

Edit : Added clarity about intent based chunks.

kurtextrem commented 7 years ago

Intent based chunks: When the mobile connection is slow, doesn't it take a while to load 32 KB? Why not speculatively preload chunks that are somewhat likely to get clicked?

ritz078 commented 7 years ago

Why not speculatively preload chunks that are somewhat likely to get clicked ?

@kurtextrem Good point that you raised. We are using 2 types of intent based chunks. the size of the file showed is non-gzipped. its actually around 9KB gzipped.

Type 1 : Those which have a chance of being visible but not immediately. They are loaded in idle time like some frequently visited modals. (driven by analytics)

Type 2: Those which have less chance of being visible or once in many sessions. Load when actually required. Most of the times its not needed. (as per our analytics data)

We have to take care of bandwidth consumption of the user. Loading lot of chunks in idle time also may not be a good idea for people with slow internet connection.

I am adding this in the main issue also.

wub commented 7 years ago

We have users all around the world, but only one server (in the USA). At first thought, would it be faster for us to host our app shells on a CDN, rather than doing SSR?

*Considering the ~500ms latency impact of doing SSR on a mobile network from the other side of the world, rather than loading something from a CDN POP nearby.