-
Notifications
You must be signed in to change notification settings - Fork 27.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prefetch pages with Service Workers #375
Conversation
support "import <Link>, { prefetch } from 'next/prefetch'"
This is pretty important since initiating will reset the cache. If we don't do this, it's possible to have old cached resources after the user decided to remove all of the prefetching logic. In this case, even the page didn't prefetch it'll use the previously cached pages. That because of there might be a already running service worker.
parser.href = href | ||
|
||
return parser.pathname | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use url
module here ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -0,0 +1,108 @@ | |||
/* global self */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you move this file to client
dir ?
pages
directory is intended to be for default pages like /_error
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks this file is not a target of gulp
and webpack
. Any reasons ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried at first, but it adds more code (because I use async await). But writing it with pure ES5 make it pretty simple (I just want this to work).
But I'd like to try something different now.
This is the all the features we need to add to the service worker code. Writing ES5 makes it smaller. Do we need to use ES6 and transpile it?
Anyway, I'll move it to the client directory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nkzawa I tried this now and It'll add ~28K with webpack but without it it's just 4K. Do we still need to proceed with webpack or just use the code written with ES5.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nkzawa Moved the prefetcher code to client. I also managed to reduced the bundle size by using babel-preset-env
and not using async await.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally prefer consistency than small optimizations which we can improve later if required.
Now we also do a webpack build for the prefetcher code.
This is going to be nuts! ❤️ |
@@ -182,6 +182,58 @@ Each top-level component receives a `url` property with the following API: | |||
- `pushTo(url)` - performs a `pushState` call that renders the new `url`. This is equivalent to following a `<Link>` | |||
- `replaceTo(url)` - performs a `replaceState` call that renders the new `url` | |||
|
|||
### Prefetching Pages |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rauchg here's the docs for README.
Doesn't Next already prefetch routes? |
@ccorcos no |
Go to https://zeit.co and look at the network tab when you click on "blog": Also: https://zeit.co/blog/next#anticipation-is-the-key-to-performance
|
they implemented it. it's not on next.js yet. they were running an internal component (probably was extracted as this PR). Related: #24 |
ah, I see |
Guys, this is a ground up implementation of prefetching for Next.js. It's not based on the zeit.co's implementation but definitely I took some core ideas from that. With this PR, Next.js doesn't prefetch all the pages. But only pages you have asked to prefetch. |
Looking awesome @arunoda |
['env', { | ||
'targets': { | ||
// All browsers which supports service workers | ||
'browsers': ['chrome 49', 'firefox 49', 'opera 41'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 👍 👍
pathname = '/index' | ||
} | ||
|
||
const url = `${pathname}.json` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Btw this url will become the same with non-json url and need to set the Accept
header with #310
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep. I will update this once we merge #310.
|
||
_register () { | ||
this.serviceWorkerState = 'REGISTERING' | ||
navigator.serviceWorker.register('/_next-prefetcher.js') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have a way to disable Service Worker completely ? I believe we need it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't get this?
You mean implement prefetching without service workers of something else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean you'd like to not register the script of ServiceWorker at all if you don't need prefetching.
It looks _register()
is always called if browser supports ServiceWorker for now ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried that way. See this commit message.
09325d9
This looks awesome, what else needs done to get this merged? |
We also clean the cache always, even we initialize the service worker or not.
When will there be a release with this new prefetch stuff? |
@arunoda - this has been merged into master, it doesn't look like it's been released on NPM yet though. Is that right? |
@philcockfield That's right. I assume it's coming pretty soon. |
This will add support for prefetching pages using service workers.
Declarative API
You can simply ask to prefetch pages by using the
<Link>
provided bynext/prefetch
. See:Now we'll prefetch all the pages. So, when you click on any of the link it won't need to do a network hit.
If you need you could stop prefetching like this:
Imperative API
You can get started with
<Link>
prefetching pretty quickly and it's a pretty decent way to prefetch. But you may want to prefetch based on your own logic.Then you can do it like this:
Browser Support
Service Workers are available only in Chrome, Firefox and Opera. For other browsers prefetching won't work. But
<Link>
fromnext/prefetch
will be work like<Link>
fromnext/link