├── .gitignore
├── README.md
├── assets
└── guess-next-large.gif
├── components
└── layout.js
├── next.config.js
├── package-lock.json
├── package.json
├── pages
├── about.js
├── example.js
├── index.js
└── media.js
├── routes.json
└── static
├── favicon.ico
├── guess.png
└── styles.css
/.gitignore:
--------------------------------------------------------------------------------
1 | .next
2 | guess
3 | node_modules
4 |
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 🔮 Guess.js + Next.js
2 |
3 | **[Guess.js](https://github.com/guess-js/guess) is a collection of libraries & tools for enabling data-driven user-experience on the web.**
4 |
5 | In this particular example, we combine Guess.js with Next.js to introduce predictive prefetching of JavaScript bundles. Based on user navigation patterns collected from Google Analytics or other source, Guess.js builds a machine-learning model to predict and prefetch JavaScript that will be required in each subsequent page.
6 |
7 | Based on early benchmarks, this can improve the perceived page load performance with 20%.
8 |
9 | For more information on Guess.js, take a look at the following links:
10 | * [Google I/O announcement](https://www.youtube.com/watch?time_continue=2093&v=Mv-l3-tJgGk) by Addy Osmani
11 | * [Introducing Guess.js - a toolkit for enabling data-driven user-experiences on the Web](https://blog.mgechev.com/2018/05/09/introducing-guess-js-data-driven-user-experiences-web/)
12 | * [Using Guess.js with static sites](https://github.com/guess-js/guess/tree/master/experiments/guess-static-sites)
13 | * [Using Guess.js with Angular, React, and Gatsby](https://github.com/guess-js/guess/tree/master/packages/guess-webpack)
14 |
15 | ## Usage
16 |
17 | Here's how you can try the demo:
18 |
19 | ```bash
20 | git clone git@github.com:mgechev/guess-next
21 | cd guess-next && npm i
22 | npm run build && npm start
23 | ```
24 |
25 | 
26 |
27 | ## Integration
28 |
29 | Guess.js (**0.1.5 and above**) works with Next.js with only two points of integration. All you need to do is add the `GuessPlugin` to `next.config.js` and introduce a snippet for prefetching the pages which are likely to be visited next.
30 |
31 | The following sections describe both points in details.
32 |
33 | ### Webpack Config
34 |
35 | All you need is to extend the webpack config of your Next.js application is to add the `GuessPlugin` to `next.config.js` file, located in the root of your project. If the file does not exist, create it and add the following content:
36 |
37 | ```ts
38 | const { GuessPlugin } = require('guess-webpack');
39 |
40 | module.exports = {
41 | webpack: function(config, { isServer }) {
42 | if (isServer) return config;
43 | config.plugins.push(
44 | new GuessPlugin({
45 | GA: 'XXXXXX'
46 | })
47 | );
48 | return config;
49 | }
50 | };
51 | ```
52 |
53 | We set the value of the `webpack` property of the object literal we set as value to `module.exports`. We set it to a function which alters the `GuessPlugin` to the `config.plugins` array. Notice that we check if Next.js has invoked webpack on the server and we return.
54 |
55 | As a value of the `GA` property, we set a Google Analytics View ID. At build time, Guess.js will open a browser and try to get read-only access to extract a report and use it for the predictive analytics.
56 |
57 | *Note that Google Analytics is not the only provider you can use to provide the user navigation report that Guess.js uses. In this example application we provide the report from a JSON file.*
58 |
59 | ### Prefetch Pages
60 |
61 | The final piece of the integration is performing the actual prefetching. In your layout component (see `components/layout.js`) add:
62 |
63 | ```ts
64 | import { guess } from 'guess-webpack/api';
65 |
66 | // ...
67 |
68 | if (typeof window !== 'undefined') {
69 | Object.keys(guess()).forEach(p => router.prefetch(p));
70 | }
71 |
72 | // ...
73 | ```
74 |
75 | Keep in mind that we check if `window` is `"undefined"`. This is required because we don't want to run Guess.js on the server. When we invoke `guess()`, we'll return a set of routes where each route will have an associated probability for the user to visit it.
76 |
77 | The routes that `guess()` returns depend on the Google Analytics report that it has extracted, together with the user's effective connection type.
78 |
79 | ## License
80 |
81 | MIT
82 |
--------------------------------------------------------------------------------
/assets/guess-next-large.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgechev/guess-next/bb76489cd500f49b6ef45d8039653cd7075743ba/assets/guess-next-large.gif
--------------------------------------------------------------------------------
/components/layout.js:
--------------------------------------------------------------------------------
1 | import { withRouter } from 'next/router';
2 | import { guess } from 'guess-webpack/api';
3 |
4 | import Link from 'next/link';
5 | import Head from 'next/head';
6 |
7 | const layout = ({ router, children, title = '🔮 Next.js + Guess.js' }) => {
8 | let predictions = [];
9 | if (typeof window !== 'undefined') {
10 | predictions = Object.keys(guess()).sort((a, b) => a.length - b.length);
11 | predictions.forEach(p => router.prefetch(p));
12 | }
13 |
14 | return (
15 |
16 |
17 | {title}
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
39 |
40 |
41 | Navigate through the application to see the magic
42 |
43 | The user will likely visit ✨
44 |