Order of rel and href matters for link tags with rel="alternate"

Author: davidnaasCreated May 9, 2017Updated May 19, 2026

When using link tags with rel="alternate", the order of which rel and href are declared affect the behavior. Declaring rel before href will cause Helmet to update the link tags incorrectly.

More specifically, I'm rendering a set of link tags to different language versions of my app on a per route basis. I.e the set of links change every time the route changes. The app uses server side rendering and that part works fine; the first request to the server renders the correct tags. However, as soon as you visit another route on the client the links are updated incorrectly. The new tags are appended to the head while the old ones linger. Switching the order of declaration solves this and old tags are removed when Helmet updates.

I tried solving this myself but couldn't get further than showing that this also, as expected, breaks one of the tests. If someone could point me in the right direction, I'd be happy to try and contribute a fix for this.

Modded failing test in test/HelmetDeclarativeTest.js

javascript
it("tags 'rel' and 'href' properly use 'rel' as the primary identification for this tag, regardless of ordering", (done) => {
    ReactDOM.render(
        <div>
            <Helmet>
                <link href="http://localhost/helmet" rel="alternate" />
            </Helmet>
            <Helmet>
                <link rel="alternate" href="http://localhost/helmet/new" />
            </Helmet>
            <Helmet>
                <link href="http://localhost/helmet/newest" rel="alternate" />
            </Helmet>
        </div>,
        container
    );

    requestIdleCallback(() => {
        const tagNodes = headElement.querySelectorAll(`link[${HELMET_ATTRIBUTE}]`);
        const existingTags = Array.prototype.slice.call(tagNodes);
        const firstTag = existingTags[0];

        expect(existingTags).to.not.equal(undefined);

        expect(existingTags.length).to.equal(1);

        expect(existingTags)
            .to.have.deep.property("[0]")
            .that.is.an.instanceof(Element);
        expect(firstTag).to.have.property("getAttribute");
        expect(firstTag.getAttribute("rel")).to.equal("alternate");
        expect(firstTag.getAttribute("href")).to.equal("http://localhost/helmet/newest");
        expect(firstTag.outerHTML).to.equal(`<link href="http://localhost/helmet/newest" rel="alternate" ${HELMET_ATTRIBUTE}="true">`);

        done();
    });
});;