Subresource Integrity and Fetch

explaination

By default, browser only support integrity for script and stylesheet. However, fetch can provides option integrity as well, which makes it possible to use this feature for other resources, such as image in this demo page.

In this demo, it uses fetch to download an image resource with integrity option provided. The browser will validate after resource is being downloaded. When succeed, image will be shown, otherwise an error will be catched and app can do further steps (for example, load a backup resource from own server).

code example

Following is an example written using React. Image will be loaded with integrity validation. Loading component is used when still fetching the resource.

import React from 'react';

function getFetch(src, integrity) {
  return fetch(src, { integrity, mode: 'cors' })
      .then(response => response.blob())
      .then(blob => URL.createObjectURL(blob));
};

const ImageComponent =
  /**
   * React.memo is used to ensure that
   * request will be fetched once only.
   */
  React.memo(({ src, integrity, alt, ...rest }) => {
    /**
     * Use React.lazy with React.Suspense
     * to display loading effect when still
     * fetching the resource.
     */
    const Component = React.lazy(
      () => getFetch(src, integrity)
        .then(
          url => ({
            default: (props) => (
              React.useEffect(() => () => {
                URL.revokeObjectURL(url);
              }, []);
              <img src={url} alt={props.alt} {...props} />
            ),
          }),
          error => ({
            default: () => (
              <div>Error: {error.toString()}</div>
            );
          }),
        ),
    );
    return <Component alt={alt} {...rest} />;
  });

const Image = ({ src, integrity, alt, ...rest }) => {
  return (
    <React.Suspense fallback={<div>loading...</div>}>
      <ImageComponent
        src={src}
        integrity={integrity}
        alt={alt}
        {...rest}
      />
    </React.Suspense>
  );
};

export default Image;

drawback

fetch does not have the same request priority as image or other resources. Meanwhile, browser will not share cache when resource is being used again from a native approach, such as an <img> tag.

Status of resources loading

pikachu
Back