Git Product home page Git Product logo

guess's People

Contributors

addyosmani avatar alan-agius4 avatar arcanis avatar chrisguttandin avatar danielruf avatar dharmin avatar dijs avatar irustm avatar kasperstorgaard avatar kevinfarrugia avatar khempenius avatar kyleamathews avatar lionralfs avatar maoberlehner avatar mgechev avatar mitkotschimev avatar pborreli avatar ra80533 avatar renovate-bot avatar renovate[bot] avatar sergeycherman avatar slavoroi avatar spencerb02 avatar vprasanth avatar wardpeet avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

guess's Issues

Optional parsing for applications with pre-existing pre-fetching logic

Currently, the parser is the most complex module of Guess mostly because it requires a lot of knowledge about the project structure. Applications using frameworks with very dynamic route declaration, such as React, make the route extraction impossible without following strict conventions.

In the same time, often the application itself has the route-bundle mapping metadata available at runtime. An example for this is Gatsby, which uses its own pre-fetching mechanism. Such applications can use only the model generated by Guess even if the parser cannot properly extract the routing metadata.

After a chat with @KyleAMathews today, I extracted a function called score which uses the Markov chain in order to rank what's the probability the user to visit a list of links from given page.

Although this API is convenient, it'll not be usable in case the parser cannot produce the application's routes because score uses the page graph of the application (i.e. it the route declarations instead of the actual links), which requires routing metadata.

In order to make the score function available to applications which are not supported by the Guess parser, we can provide a flag which hints the GuessPlugin to skip parsing. In such case, the Markov chain will reflect the actual application links (i.e. it'll not aggregate links corresponding to the same route declaration).

Cannot build with guess api

When using:

  runtime: {
    delegate: true
  }

and

import { guess } from 'guess-webpack/api'

Webpack is throwing this:

Module not found: Error: Can't resolve 'guess-webpack/api' in '...'

Any ideas?

Re-introduce chunk clustering

Prior implementation

The initial chunk clustering implementation accepts a minimum number of chunks that need to be produced by the build process and goes through a graph clustering based on Tarjan's algorithm for finding strongly connected components.

This algorithm has a number of problems:

  • It treats chunks belonging to nested routes and chunks without a common ancestor the same way.
  • It terminates when the number of chunks in the application is at most the minimum number of chunks specified in the configuration. Configuring the minimum number of chunks the application should consist is not a good heuristic for concatenating JavaScript files together.
  • The algorithm does not consider the chunk size but only the probability two chunks to be visited in the same session.

Suggested implementation

Combine only chunks of nested routes where the probability of two chunks to be used together is high (threshold should be discussed).

In such case, if we have the following routes in the application:

/a/b/c
/b
/c
/d
/e/f
/e

We'll recommend developers to load everything lazily (i.e. even load lazily /a, /a/b, and /a/b/c).

In such case, the probability /a, /a/b, and /a/b/c to be visited in the same session is 1 (because we have only one route with root /a), for /e and /e/f the probability is n.

In this case, we'll cluster the chunks from /a, /a/b, and /a/b/c into a single file. Depending on the value of n, we may also combine /e and /e/f.

When the user is at any page (e.g. /a/b/c) we'll prefetch the other bundles based on the Markov chain which we've built in the prefetch plugin.

Note: this algorithm does not solve the problem which occurs when combining large chunks together.

How to measure success?

What metric should I use to measure the success of adding prefetching to my static site? Thanks

Guess parser does not work on Windows

The parser in the src/angular/index.ts file (and probably the other parsers) do non-cross platform compatible path manipulations.

This should be fixed so that the parsing works properly on Windows.

Roadmap proposals

Roadmap/Ideas

Features / Ease of use

  • Improve Guess API #42
  • Re-introduce chunk clustering #6
  • Cache the OAuth2 access token #12

Code-sharing

  • Investigate better code-sharing between bundling/non-bundling solutions
  • Investigate code re-use with 3P providers (e.g IIH Nordic)

Machine Learning

  • Evaluate using neural networks vs current markov chain approach
  • Evaluate using LSTM

Community

  • Micro-site
  • Codelab: Data-driven loading
  • Codelab: Data-driven bundling

Integrations

  • Parser: return all routes for an Angular app #44
  • Parser: support for Vue.js
  • Parser: support for Next.js

Any other ideas we want to consider? @mgechev @khempenius @KyleAMathews @MarkEdmondson1234

Cannot read property 'guess' of undefined

am trying to use guess with laravel through a pre-defined routes file like in nuxt example so the setup is

  • guess-routes.json ex.
{
    "\/": {
        "\/login": 2,
        "\/about": 1
    },
    "\/about": {
        "\/contact-us": 1
    },
    "\/contact-us": {
        "\/": 1
    }
}
  • webpack
const {readFileSync} = require('fs')
const {GuessPlugin} = require('guess-webpack')

mix.webpackConfig({
    plugins: [
        new GuessPlugin({
            reportProvider() {
                return Promise.resolve(JSON.parse(readFileSync('./guess-routes.json')))
            }
        })
    ]
})
  • app.js
import {guess} from 'guess-webpack/api'
guess()
  • error
    demo

Model for predictive analytics

Current approach

At the moment, Guess.js uses a Markov chain in order to predict the next route the user will navigate to. We build the Markov chain by using a report fetched from Google Analytics (GA) where for each page path, we get the previous page path. The model has several advantages such as:

  • Doesn't require a lot of runtimes. The prediction can be made with a simple O(1) lookup so we don't have to ship a lot of code to the browser. On top of that, the matrix can be easily compressed, so even for large apps, its size will be reasonable.
  • Simplicity. We do not have to trace users' complex navigation patterns. Also, the model is quite easy to reason about

This approach has its own cons. We ignore a lot of potentially useful features such as:

  • More comprehensive navigation patterns including more than two pages visited in a session
  • navigator.locale & navigator.platform
  • etc.

Improving accuracy

We're thinking of exploring a more advanced model using neural networks. We've been looking at LSTM using tensorflow.js. Currently, there are few unknowns we need to research further, such as:

  • What'd be the most efficient way to extract longer navigation sequences from GA
  • What'd be the runtime that we should ship to the browser if we move to a predictive model using neural networks (not applicable to static websites)
  • How much the build-time will increase if we train the model while bundling the application (not applicable to static websites)
  • How to measure accuracy efficiently without violating users' privacy
  • Can we ship only part of the model to the browser without loading the entire tensorflow.js
  • What additional features to include in order to improve accuracy

Additional questions

The problem that we're solving looks quite similar to a recommender system and the path we've taken is collaborative filtering. Is it worth exploring content-based filtering or a mixture between the two?

Building repo doesn't quite finish

npm run build

> [email protected] build /Users/kylemathews/programs/guess
> ts-node infra/build.ts

Hash: bf143cb0a0b4932eec72
Version: webpack 3.11.0
Time: 1743ms
                      Asset       Size  Chunks             Chunk Names
         ./dist/ga/index.js    17.7 kB       0  [emitted]  main
         dist/ga/index.d.ts   26 bytes          [emitted]
        dist/ga/src/ga.d.ts  304 bytes          [emitted]
    dist/ga/src/client.d.ts  324 bytes          [emitted]
dist/common/interfaces.d.ts  899 bytes          [emitted]
 dist/ga/src/normalize.d.ts  192 bytes          [emitted]
   [0] ./index.ts 205 bytes {0} [built]
   [1] ./src/ga.ts 5.16 kB {0} [built]
   [2] ./src/client.ts 7.29 kB {0} [built]
   [4] ./src/normalize.ts 1.61 kB {0} [built]
    + 1 hidden module

Hash: a15f1cf2b91a4d961071
Version: webpack 3.11.0
Time: 3694ms
                               Asset       Size  Chunks             Chunk Names
    dist/parser/src/react/index.d.ts  175 bytes          [emitted]
              ./dist/parser/index.js    20.8 kB       0  [emitted]  main
         dist/parser/src/parser.d.ts  126 bytes          [emitted]
  dist/parser/src/angular/index.d.ts  334 bytes          [emitted]
         dist/common/interfaces.d.ts  899 bytes          [emitted]
              dist/parser/index.d.ts  181 bytes          [emitted]
     dist/parser/src/react/base.d.ts  200 bytes          [emitted]
dist/parser/src/react/react-tsx.d.ts  133 bytes          [emitted]
dist/parser/src/react/react-jsx.d.ts  129 bytes          [emitted]
 dist/parser/src/detector/index.d.ts   26 bytes          [emitted]
dist/parser/src/detector/detect.d.ts  138 bytes          [emitted]
   [2] ./src/react/index.ts 355 bytes {0} [built]
   [4] ./src/angular/index.ts 5.15 kB {0} [built]
   [5] ../common/interfaces.ts 407 bytes {0} [built]
   [6] ./src/detector/index.ts 205 bytes {0} [built]
   [7] ./index.ts 466 bytes {0} [built]
   [8] ./src/parser.ts 1.47 kB {0} [built]
  [10] ./src/react/base.ts 4.16 kB {0} [built]
  [11] ./src/react/react-tsx.ts 1.2 kB {0} [built]
  [12] ./src/react/react-jsx.ts 757 bytes {0} [built]
  [13] ./src/detector/detect.ts 2.14 kB {0} [built]
    + 4 hidden modules

Error: Command failed: cd /Users/kylemathews/programs/guess/packages/webpack && rm -rf dist && webpack
    at checkExecSyncError (child_process.js:575:11)
    at Object.execSync (child_process.js:612:13)
    at _loop_1 (/Users/kylemathews/programs/guess/infra/build.ts:45:17)
    at build (/Users/kylemathews/programs/guess/infra/build.ts:62:13)
    at Object.<anonymous> (/Users/kylemathews/programs/guess/infra/build.ts:75:3)
    at Module._compile (internal/modules/cjs/loader.js:654:30)
    at Module.m._compile (/Users/kylemathews/programs/guess/node_modules/ts-node/src/index.ts:403:23)
    at Module._extensions..js (internal/modules/cjs/loader.js:665:10)
    at Object.require.extensions.(anonymous function) [as .ts] (/Users/kylemathews/programs/guess/node_modules/ts-node/src/index.ts:406:12)
    at Module.load (internal/modules/cjs/loader.js:566:32)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] build: `ts-node infra/build.ts`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/kylemathews/.npm/_logs/2018-05-05T23_45_56_625Z-debug.log

