#onLoad attribute on a link tag in entry-server not running

9 messages · Page 1 of 1 (latest)

dusk sleet
#

I'm on @solidjs/start 0.7.7 and trying to add an onload="this.onload=null;this.rel='stylesheet'" on a link tag. The purpose is more widely explained here.

Problem with this approach is that typescript keeps shouting Type 'string' is not assignable to type 'EventHandlerUnion<HTMLLinkElement, Event> | undefined'. So I rewrote the single liner above to the following:

<link
  ...
  onLoad={function (this: HTMLLinkElement) {
    console.log("I was run")
    this.onload = null
    this.rel = "stylesheet"
  }}
/>

And I don't see the console.log anywhere. I checked on the console tab, the terminal I ran "pnpm dev" on... nothing

How should I handle this? I'd like to keep onload="this.onload=null;this.rel='stylesheet'", or accept any alternatives that work

#

I'd also like to point out that the single liner works if we just ignore the typescript

vital lintel
#

Have you tried

// @refresh reload
// src/entry-client.tsx
import { mount, StartClient } from '@solidjs/start/client';

mount(() => { 
    const link = document.querySelector('link[rel="preload"][as="style"]');
    if (link instanceof HTMLLinkElement) link.rel = 'stylesheet';

    return (<StartClient />);
}, document.getElementById('app')!);

and

// src/entry-server.tsx

                    <link rel="preload" as="style" href="styles.css"/>
vital lintel
#

Another alternative

// file: src/entry-server.tsx
import { getRequestEvent } from 'solid-js/web';
import { createHandler, StartServer } from '@solidjs/start/server';

declare module '@solidjs/start/server' {
  interface RequestEventLocals {
    clientId: string;
  }
}

const loadNonCritical = `
function loadNonCritical() {
  var link = document.querySelector('link[rel="preload"][as="style"]');
  if (link instanceof HTMLLinkElement) link.rel = 'stylesheet';
}

if (document.readyState === 'loading') {
  document.addEventListener("DOMContentLoaded", loadNonCritical);
} else {
  loadNonCritical();
}`;

export default createHandler(() => {
  const event = getRequestEvent();
  // @ts-ignore
  const nonce = event.nonce;

  return (
    <StartServer
      document={({ assets, children, scripts }) => (
        <html lang="en">
          <head>
            <meta charset="utf-8" />
            <meta
              name="viewport"
              content="width=device-width, initial-scale=1"
            />
            <link rel="icon" href="/favicon.ico" />
            <link rel="preload" as="style" href="styles.css" />
            <script {...(nonce ? { nonce } : {})} innerHTML={loadNonCritical} />
            {assets}
          </head>
          <body>
            <div id="app">{children}</div>
            {scripts}
          </body>
        </html>
      )}
    />
  );
});
vital lintel
#

Finally that article is from 2019.

Under CSP inline event handlers will be ignored and only scripts with a valid CSP hash or nonce will be executed.

MDN Web Docs

Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks,
including Cross-Site Scripting (XSS) and data injection attacks.
These attacks are used for everything from data theft, to site defacement, to malware distribution.

MDN Web Docs

The nonce global attribute
is a content attribute defining a cryptographic nonce ("number used once") which can be used by
Content Security Policy to determine whether or not a given fetch will
be allowed to proceed for a given element.

dusk sleet
#

@vital lintel Thank you for the suggestions! I guess @ts-ignore seems to be the way to go eh?

vital lintel
# dusk sleet <@1040721210142634016> Thank you for the suggestions! I guess @ts-ignore seems t...

You shouldn't be using the string "event handler" (inline event-handling HTML attibute) in the first place (which is what TypeScript is complaining about).

onload="this.onload=null;this.rel='stylesheet'"

Chrome is notorious for all of a sudden cracking down on these type of things.

So if updating the element in entry-client.tsx is too late, injecting a whitelisted inline script is the way to go.

dusk sleet
#

You shouldn't be using the string "event handler" (inline event-handling HTML attibute) in the first place (which is what TypeScript is complaining about).

I get that part but is it really such a big deal tho?

vital lintel
# dusk sleet > You shouldn't be using the string "event handler" (inline event-handling HTML ...

https://stackoverflow.com/search?tab=newest&q=inline event handler CSP&searchOn=3

More often than not they cause avoidable grief like all of a sudden your site only loading its critical CSS.

And I don't see the console.log anywhere.

That's because the JSX uses addEventListener. That onload is run at element creation; so by the time addEventListener is run it's too late.

The tactic is gaming the preload mechanic; delaying the switch to the time that DOM element is created.

If you pick your critical CSS to suitably style the above the fold content of the page the link.rel = 'stylesheet' in entry-client.tsx should be fine.