[whatwg] Criticism of pushState (was Global Script proposal)

Dimitri Glazkov dglazkov at chromium.org
Tue Sep 8 07:05:40 PDT 2009


On Mon, Sep 7, 2009 at 4:40 PM, Justin Lebar<justin.lebar at gmail.com> wrote:
>> Dimitri Glazkov wrote:
>> But more to the point, I think globalScript is a good replacement for
>> the pushState additions to the History spec.
>
> I'm not sure I agree.  pushState lets you change the URI very quickly,
> without doing any kind of navigation at all.  To emulate a pushSate
> with globalScript, you'd have to save and restore the whole document,
> and the browser would still have to do at least one network request,
> unless you were only changing the hash of the URI.

pushState does let you change the URI very quickly -- you're exactly
right! But it doesn't do anything else. The implementor still has to
grapple with the same problems as they did with the hash-navigation,
and that doesn't seem like much of an improvement.

>
>> I am becoming
>> somewhat convinced that pushState is confusing, hard to get right, and
>> full of fail. You should simply look at the motivation behind building
>> JS-based history state managers -- it all becomes fairly clear.
>
> Could you elaborate on these points?  It seems to me that pushState
> attacks a specific problem and delivers a simple solution which is
> much better than the current workarounds (using the URL's hash to
> identify a page and store state).  Yes, it's nontrivial to develop an
> AJAX app which uses pushState and works correctly with bookmarking and
> page refreshes.  On the other hand, pushState makes this a lot easier
> than it would be otherwise.

The problem pushState attacks is specific, correct. But IMHO it is too
specific -- you're trying to treat the symptom, not the root cause.
Why do developers want to reinvent the entire URL hierarchies -- and
elaborate ways of managing them! -- inside of the hashes? Because they
want cheap navigation. Why do they want cheap navigation? Because
there is no easy way to preserve tons of JS code that's been already
loaded and primed. With globalScript, they no longer have this
problem.

Just think about it -- load jquery (for instance) with tons
extensions, and reuse it on any page of your site. No need to load it
or re-initialize. Ideally, I should be able to do this:

function onContentLoaded() {
 if (!globalObject.loaded())
   globalObject.load();

 document.body.appendChild(globalObject.uiNode());
}

.. and only hit .load() method once per browsing session.

Your entire controller survives navigation. Your pages become the
model, only delivering the minimum of markup (data). It's a much more
natural model from pretty much any reasonable perspective (that I know
of).

Then why the heck would we want to come up with a fancier way to
provide hash-navigation?

>> My big issue with pushHistory is that it messes with the nature of the
>> Web: a URL is a resource you request from the server. Not something
>> you arrive to via clever sleight of hand in a user agent.
>
> Like it or not, this ship has already sailed.  When I load Gmail, I'm
> taken to https://mail.google.com/mail/#inbox, but my browser never
> sends "#inbox" to the server as part of the HTTP request.  Pandora and
> Facebook do something like this too.  Perhaps the new intuition is
> that a URL tells you how to get back to where you were.

Again, you're diagnosing a symptom. Hashes were never supposed to go
back to the server. These hash-navigation controllers are workarounds.
Let's not create a better workaround.

Once you introduce pushState, you deviate from the normalcy -- now you
can have a URL in the address bar that the user agent hasn't requested
from the server.

>> So, you've managed to pushState your way to
>> a.com/some/path/10/clicks/from/the/home/page. Now the user bookmarks
>> it. What are you going to do know?
>
> When reading this message in Gmail, my browser shows that I'm at
> https://mail.google.com/mail/#label/WhatWG/{guid} .  If I bookmark
> this page and go back to it, Gmail takes me back to this exact
> message.  There's no actual resource named #label/WhatWG/{guid} on
> Google's servers, but the URL I bookmarked is sufficient to identify
> where I was, and Gmail's servers were intelligent enough to take me
> there.

It's not the server that's intelligent. It's the URL controller in
Gmail's JS code -- in addition to the one on the server. Since hash is
never sent to the server, the user-agent-side hash-navigation
controllers have to be intelligent enough to figure out what to do.
That's another point where I see a failing of the pushState concept:
once you extend this to actual URLs, they will have to be just as
smart or even smarter to figure out the state to which they are
supposed to bring the page. So we're not really saving much beyond
cosmetics.

> Maybe you think that Gmail's URLs should name "real" resources; maybe
> they should look like
> https://mail.google.com/mail.cgi?label=WhatWG&message={guid} or
> something.  I'm not convinced this is better, but even if it suits
> you, pushState still helps you navigate between mail.cgi?label=WhatWG
> and mail.cgi?label=Drafts without a page refresh.

It's not that it's better. I really don't care about how the URLs
look. I just want the Web development to be easier. And in my humble
opinion, building a request controller in JS and essentially a whole
alternative reality navigation system using hashes is not.

> I think pushState API is really useful, but what do I know?  We're
> going to land it in Firefox trunk Real Soon Now, so developers and
> members of this list will be able to play with it and decide for
> themselves whether it's the right API to solve the problem at hand.

Indeed. It may take a while, and in the meantime we can keep arguing
about its merits :)

:DG<


More information about the whatwg mailing list