Hacker News new | ask | show | jobs
by jashkenas 4716 days ago
The fundamental problem with attempting to transparently support querystrings on the client-side -- touched on a bit in this article, but not explained completely, is this:

Querystrings are a server-side convention for URLs containing parameters -- the browser doesn't traditionally parse them. If you ask for document.location.search, you'll get back an opaque string containing the query part that you'll have to parse yourself.

The point of Backbone's router is to be able to transparently support both pushState-based routing, with real URLs, as well as onhashchange-based routing, for older browsers that can't do real URLs via JavaScript. So, if you add querystring generation and parsing support to Backbone's router (as some plugins do), and use pushState, everything starts off looking peachy. But as soon as you run into an older browser, and try to fall back to the hash-based URL equivalent, you run into trouble:

    /app?query=string#home?query=other
... now you have the possibility to have to merge two different sources of query string, and still keep transparent redirects working back and forth between the two schemes.

I'd be more than happy to merge an implementation that supports them -- but that implementation needs to solve this particular problem, and have a relatively bulletproof way of supporting the querystring logic parsed out of real URLs and transferred to the fragment, and vice-versa ... and also has to have a strategy for dealing with URLs of the above breed. The devil, as always, is in the details.

2 comments

> now you have the possibility to have to merge two different sources of query string

Not really:

  if hashMode and queryStringInHash
    parseQueryStringFromHash
  else
    parseRealQueryString
You don't have to merge. Just if you modify the query string and are in "hashMode" then just push the "real querystring" elements you parsed first into the "hashquery string".
The thing is that it has to work cross-browser. If an IE user copies an URL with both a fragment query string and a real query string and then shares it with a Firefox user, the URL should resolve to the same thing (and the same thing the other way around).

Not impossible by any means, but, as Jeremy points out, it involves subtle details :)

Right-o. PushState-supporting users copying URLs and sending them to IE8 and IE9 folks is one thing, as is the opposite direction.

In addition, some folks currently like to mount their Backbone.js applications at a root URL that contains a query string, for example:

    todolist.com/app?org=nsa#location
> some folks currently like to mount their Backbone.js applications at a root URL that contains a query string

That seems like the root of the problem. It seems like querystrings could otherwise be solved, but this case would certainly introduce a problem for pushState-incompatible browsers.

Is there a reason this kind of app root URL isn't considered bad practice that doesn't need to be supported? Everything about it seems wrong - now you're trying to put part of the path after the querystring.

"Doctor, it hurts when I do this."

"Then don't do that."

I love backbone, and it works well for us. We hacked in support for full paths and query parameters and will likely end doing full page reloads for IE8/IE9 (IE10 will support push state anyway)

It seems mighty unfair that we can't have nice things because Microsoft took so long to roll out push state.

Well it's les simple that I though but it's still seems doable. I'll probably try to submit a PR about that. Is there any previous PR or issue that I should rea first ?
Not really a problem... does "app" conflict with "home" in your case? If so, then there's also an issue here... if not, then why not? Also, if not, then why not take the same approach to query strings.

    var querystring = {};
    //add actual querystring (prior to #) parameters
    //add hash's querystring, overwriting any already defined keys
    return querystring;
It's not that hard.