Skip to content
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

navigateFallback / App Shell routing #169

Closed
jeffposnick opened this issue Jan 23, 2017 · 8 comments
Closed

navigateFallback / App Shell routing #169

jeffposnick opened this issue Jan 23, 2017 · 8 comments
Assignees

Comments

@jeffposnick
Copy link
Contributor

(This is a continuation of the discussion from #136)

CC: @addyosmani @gauntface

Library Affected:
sw-routing

An important piece of SW functionality when using the App Shell model is allowing the SW to fulfill some or all navigation requests with the cached App Shell HTML document.

This is accomplished in sw-precache via the navigateFallback option (which allows you to define the HTML document's URL) and the navigateFallbackWhitelist option (which allows you to only route a subset of navigation requests to the App Shell, if your site also has non-App Shell URLs).

This functionality can be achieved cleanly using a sub-class of goog.routing.Route that checked for request.mode === 'navigation' as part of its match predicate, and used a goog.runtimeCaching.CacheFirst handler to return the App Shell.

The main question, as I see it, is what the class should be called and how it should be configured. Here's a strawman proposal:

class AppShellRoute extends Route {
  /**
  appShellUrl is a string
  urlWhitelist is an optional Array of RegExps
  */
  constructor({appShellUrl, urlWhitelist}) {
     // Use the provided configuration...
  }
}

Rather than using the "navigate fallback" terminology, which can be confusing and hard to explain, this just goes all-in with the App Shell terminology. It won't make much sense if people don't know what an App Shell is, but if you don't know what that is then you probably shouldn't be using the class to begin with.

@gauntface
Copy link

I always liked the navigateFallback analogy as I tend to think this is less of an "appshell thing" and more of a single page app feature so personally I'm in favor of sticking with a name along the lines of NavigationFallbackRoute or NavigateFallbackRoute.

The stram API also looks good. Would it be possible to pass in strings into the urlWhitelist if you know the specific URL's that should be matched?

i.e. new AppShellRoute({appShellUrl: '/spa.html', urlWhitelist: ['/', '/about', '/contact', '/blog'})

@jeffposnick
Copy link
Contributor Author

I'm fine with NavigateFallbackRoute if other folks are. https://github.com/NekR/offline-plugin has borrowed that terminology as well, so I guess it's become something of a standard.

There are a few ways of thinking about configuring the behavior:

  1. Only support a whitelist, and it defaults to matching everything (i.e. /./).
  2. Only support a whitelist, and it defaults to empty.
  3. Only support a blacklist, and it defaults to empty.
  4. Support both a whitelist and black, both defaulting to empty.

Approach 1 works well for the my-site-is-100%-SPA use case, and if we went with that, would you still think it's useful to whitelist specific URL strings? The default behavior would route everything to your App Shell, which is what SPAs want. Since sw-precache currently takes approach 1, using that for NavigateFallbackRoute would make it easier to migrate, since the semantics are the same.

Approach 2 doesn't seem useful as it forces folks to provide additional configuration for a common use case.

For the my-site-is-95%-SPA-but-some-URLs-aren't use case, a blacklist might make more sense that a whitelist. That's a point in approach 3's favor.

Approach 4 is the most flexible, but then you need to come up with an intuitive policy as to how to handle a URL that matches both the white and blacklist, which I think disqualifies that approach.

@gauntface
Copy link

With the 95% SPA scenario, would the solution actually involve having routes for non-SPA pages and other wise falling back to the SPA?

I can picture scenarios for both whitelist and backlist.

  • Whitelist: "I have specific pages that should direct to SPA, I want other pages to show normal failure page".
  • Blacklist: "All my pages are SPA, but I need my admin panel to ONLY go to the network".

To me it'll depend on the user and how they think about their web app / routing.

Regarding duplication matches of whitelist and blacklist I'd probably just make blacklist take priority (i.e. no blacklist site will every use the fallback), if it's not in the blacklist, then we check if it's in the whitelist.

While this can be confusing to developers, it's something that a debug flag would help with.

@jeffposnick
Copy link
Contributor Author

With the 95% SPA scenario, would the solution actually involve having routes for non-SPA pages and other wise falling back to the SPA?

It might mean having routes with, e.g., stale-while-revalidate handlers for the non-SPA pages, or it might mean not having any routes at all and just relying on the browser's default network behavior.

Regarding duplication matches of whitelist and blacklist I'd probably just make blacklist take priority (i.e. no blacklist site will every use the fallback), if it's not in the blacklist, then we check if it's in the whitelist.

Okay, I'll move ahead with a white + blacklist, with a runtime warning if a URL matches both.

@jeffposnick jeffposnick self-assigned this Feb 1, 2017
@gauntface
Copy link

👍 SGTM

@addyosmani addyosmani modified the milestone: Service Worker Framework (beta) Feb 17, 2017
@jeffposnick
Copy link
Contributor Author

Copying over the comment in #234 to be tracked here:

This lays the groundwork for App Shell routing. I think the next step would be to take this and add in some logic in sw-lib that made use of NavigationRoute coming after the route that matches precached assets, and allowed the developer to cleanly specify the URL that corresponds to their App Shell HTML.

@gauntface
Copy link

@jeffposnick are you happy doing this or would you like to pass the buck? (More than happy for you to do this - just wanted to check expectation).

@jeffposnick
Copy link
Contributor Author

I'm happy to do it. We need to have another discussion about the API surface, though, since we're now dealing with the higher level abstraction where a different set of defaults might make sense.

import swLib from 'sw-lib';
// Set up the precaching bits...
swLib.cacheRevisionedAssets(manifest);

// Proposed interface:
// opt_whitelist is optional, and defaults [/./]
// opt_blacklist is optional, and defaults to []
swLib.router.navigationRoute('/shell.html', opt_blacklist, opt_whitelist);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants