pwa-module icon indicating copy to clipboard operation
pwa-module copied to clipboard

Only caches visited routes

Open akirarika opened this issue 5 years ago β€’ 12 comments

Excuse me!

I'm making a Note App,

Notes is synchronized through websocket and written to IndexedDB with network,

Read historical notes from indexeddb without network,

But latest version 3.0.0-beta.20 only caches visited routes (2.6.0 it works)

1

I wish users to have access to all routes without a network, What do I need to do?

Thank you for your help (and #24)

akirarika avatar Jul 23 '20 09:07 akirarika

Having the same issue using v3.0.2.

I want to pre-cache some routes (if not all) so that even though the user may not have visited that route (page) while online, it would work offline.

nuxt.config.js

pwa: {
	workbox: {
		cacheNames: {
			prefix: "my-app",
			suffix: "v1",
			googleAnalytics: "test-ga"
		},
		offlineAssets: ["/400.png"],
		offlineAnalytics: true
	}
}

sw.js

// Precache assets

workbox.precaching.precacheAndRoute([
  "/400.png"
], {
  "cacheId": "APP-prod",
  "directoryIndex": "/"
})

// --------------------------------------------------
// Runtime Caching
// --------------------------------------------------

// Register route handlers for runtimeCaching
workbox.routing.registerRoute(new RegExp('/_nuxt/'), new workbox.strategies.CacheFirst ({}), 'GET')

There is no workbox.precaching.precacheAndRoute happening for routes!

Youhan avatar Aug 26 '20 17:08 Youhan

I have the same problem, user must visit the route in online mode in order to be cached for future offline mode.

codehunter12345 avatar Oct 08 '20 16:10 codehunter12345

Hello, did anyone find a solution? Thanks :)

narduin avatar Feb 13 '21 18:02 narduin

Facing the same limitation. It would be good to have a precachedRoutes option like this: precachedRoutes: ['/home', '/about', '/tasks']

So when the user access any one of this routes in offline it will render even if the user never entered before on this route.

diegomr86 avatar Feb 19 '21 18:02 diegomr86

Is there any news on this ?

Why this change has been made ? => I guess this is about "Nuxt smart pre-fetch" feature. => This cause issues to fetch pages that haven't been pre-fetched ...

How easy would it be to add a configuration option that would allow bringing back old behavior ?

homersimpsons avatar Aug 02 '21 14:08 homersimpsons

@narduin The only solution that is currently working for me is downgrading @nuxt/pwa to 2.6.0. That way it preloads the content within /_nuxt and it becomes accesible even if the user did not visit it before.

I get the new smart prefetching can make online websites feel quicker over time but it is really useless for out of the box offline experiences. Hope a configuration that addresses it can be introduced so I can move forward to the latest version again.

quezadaesteban avatar Aug 09 '21 03:08 quezadaesteban

Hi there,

Having the same problem. Only visited routes are cached and I would like to have all routes precached. I'm using @nuxtjs/pwa v3.3.5 and by reading this thread I understood that a "solution" is to downgrade to v 2.6.0 but I'd prefer to find a way of making it work with the last version!

Did anyone find a solution? Thx!

cdefy avatar Nov 03 '21 09:11 cdefy

I have the some problem in @nuxtjs/pwa v3.3.5 too, so I fixed it, refer to v2.6.0 code. Here is the snippet code. I think maybe this will help somebodyπŸ˜„.

  1. copy the sw.template.js from node_modules\@nuxtjs\pwa\templates\workbox\sw.js into your root folder and add some code.
const options = <%= JSON.stringify(options.swOptions) %>

importScripts(...[options.workboxURL, ...options.importScripts])

initWorkbox(workbox, options)
workboxExtensions(workbox, options)
precacheAssets(workbox, options)
cachingExtensions(workbox, options)
runtimeCaching(workbox, options)
offlinePage(workbox, options)
routingExtensions(workbox, options)

function getProp(obj, prop) {
  return prop.split('.').reduce((p, c) => p[c], obj)
}

function initWorkbox(workbox, options) {
  if (options.config) {
    // Set workbox config
    workbox.setConfig(options.config)
  }

  if (options.cacheNames) {
    // Set workbox cache names
    workbox.core.setCacheNameDetails(options.cacheNames)
  }

  // add this ↓↓↓↓↓
  if (options.cacheOptions) {
    // Set workbox default cache
    workbox.precaching.precacheAndRoute([], options.cacheOptions)
  }

  if (options.clientsClaim) {
    // Start controlling any existing clients as soon as it activates
    workbox.core.clientsClaim()
  }

  if (options.skipWaiting) {
    workbox.core.skipWaiting()
  }

  // ignore...
}

