justinfagnani / route

A client + server routing library for Dart
BSD 3-Clause "New" or "Revised" License
114 stars 40 forks source link

Work with browsers that don't support pushState #2

Closed justinfagnani closed 11 years ago

justinfagnani commented 11 years ago

There are two options:

  1. Use URL fragments. This would mean that UrlPattern.parse() and reverse() know how to handle fragments, reverse() is somehow aware of browser support for pushState, and that the server can serve a generic page since it doesn't receive fragments.
  2. Simply refresh the entire page.

I'm not aware of a real polyfill for pushState.

justinfagnani commented 11 years ago

I think fragments are the better way to go, even if more complicated to implement. No reason to offer a bad experience to IE9 users if we can avoid it.

To support URL fragments, the definition of a UrlPattern will have to change. Instead of a single path, like "/app/resource/(\w+)/", there will need to be an indicator of where to split the pattern between path and fragment. A hashbang ('#!') will work well. The example pattern would become "/app#!resource/(\w+)/".

hashbangs are considered very harmful by many, but here we'll support both hashbang and full path versions of each URL, so it should be fine.

On most browsers the hashbang would just be replaced with a '/' right before a pushState. On browsers that don't support pushState the hashbang would be left in and window.location is used. The code to do this will be in client.dart so there's no dependency in url_pattern.dart on dart:html.

UrlPattern.matches() is trickier. On the client, we need to match against the URL path and fragment and return true for both hashbang and path versions of the URL. On the servers that don't do server-side rendering we need to match against full paths, or the path before the fragment (base path?). Both will typically send back the same HTML page (for single page apps). On servers that do server-side rendering the full path URL and base path may be sent to different handlers.

UrlPattern.matches(String str) should match against full paths and base path + #! + fragment, but not against base paths. A new method, maybe matchesBase(String str) will match against both full paths and base paths.

UrlPattern could be extended to also produce a pattern that matches against "ugly URLs" according to Google's crawlable AJAX convention. It would need to support query parameters and map the fragment to the _escapedfragment parameter.

@jmesserly @jacob314 what do you think?

justinfagnani commented 11 years ago

Implemented plain fragment support for '#' characters. Nothing special for hashbangs yet.