JavaScript가 비활성화되었거나 사용할 수 없는 사용자를 위해 지연 로드된 중요한 CSS 폴백을 추가하는 Vite 플러그인 작성

JavaScript가 비활성화되었거나 사용할 수 없는 사용자를 위해 지연 로드된 중요한 CSS 폴백을 추가하는 Vite 플러그인 작성

2022-10-19 last update

6 minutes reading css vite javascript performance
Netlify build plugin to automatically split out and inline critical CSSpersonal website 을 사용하고 있습니다.

중요한 CSS(페이지의 즉시 보이는 부분을 표시하는 데 필요한 CSS)를 인라인하는 것은 '스크롤 없이 볼 수 있는 부분' 콘텐츠를 예측할 수 있는 정적 사이트에서 많은 의미가 있으며 빠른 First Contentful Paint를 다운로드해야 하는 CSS가 적을수록 더 좋습니다(렌더링 차단 특성을 감안할 때).

가장 중요한 CSS 구현으로 중요한 CSS를 인라인하고 the media="print" and onload trick을 사용하여 나머지 CSS를 지연 로드합니다.

<link
  rel="stylesheet"
  href="/assets/styles.css"
  media="print"
  onload="this.media='all'"
/>


이 트릭에는 JavaScript가 필요하므로 JavaScript를 사용하지 않는 사용자를 위한 대안을 제공해야 합니다.

<noscript>
  <link 
    rel="stylesheet"
    href="/assets/styles.css"
  />
</noscript>


얼마 전에 netlify-plugin-inline-critical-css Netlify 빌드 플러그인에서 사용하는 Critical 패키지의 버전(또는 구성)에 <noscript> 대체가 누락되어 수동으로 Eleventy 템플릿에 추가했습니다. 큰 거래.

몇 주 전에 Vite 사용으로 전환했는데 <noscript> 대체가 작동을 멈췄습니다. Vite는 CSS와 JS의 이름을 변경하여 해시된 파일 이름을 부여한 다음 이러한 자산에 대한 링크를 감지하고 다음과 같이 해시된 버전을 사용하도록 경로를 업데이트합니다.

<link 
  rel="stylesheet"
  href="/assets/styles.833a7f93.css"
/>


그러나 Vite는 내 link 대체 내 <noscript> 요소를 선택하지 않는 것 같습니다.

이 문제를 해결하기 위해 내부의 작은 Vite 플러그인(내 vite.config.js 파일에 인라인됨)을 사용하여 스스로 대체를 추가했습니다.

const { defineConfig } = require('vite');

const addNoscriptCss = () => {
  return {
    name: 'add-noscript-css',
    transformIndexHtml(html, { chunk }) {
      const tags = [];

      Array.from(chunk.viteMetadata.importedCss, assetUrl => {
        tags.push({
          tag: 'noscript',
          children: [
            {
              tag: 'link',
              attrs: {
                rel: 'stylesheet',
                href: `/${assetUrl}`,
              },
            },
          ],
          injectTo: 'body',
        });
      });

      return {
        html,
        tags,
      };
    },
  };
};

module.exports = defineConfig({
  plugins: [
    addNoscriptCss(),
  ],
});


해당 플러그인은 생성된 HTML 파일을 가져와 Vite가 페이지에서 인식하는 모든 CSS 파일에 대해 <noscript> 대체를 추가합니다.

저는 정말 간단한 설정(모든 CSS<link>이 폴백이 필요한 단일 HTML 페이지)이 있으므로 이 스니펫이 다른 프로젝트에는 적합하지 않을 수 있지만, 이 스니펫을 우연히 발견하는 사람에게 도움이 되었으면 합니다.