// ignore...

  1. Create the sw-generate.ts in your plugins folder and use it overwrite sw.js when nuxt generate done.
import * as fs from 'fs';
import * as path from 'path';
import * as crypto from 'crypto';

export function overrideSW(generator) {
  // read _nuxt folder file and generate manifestEntries.
  const fileRegex = /^[a-z0-9]{7}.js$/;
  const files = fs.readdirSync(generator.distNuxtPath);
  const manifestEntries = files
    .filter((f) => fileRegex.test(f))
    .map((f) => {
      return {
        url: `/_nuxt/${f}`,
        revision: generateHash(f),
      };
    });
  
  // replace manifestEntries to swFileContents
  var swPath = path.join(generator.distPath, 'sw.js');
  let swFileContents = fs.readFileSync(swPath, 'utf8');
  const entriesString = JSON.stringify(manifestEntries, null, 2);
  swFileContents = swFileContents.replace(
    /(\.precacheAndRoute\()\s*\[\s*\]\s*(\)|,)/g,
    `$1${entriesString}$2`
  );

  // write swFileContents to sw.js
  var swPath = path.join(generator.distPath, 'sw.js');
  fs.writeFileSync(swPath, swFileContents);
}

function generateHash(value) {
  var md5 = crypto.createHash('md5');
  md5.update(value);
  return md5.digest('hex');
}
  1. Modify your nuxt config. Use your customer sw template and use overrideSW method to overwrite sw.js.
import { overrideSW } from './plugins/sw-generate';

module.exports = {
  // ignore...
  pwa: {          
    workbox: {       
      swTemplate: './sw.template.js',
    },
  },
  hooks: {
    generate: {
      done(a) {
        overrideSW(a);
      },
    }
  },
}
  1. Execute npm run build, the dist/sw.js generate result will like this.
// ignore ...

function initWorkbox(workbox, options) {
  if (options.config) {
    // Set workbox config
    workbox.setConfig(options.config)
  }

  if (options.cacheNames) {
    // Set workbox cache names
    workbox.core.setCacheNameDetails(options.cacheNames)
  }

  // add this ↓↓↓↓↓
  if (options.cacheOptions) {
    // Set workbox default cache
    workbox.precaching.precacheAndRoute([
  {
    "url": "/_nuxt/047bf65.js",
    "revision": "92c2ff862cedb6fdfb0aa04c26e27b15"
  },   
  {
    "url": "/_nuxt/d171ee6.js",
    "revision": "6342de608795a344ce16a58921ab63bf"
  },
  // ...
], options.cacheOptions)
  }

  if (options.clientsClaim) {
    // Start controlling any existing clients as soon as it activates
    workbox.core.clientsClaim()
  }
}

// ignore...

p.s: When I use the v2.6.0, I get the error message see blow, so I use v3.3.5 and use above approach, the error is gone and every work fine like you use the v2.6.0.

ERROR  (node:47524) DeprecationWarning: Tapable.plugin is deprecated. Use new API on .hooks instead 
(Use `node --trace-deprecation ...` to show where the warning was created)

changemyminds avatar Apr 09 '22 17:04 changemyminds

Experiencing the same issue.

Thank you so much for your effort @changemyminds, this helped me a lot!

klickparkdominik avatar May 06 '22 11:05 klickparkdominik

Thanks @changemyminds πŸ™πŸ½

For some reason not all components in my project get pre-cached, e.g. from the following items in the /components dir

Screen Shot 2022-09-16 at 15 48 57

these are not getting pre-cached:

Calendar.vue
Images.vue
ItemIndicators.vue
List.vue
Notes.vue
bullet/Bullet.vue
bullet/Compilation.vue
bullet/CompilationItem.vue
Placeholder.vue
dialog/Edit.vue

Any idea why?

toniengelhardt avatar Sep 16 '22 14:09 toniengelhardt

@toniengelhardt Could you reproduce your project or code ?

changemyminds avatar Sep 28 '22 15:09 changemyminds

@changemyminds unfortunately no, it's a quite large private project. But there is really nothing special about it that should have an impact on this...

toniengelhardt avatar Sep 28 '22 16:09 toniengelhardt