Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it safe to use window.history.replaceState() in <head>?

Tags:

javascript

I'd like to remove the #_=_ artefact that Facebook adds to URLs when a user logs in on my website.

I'm using this script:

if (window.location.hash === '#_=_') {
    const uri = window.location.toString();
    const withNoHash = uri.substring(0, uri.indexOf('#'));
    window.history.replaceState({}, document.title, withNoHash);
}

I'd like the script to fire as soon as possible, so I've put it in the <head> and it seems to work fine on Chrome & Firefox.

Is it standardized that the window.history API is ready when the script executes in <head>?

(and document.title, by the way).

like image 881
BenMorel Avatar asked Nov 05 '20 18:11

BenMorel


People also ask

What does Window history replaceState do?

The History. replaceState() method modifies the current history entry, replacing it with the state object and URL passed in the method parameters. This method is particularly useful when you want to update the state object or URL of the current history entry in response to some user action.

Can I use replaceState?

This feature is deprecated/obsolete and should not be used.

What is the difference between pushState and replaceState?

The big difference is, that while pushState will create a new entry in the browser's history, replaceState will only replace the current state. As a side effect of this, using the replaceState method will change the URL in the address bar, without creating a new history entry.

What is window history?

history. The Window. history read-only property returns a reference to the History object, which provides an interface for manipulating the browser session history (pages visited in the tab or frame that the current page is loaded in). See Manipulating the browser history for examples and details.


1 Answers

On the topic of window

Standard browsers implement a Window interface, from which a global window property is exposed to javascript in the documents. Subsequent navigation will load different documents in the same Window even if new tabs are opened. So the properties you use, like window.location and window.history inside your document, would be present in the Window before a user navigates to your page (from Facebook) and therefore be available to your document.

This also applies to when you directly load your page in a new browser window - the document will have access to the window property. More on Window and window here: https://developer.mozilla.org/en-US/docs/Web/API/Window

If you are worried about your page getting loaded by a non-standard browser, or for some reason, the window property's history and location properties are overridden, you could just do a check to see if they are available, before calling them with:

if (window && window.location && window.location.hash) {
// safely use window.location.hash here
}

But even then, the error would be suppressed by the browser on the client-side.

On the topic of using document.title with replaceState()

The specification specifies it as a string, so by design, it will return an empty string if it is not set. There are no warnings from Mozilla for using it before a document is fully loaded. More here https://developer.mozilla.org/en-US/docs/Web/API/Document/title

Here are some quick tests I did to see if it is in fact the case using an HTML page with no <title> tag.

<html>
    <head>
        <script>
            console.log("title", document.title)
            window.history.replaceState({}, document.title, "newHMTL.page");
        </script>
    </head>
    <body>
    Testing
    </body>
</html>

There are no errors or warnings as expected.

On the topic of replaceState

The specification points out that most browsers ignore the title / document.title parameter that you pass to replaceState:

Most browsers currently ignore this parameter, although they may use it in the future. Passing the empty string here should be safe against future changes to the method. Alternatively, you could pass a short title for the state.

So while I had a page ready, some more quick tests. Setting the title to null; undefined; and a function; and then passing it to replaceState did not change the title in the history nor throw errors in Chrome when there was a <title> tag or not. So 6 tests.

<html>
    <!-- <title>title</title> -->
    <head>
    <script>
        let title = () => alert("huh?") //null; //undefined;
        console.log("Title", title);
        window.history.replaceState({}, title, "NewHTML.page");
        //works as expected
    </script>
    </head>
    <body>
    Testing
    </body>
</html>
like image 126
Herald Smit Avatar answered Sep 27 '22 20:09

Herald Smit