[guess-parser] Return all routes of an Angular app

Hi @mgechev,

this is a follow up issue of #1 of @mlx/parser. I guess guess-parser is the successor of @mlx/parser.

I can confirm, that parsing an Angular App which has a routing module generated by the CLI works now. However when there are nested routes guess-parser does not pick up those routes. I was abled to track down the problem. It seems to be problematic that the CLI does extract nested routes into their own modules as well but guess-parser expects them to be defined in the root module of any lazily loaded module.

Since explaining the problem is a bit difficult I created a little example project. It is an app created by the Angular CLI. The README contains all the commands I used. It also contains a little script to invoke the parseAngularRoutes() function. It can be invoked by running node parse.js. I would expect it to return two routes (zero and zero/first) but it only returns the first.

Please let me know if you need more infos to reproduce the bug.

Integrating Katie's predictiveFetching work

Hey folks. @khempenius has been working on a set of experimental solutions for the average site wishing to take advantage of predictive fetching over in https://github.com/guess-js/guess/tree/predictiveFetching/predictiveFetching.

I'd love to figure out this week how best to position this work inside the repo. I'm currently thinking that we keep packages as-is for reusable modules that we deploy to npm (or we could roll Katie's work into a new package entry in there). I was otherwise viewing Katie's work as a workflow (which we'll hopefully eventually figure out the convergence points between compared to the rest of the packages we have).

Perhaps this work would make sense in either:

  • \workflows\predictive-fetching-sites\
  • \tutorials\predictive-fetching-sites\
  • \demos\predictive-fetching-sites\
  • \experiments\predictive-fetching-sites\

There may also be a better framing for this that I'm missing. Would love your thoughts @mgechev and @khempenius. I think that once we've nailed this down we can make some minor adjustments to the branch and move it to a PR. It would be great if we could attempt to land that work before Tuesday.

Wdyt?

Use a logger with different logging levels

Currently, inside of the Guess.js webpack plugin there are a lot of statements in the form:

if (this._config.debug) {
  console.warn(...);
}

Instead of having this duplication of this._config.debug checks, it'd be better if we isolate the logic into a logger with different logging levels. We can either create a custom logger (no dependencies, smaller payload) or go with an existing one (code reuse).

Enhancement: Improve User Experience for React based Applications

As React is a fairly popular framework it would be awesome to have the initial user experience with GuessJS better. In practise, this would mean that a Router configuration file (which is either js or jsx) is read as static routes for Guess JS to parse. Either that or a json-like configuration that the user could specify in their app. Refering to conversation at JSConfEU to improve the impression of using the framework as a whole.

In addition, a method to run static apps once and generating a list over routes used would be great so that to programatic interface is needed to run GuessJS.

Gatsby plugin usage query (Getting a Webpack Error during build)

I am trying to get the gatsby plugin working in my project and during the build I get this error

WebpackError: ENOENT: no such file or directory, open '/home/travis/build/ERS-HCL/gatsby-demo-app/.cache/data.json

It would be great if you could let me know if I am missing something here

Here is the code change for including the gatsby plugin (on the same lines as your example) https://github.com/ERS-HCL/gatsby-demo-app/commit/43cadc9f0b1f6d2726fb485ab93429629465946f

The travis build error is here https://travis-ci.org/ERS-HCL/gatsby-demo-app/builds/379160574

Thanks ,
Tarun

Microsite 📃

Now that we have guessjs.com, we might want to put together a microsite for the project 🤔

@mgechev and I like the idea of using Gatsby as our static site framework. Given we already have a reference implementation of using Guess.js with it thanks to @KyleAMathews, this seems like a reasonable direction? What do folks think?

Some things to discuss regardless of stack:

  • Goals of the site
  • Information architecture
  • How we present the bundling vs non-bundling solutions (building on @khempenius's work in README)
  • Having a clear/easy getting started experience
  • Keeping it easy to edit/contribute

Once we're further along with the direction, I'm happy to try finding an owner to work on the site.

Gatsby build fails after adding gatsby-plugin-guess-js

Summary

After adding 'gatsby-plugin-guess-js' builds for my Gatsby site started failing.

Code changes

// package.json

{
  // ...
  "dependencies": { 
    "gatsby-plugin-guess-js": "^1.1.0",
  },
}
// .env

GA_VIEW_ID=int
GA_SERVICE_ACCOUNT=...@....iam.gserviceaccount.com
GA_SERVICE_ACCOUNT_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
// gatsby-config.js

const dynamicPlugins = []
const startDate = new Date()
startDate.setMonth(startDate.getMonth() - 3)
if (
  process.env.GA_SERVICE_ACCOUNT
  && process.env.GA_SERVICE_ACCOUNT_KEY
  && process.env.GA_VIEW_ID
) {
  dynamicPlugins.push({
    resolve: 'gatsby-plugin-guess-js',
    options: {
      GAViewID: `${process.env.GA_VIEW_ID}`,
      jwt: {
        client_email: process.env.GA_SERVICE_ACCOUNT,
        private_key: process.env.GA_SERVICE_ACCOUNT_KEY,
      },
      period: {
        startDate,
        endDate: new Date(),
      },
    },
  })
}

module.exports = {
  plugins: [
    // ...
  ].concat(dynamicPlugins),
}

Error log

...

info bootstrap finished - 5.486 s

error (node:51068) DeprecationWarning: Tapable.plugin
success Building production JavaScript and CSS bundles
⠀
error Building static HTML failed for path
"/blog/another-post/"



  TypeError: undefined is not a function

  - Array.map

  - render-page.js:25330 Object../node_modules/gatsby-p
    lugin-guess-js/gatsby-ssr.js.exports.onRenderBody
    /Users/bartol/javascript/bartol.dev/public/render-p
    age.js:25330:39

  - render-page.js:232
    /Users/bartol/javascript/bartol.dev/public/render-p
    age.js:232:36

  - Array.map

  - render-page.js:227 ./.cache/api-runner-ssr.js.modul
    e.exports
    /Users/bartol/javascript/bartol.dev/public/render-p
    age.js:227:25

  - render-page.js:1016 Module.default
    /Users/bartol/javascript/bartol.dev/public/render-p
    age.js:1016:3

  - worker.js:35
    [bartol.dev]/[gatsby]/dist/utils/worker.js:35:36

  - debuggability.js:313 Promise._execute
    [bartol.dev]/[bluebird]/js/release/debuggability.js
    :313:9

  - promise.js:488 Promise._resolveFromExecutor
    [bartol.dev]/[bluebird]/js/release/promise.js:488:1
    8

  - promise.js:79 new Promise
    [bartol.dev]/[bluebird]/js/release/promise.js:79:10

  - worker.js:31
    [bartol.dev]/[gatsby]/dist/utils/worker.js:31:37

  - util.js:16 tryCatcher
    [bartol.dev]/[bluebird]/js/release/util.js:16:23

  - map.js:61 MappingPromiseArray._promiseFulfilled
    [bartol.dev]/[bluebird]/js/release/map.js:61:38

  - promise_array.js:114 MappingPromiseArray.PromiseArr
⠇ Building static HTML for pages
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

[question] In which way is ML / AI used for guess' predictions ?

I am trying to get a better understanding of the features of guess.
At what point on an implementation level is ML used? Is the GA page transition data used as an input for the model application? Does the ML happen on the server and is done on the Google Analytics layer or is it run in the client (after retrieving data from GA?) ?

Thank you very much for pointing me in the right direction

[RFC] Guess function API

Prior art

Currently, guess has the following signature:

interface GuessFn {
  (route: string, links?: string[]): Predictions;
}

interface Predictions {
  [route: Route]: Probability;
}

type Route = string;
type Probability = number;

The call guess(route) returns an object literal which as keys has URLs/routes likely to be visited next, and values the associated probabilities.

If as a second argument we pass a list of URLs/routes the function will return an object with keys from the intersection between the passed data & the known possible navigations.

Few problems with this API is:

  • links: string[] seem redundant. The consumer of guess can easily filter the links
  • The returned result does not adapt based on the connection's effective type

Proposal

I'm proposing the following API:

interface GuessFn {
  (params?: GuessFnParams): Predictions;
}

interface GuessFnParams {
  route?: Route;
  thresholds?: ConnectionEffectiveTypeThresholds;
  connection?: ConnectionEffectiveType;
}

type Route = string;
type Probability = number;
type ConnectionEffectiveType = '4g' | '3g' | '2g' | 'slow-2g';

interface ConnectionEffectiveTypeThresholds {
  '4g': Probability;
  '3g': Probability;
  '2g': Probability;
  'slow-2g': Probability;
}

interface Predictions {
  [route: Route]: Probability;
}

This way, guess could be invoked without any arguments (i.e. guess()). Such call will:

  • Set params.route to window.location.pathname (since not specified)
  • Use the build-time value for params.thresholds (since not specified)
  • Use window.navigator.connection.effectiveType as value of params.connection (since not specified)
  • guess will after that query the model and filter the results by the respective connection and thresholds values and return an object literal subtype of Predictions

Ideally, we'd want to have a method prefetch() which uses guess() internally and prefetches all the bundles associated with the returned routes. The problem here is that with this low-level API we don't have access to the route-bundle mapping. For Angular & React we resolve the mapping at build-time with guess-parser.

// cc @addyosmani @KyleAMathews

Demo breaked

Visible in the console from https://guess-static-sites-demo.firebaseapp.com/

Access to XMLHttpRequest at 'https://guess-static-sites-demo.appspot.com/' from origin 'https://guess-static-sites-demo.firebaseapp.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Implement Wikipedia + Gatsby demo

👜 Carried over from docs..

This demo aims to create a Wikipedia client using Gatsby.js (by Kyle Mathews). It will take advantage of the concepts outlined in Guess.js - primarily, data-driven prefetching of data using the Google Analytics API and machine learning - to improve the page-load performance of subsequent navigations.

The application will use offline-wikipedia as a reference implementation, treating the WikiMedia/Wikipedia API as an endpoint. Given how Gatsby works, we may wish/need to have a build-time available source for Wikipedia content, however the decision on how to structure the data for the implementation best to follow Gatsby’s idiomatic way of doing things is deferred to Kyle.

The core data-driven fetching logic for the application should be powered by Guess.js.

Gatsby Wikipedia will:

  • P0: Implement the same sets of views as offline-wikipedia.
  • P1: Implement a URL flag to enable/disable ML-based prefetching.
    • Offline Wikipedia exposes this type of URL-based configuration via a flags page too, however, we could do something simpler if needed. This is to let us do before/after testing
  • P0: Use its own responsive styling. We are open to using a Material Design inspired UI as was used in offline-wikipedia, or something slightly different if clean.
  • P2: Use Gatsby 2.0 if timelines allow.
  • P0: Work cross-browser (the latest versions of Chrome, Safari, Firefox, Edge)
    • Prefetch is available everywhere except Safari (https://caniuse.com/#search=prefetch). We may wish to attempt to implement a JS-based polyfill for the feature there using a feature detect.
  • P1: Aim to have a Lighthouse score of ~90+ on WebPageTest.org/easy #perfmatters
  • P0: Be documented in a project README (e.g instructions on how to generate dev, prod builds or call any other commands necessary to use the implementation, basic architecture notes to help folks attempting to learn from the repo)
  • Have WebPageTest traces showing the before/after impact of using ML-based prefetching for the implementation

Feature Support for GuessJS in Nx Workspace

I have started to implement GuessJS in my Mono repo project but after going through the Guess source code it looks like it won't support the project structure as the path to the source folder is hardcoded in as a sibling to the package.json as per:

if (dd('@angular/cli') && exists(join('src', 'tsconfig.app.json'))) {
    return {
      type: ProjectType.AngularCLI,
      version: dd('@angular/cli'),
      details: {
        typescript: dd('typescript'),
        tsconfigPath: join(base, 'src', 'tsconfig.app.json'),
        sourceDir: 'src'
      }
    };
}

Maybe we can add a config option for srcPath in the GuessPluginConfig interface? that way people that have a different folder structure than package.json and src beside each other can use GuessJS?

I can try and make the change and open a pull request.

Trying to use Guess.js in Angular 6

Implement the Guess.JS webpack plugin with angular 6 @angular-builders/custom-webpack:browser method

config:

const { GuessPlugin } = require('guess-webpack');

module.exports = {
  plugins: [
    new GuessPlugin({
      GA: 'XXXXXX',
      runtime: {
        delegate: true,
      },
      mode: 'angular',
      layout: {
        tsconfigPath: 'src/tsconfig.app.json'
      },
      routeProvider: false
    })
  ]
};

i got this error:

node_modules/guess-webpack/dist/guess-webpack/main.js:1
(function (exports, require, module, __filename, __dirname) { !function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("guess-parser"),require("go
ogleapis"),require("flat-cache"),require("guess-ga"),require("google-oauth2-node"),require("webpack"),require("memory-fs"),require("webpack-sources"),require("lodash.template"),requi
re("path"),require("fs"));else if("function"==typeof define&&define.amd)define(["guess-parser","googleapis","flat-cache","guess-ga","google-oauth2-node","webpack","memory-fs","webpac
k-sources","lodash.template","path","fs"],t);else{var r="object"==typeof exports?t(require("guess-parser"),require("googleapis"),require("flat-cache"),require("guess-ga"),require("go
ogle-oauth2-node"),require("webpack"),require("memory-fs"),require("webpack-sources"),require("lodash.template"),require("path"),require("fs")):t(e["guess-parser"],e.googleapis,e["flat-cache"],e["guess-ga

TypeError: Cannot read property 'source' of undefined

[guess-parser] has incomplete type definitions

Hi, thanks for publishing a new version of guess-parser to npm. It works great, when used in JavaScript code. However it can't be used as part of a TypeScript codebase. The type definition file dist/guess-parser/index.d.ts currently looks like this:

export { parseRoutes } from './src/parser';
export { detect } from './src/detector';
export { parseRoutes as parseAngularRoutes } from './src/angular';
export * from './src/react';
export * from './src/preact';

It refers to the ./src directory which is not part of the npm package. I hope it is just a matter of configuring the build process. Unfortunately I don't really know how your build process works.

Ahead-of-Time bundle prefetching ✨

Currently, Guess.js analyzes the application, fetches data from Google Analytics, and builds a model. In the main chunk of the application, we introduce the following two pieces of code:

  • The model itself (could be a Markov chain, recurrent neural network, etc.)
  • Small runtime which queries the model on each page navigation

The drawback of this approach is that we need to ship to the browser the model & also introduce a runtime overhead, querying it and tracking the user's navigation.

Since at build-time, we already have the mapping between routes & bundles, we can introduce a small piece of logic in each bundle which prefetches its neighbors that are likely to be visited.

This approach has the following benefits:

  • We can reduce the bundle size a lot! We no longer need to ship the entire model and a potential framework (e.g., TensorFlow) to query it.
  • We don't have any runtime overhead - we no longer need to query the model which on mobile can be inefficient for a deep neural network.

Guess.js Webpack plugin

Goal: Lowering the friction for unlocking @MLX’s capabilities

Authors: Joint proposal from Addy and Minko

In Machine Learning: Data-driven Bundling, a set of packages was introduced for getting started with data-driven bundling (DDB). Together, these packages enabled a developer to leverage their analytics to generate data-driven bundle layouts and code for intelligently prefetching JavaScript chunks to improve page-load performance.

These modules accomplished the following tasks (from the blog post):

  • @mlx/ga - fetched structured information from the Google Analytics API. This provides a navigation graph that needs to be translated into a page graph. @mlx/ga can automatically do this if supplied with all the paths in the application.

  • @mlx/parser - extracts the routes of our application, finds the associated chunk entry points of the lazy-loaded routes and builds the routing bundle tree. Once the application is parsed with @mlx/parser, get an array with all the routes, their corresponding chunk entry points, and their parent chunk entry points.

  • @mlx/cluster - performs a clustering algorithm based on the data from Google Analytics and the bundle routing tree, from @mlx/parser.

  • @mlx/webpack - webpack plugins which use @mlx/parser and @mlx/cluster in order to produce data-driven bundle layout for the application, and generate code for data-driven pre-fetching.

Guess plugin

In order to lower the friction for using these packages, we propose a Webpack plugin that:

  • Allows a developer to start using data-driven bundling in < 5 minutes

  • Attempts to remove some of the manual work involved in intermediate steps

    • e.g generating a data.json file with Google Analytics navigation graph data needed for later stages. This could be generating behind the scenes for you and passed along to subsequent steps.
  • Reduces the configuration overhead for each package

    • Where possible we will provide sane defaults and simplify decision making. e.g in @mlx/parser, we could expose a way for developers to inform us which framework they are using so we can pick the correct package to extract routes.

API

An API sketch for this webpack plugin would be:

new GuessPlugin({

  GA: '8765456',       
  // *String*. Supply the ViewID needed by @mlx/ga
  // The first time the plugin loads, if a ViewID is supplied we will attempt
  // to authenticate the user, taking them to a browser. We will then get a 
  // session token and store this so that auth is not required in future. This 
  // simplifies the need to setup a credentials.json file manually. 

  mode: 'react'        
  // String: `mode` will accept one of three values: react, angular or gatsby
   // For each `mode` supported, an @mlx/parser must be available which 
   // can extracts routes of our application, find the associated chunk
   // entry points of the lazy-loaded routes and build the routing bundle tree
})

Open questions:

  • Should we expose a way to provide more granular configuration options back to the other packages? Such as specifying the period -> startDate and endDate for GA

    • This could be done in a few ways. e.g { ga: { }, parser: {}, cluster: {} }
  • Or should we encourage users needing further configuration needs to just use the other packages directly?

  • Are there any configuration options that are absolutely necessary for the above?

Dependencies

In order to support a ‘gatsby’ mode, we will need a Gatsby equivalent of the @mlx/parser packages for React and Angular. This is something we can pursue as part of our collaboration with Gatsby.

API requires

Parcel Support

Could I use Guess with parcel bundler, or it's limited to webpack?

enable Travis CI

Currently Travis CI is not enabled but there is a config. Would be great to have automatic testing of every build / push and PR.

[Docs] Type of sites we are targeting

A common question I get is what size/scale of site Guess.js is targeting. I think it's worth documenting this a little more clearly. My two cents:

  • Sites with nested pages (e.g have a minimum of three levels of nesting). Good examples: news and publisher sites, e-commerce, large SaaS sites)
  • Sites who have already been using Analytics tracking for a while (likely to have a rich set of data that can be used for predictive fetching).

Advertising package

It looks like this project depends on https://github.com/feross/funding, a project intended to show advertising in a projects build log.

I'm not familiar with your project, I'm just looking through a list of projects that depend on feross/funding. It's my understanding that right now there aren't any advertising messages actually showing, but if you're uncomfortable with the possibility of advertisements in build logs that's something you might want to look into.

Cache the GA report

We should cache the GA report for given time range so we can reuse it on frequent calls of the GuessPlugin.

Unable to build the React Project uisng webpack guess plugin

I am not able to build my react project using the webpack guess plugin with below error

95% emitting/Users/ajasingh/Work/CXE-UECP/node_modules/webpack-sources/lib/ConcatSource.js:42
source += typeof child === "string" ? child : child.source();
^

TypeError: child.source is not a function
at ConcatSource.source (/Users/ajasingh/Work/CXE-UECP/node_modules/webpack-sources/lib/ConcatSource.js:42:56)
at Compiler.writeOut (/Users/ajasingh/Work/CXE-UECP/node_modules/webpack/lib/Compiler.js:338:26)
at Compiler. (/Users/ajasingh/Work/CXE-UECP/node_modules/webpack/lib/Compiler.js:328:20)
at /Users/ajasingh/Work/CXE-UECP/node_modules/webpack/node_modules/async/dist/async.js:3110:16
at eachOfArrayLike (/Users/ajasingh/Work/CXE-UECP/node_modules/webpack/node_modules/async/dist/async.js:1069:9)
at eachOf (/Users/ajasingh/Work/CXE-UECP/node_modules/webpack/node_modules/async/dist/async.js:1117:5)
at Object.eachLimit (/Users/ajasingh/Work/CXE-UECP/node_modules/webpack/node_modules/async/dist/async.js:3172:5)
at Compiler.emitFiles (/Users/ajasingh/Work/CXE-UECP/node_modules/webpack/lib/Compiler.js:317:20)
at /Users/ajasingh/Work/CXE-UECP/node_modules/mkdirp/index.js:30:20
at FSReqWrap.args [as oncomplete] (fs.js:140:20)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] build: cross-env NODE_ENV=production EQIX_APP=ecp EQIX_ENV=dev webpack --config internals/webpack/webpack.prod.babel.js --color -p --progress
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR! /Users/ajasingh/.npm/_logs/2019-07-28T03_21_26_080Z-debug.log

The Angular parser does not properly recognize lazy routes

For example:

// app.ts
{
  path: 'foo',
  loadChildren: 'foo/foo.module#FooModule'
}

// foo.ts
{
  path: 'index',
  component: FooComponent
}

The parser will return two URLs, although there's only one:

foo - lazy (wrong)
foo/index - not lazy (wrong)

Repository structure

Probably good to decide on this as a team :)

Proposed top-level folders

  • /packages
  • /docs (for design docs, moving things from Google Docs over)
  • /infra (previous called /scripts in mlx)
  • /demos
  • CONTRIBUTING.md
  • README.md
  • LICENSE
  • .gitignore
  • {package, package-lock, yarn, other package manager files}

@mgechev wdyt? anything worth changing or adding here?

SPFJS - GUESS

Hi @addyosmani @mgechev , this is a little unrelated topic ... but i was building some micro front end services kind of framework that fetch content and render to page as fragments etc ...

I saw SPF-js from google and found very futuristic for that time and is great and i see guess-js doing similar thing in another level - but they share some similar goals --- one of them is prefetch content to improve experience for user .

But today with SW and all browser capabilities , what do you recommend for an architecture similar to SPF-JS sites .

Big web application that needs to render fragments from different teams in same page , if possible all SSRendered . being independent sharing routing from server to client.

I know is kind of silly question but was the unique place i can sit down both of the you.

GuessPlugin throws error with Angular 8 / Node 10

What

After upgrading guess-angular demo project to Angular 8 and when i try to run the build command ng build on Node v10.15.0(npm v 6.4.1) , it throws below error. Looks like issue with GuessPlugin

> ng build

 95% emitting GuessPlugin(node:21777) UnhandledPromiseRejectionWarning: Error: Cannot find the entry point for /Users/kumaran/mydrive/personal/guess-angular/src/app/about/about.module.ts
    at d (/Users/kumaran/mydrive/personal/guess-angular/node_modules/guess-parser/dist/guess-parser/index.js:1:3675)
    at y (/Users/kumaran/mydrive/personal/guess-angular/node_modules/guess-parser/dist/guess-parser/index.js:1:4314)
    at /Users/kumaran/mydrive/personal/guess-angular/node_modules/guess-parser/dist/guess-parser/index.js:1:6338
    at x (/Users/kumaran/mydrive/personal/guess-angular/node_modules/guess-parser/dist/guess-parser/index.js:1:5293)
    at visitNodes (/Users/kumaran/mydrive/personal/guess-angular/node_modules/typescript/lib/typescript.js:16514:30)
    at Object.forEachChild (/Users/kumaran/mydrive/personal/guess-angular/node_modules/typescript/lib/typescript.js:16681:24)
    at NodeObject.forEachChild (/Users/kumaran/mydrive/personal/guess-angular/node_modules/typescript/lib/typescript.js:120242:23)
    at x (/Users/kumaran/mydrive/personal/guess-angular/node_modules/guess-parser/dist/guess-parser/index.js:1:4840)
    at visitNodes (/Users/kumaran/mydrive/personal/guess-angular/node_modules/typescript/lib/typescript.js:16514:30)
    at Object.forEachChild (/Users/kumaran/mydrive/personal/guess-angular/node_modules/typescript/lib/typescript.js:16694:21)
    at NodeObject.forEachChild (/Users/kumaran/mydrive/personal/guess-angular/node_modules/typescript/lib/typescript.js:120242:23)
    at x (/Users/kumaran/mydrive/personal/guess-angular/node_modules/guess-parser/dist/guess-parser/index.js:1:4840)
    at visitNodes (/Users/kumaran/mydrive/personal/guess-angular/node_modules/typescript/lib/typescript.js:16514:30)
    at Object.forEachChild (/Users/kumaran/mydrive/personal/guess-angular/node_modules/typescript/lib/typescript.js:16681:24)
    at NodeObject.forEachChild (/Users/kumaran/mydrive/personal/guess-angular/node_modules/typescript/lib/typescript.js:120242:23)
    at x (/Users/kumaran/mydrive/personal/guess-angular/node_modules/guess-parser/dist/guess-parser/index.js:1:4840)
(node:21777) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:21777) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

How to Reproduce the Issue

Get the code from my forked repo and make sure you are using Node 10

  • Clone the repo and checkout the master branch

    git clone https://github.com/kumaran-is/guess-angular.git
    cd guess-angular
    npm install
    

Run the build and try to launch the application in http://localhost:4200

npm run build && http-server ./dist/guess-angular  -p 4200

Fail when login with Google when using guess-webpack

I try to using guess-webpack with my nuxt.js. When I serve my project my browser is open Google login page. When login complete and redirect back to localhost:xxxxx < some random port this page is empty. How I fix it?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.