Next.js와 비동기적으로 CSS를 분할하는 비극

13890 단어 Next.jstech
이 기사는 Recruit Engineers Advent Calendar 2020 "4일째"기사입니다.
안녕하세요!나는 10월부터 Recruit 과학 기술 회사에 등록한 길정이다.올해는 넥스트다.제이스가 뜨거웠던 해였어요.이 문서에서는 Next를 소개합니다.js의 CSS와 관련된'언제 부딪힐지 모르는 버그'를 소개하고 싶습니다.
규칙만 지키면 닥치지 않는 오류이자 현 상태의 넥스다.js의 구조에서 발생할 수 있는 현상이기 때문에 왜 이런 일이 일어났을까요?잘 이해하는 게 목적이야.

[오류 개요] 색깔이 불규칙적으로 변동되다


rainbow
절차.
조작하다
1
Red/Green/Blue 페이지 중 하나부터 표시
2
다른 색상 화면으로 이동하여 TOP 페이지 표시
3
랜덤으로'빨간색, 녹색, 파란색'의 응용
【샘플】https://github.com/takefumi-yoshii/nextjs-cssmodules-rainbow
샘플 코드는 매우 간단합니다.component에 hooks를 쓰지 않고 '페이지 탐색' 에서만 발생합니다.이것은 CSS 규격과 비동기 분할 읽기로 인한 비극이다.

설치 확인


우선 서류 구성이다.아래와 같다.
./src
├── components
│   ├── Blue.tsx
│   ├── Green.tsx
│   ├── Red.tsx
│   └── Top.tsx
├── pages
│   ├── blue.tsx
│   ├── green.tsx
│   ├── index.tsx
│   └── red.tsx
└── styles
    ├── colors.module.css
    ├── common.module.css
    └── shared.module.css
다음은 styles 디렉터리에 포함된 3장.module.css의 파일 내역이다.사건을 소개하기 위해서 일부러 문서를 이렇게 너저분하게 정의했으니 탓하지 마세요.
/* src/styles/common.module.css */
.red {
  color: #f00;
}
/* src/styles/colors.module.css */
.green {
  color: #0f0;
}
/* src/styles/shared.module.css */
.blue {
  color: #00f;
}
다음은 문제의 첫 페이지에 있는 구성 요소입니다.그럼 이 단계가 어떤 색으로 변할지 아세요?나는 우선 색깔 충돌과 같은 이상한 지정은 없을 것이라고 생각한다. 그러나 여러 가지 조형을 사용했는데 설치에 따라 어떻게 채택되는지 모르겠다.
import * as React from "react";
import Nav from "./Nav";
import shared from "../styles/shared.module.css";
import colors from "../styles/colors.module.css";
import common from "../styles/common.module.css";
// _____________________________________________________________________________
//
const Component = () => (
  <div className={`${common.red} ${colors.green} ${shared.blue}`}>
    <h1>Rainbow</h1>
    <Nav />
  </div>
);

빌드 컨텐트 확인


구축을 실행하고 각 페이지의 import.module.css의 정적 CSS 정보 블록 파일 내역을 확인합니다.경쟁을 피하기 위해 선택기가hash값을 부여받았는지 확인할 수 있고 선택기 이름은(local scope)을 부여받았습니다.
/* .next/static/css/9ec1f7fe0241b8d2fe1a.css */
.colors_green__9sX5x {
  color: #0f0;
}
/* .next/static/css/5373b7cb8b0c11d15c48.css */
.shared_blue__1C81Z {
  color: #00f;
}
/* .next/static/css/a051605e66b313704c13.css */
.common_red__2ckaP {
  color: red;
}
TOP에 해당하는 파일입니다.디스플레이에 필요한 정의가 같은 선택기 이름에 포함되어 있는지 확인할 수 있습니다.정적 파일 출력이기 때문에 여기까지 종합하면 변동이 불확실한 요소가 보이지 않는다.
.common_red__2ckaP {
  color: red;
}
.colors_green__9sX5x {
  color: #0f0;
}
.shared_blue__1C81Z {
  color: #00f;
}

CSS 사양 복원


버그의 근본 원인을 이해하기 위해 먼저 Next.js를 떠나서 CSS의 규격을 확인하십시오.양식 확정에 있어서 중요한 다음과 같은 사항.

CSS order "should matter"


'CSS는 선택기의 상세도가 같은 상황에서 후승이다'는 성격이 있다.아래 p태그를 보면 모두'빨강·파랑'이고 실제로는 모두'빨강'이다.p 탭의class 지정 전후는 스타일 확정과 관련이 없습니다.근본적으로 잘못된 원인은 바로 이 성질에 있다.
<html>
  <head>
    <style>
      .blue {
        color: #00f;
      } /* 詳細度 10 */
      .red {
        color: #f00;
      } /* 詳細度 10 こちらが適用される */
    </style>
  </head>
  <body>
    <p class="blue red">red?</p>
    <p class="red blue">blue?</p>
  </body>
</html>
아무리 복잡한hash값이 부여되더라도class선택기는 일률적으로'10'상태를 유지하고'스타일의 확정은 선언 순서'다.CSS에서 선언한 전후 관계는 중요한 요소이다.

설치 다시 확인


사실 이 잘못된 재현을 위해서 나는 또 준비를 한 적이 있다.그것은 next/dynamic 구성 요소를 사용한 다이내믹 import입니다.헤드 탭에 삽입된 자원을 확인한 후,dynamic import의 자원과 그렇지 않은 자원에 차이가 있습니다.
다음 캡처는 모든 화면을 이동할 때의 출력 결과입니다.

[다이내믹 import 없음!]


페이지 단위의 정보 블록 파일을 확인할 수 있으며 변환 전후에 따라 달라집니다.이 전후 순서 조작을 통해 이번에 열거한 현상은 발생하지 않을 것이다.
non-dynamic

[다이내믹 import이 있습니다.]


위에서 읽히는 것을 공동으로 지정하는 것 외에 아래에 구성 요소의 js와 css가 추가되었는지 확인할 수 있습니다.이 캡처는 전체 화면 이동이 완료된 것이기 때문에 탑으로 돌아와도 안정적일 것이다.비극은 이 양식의 읽기가 완료되지 않았을 때 발생한다.
dynamic
  • 공통 지정 읽기
  • RGB 읽기
  • 이런 상황에서 잘못된 전모는'포스트잇이 읽은 RGB 중 임의의 것을 적용한다'는 것이다.dynamic import의 삽입 순서를 예측할 수 없습니다.이 점에 대해 아래의 issue에서도 CSS의 읽기 순서 제어는 매우 이해하기 어려운 문제라고 언급했다.
    【Inconsistent loading order of CSS Modules + global CSS】 https://github.com/vercel/next.js/issues/10148
    CSS Modules 때문에 발생하는 문제가 아니라 비동기적으로 스타일을 삽입하는 모든 해결 방안에서 발생할 수 있는 일이다.

    잘못을 당하지 않도록 보호하기 위한 것은 오직 하나뿐이다


    여기까지 정리하면dynamic import과 여러 종류를 지정하는 것이 좋지 않습니까?이런 느낌이 들긴 하지만 그렇지는 않아요.우리가 실행에 있어서 지켜야 할 것은 오직 하나뿐이다.

    ".module.css 및 어셈블리는 1대1로 정의됨"


    이 규칙을 준수하기만 한다면 이전의 전후 관계와 관련된 분쟁을 만나지 않을 것이다.수여된hash값은local scope로 작용하기 때문에 순서대로 읽지 않아도 충돌이 발생하지 않습니다.
    내장형 웹 패키지 로더 MiniCssExtractPlugin 설정에 쓰인 주석을 인용하다.
    Next.js guarantees that CSS order "doesn't matter", due to imposed restrictions:
  • Global CSS can only be defined in a single entrypoint (_app)
  • CSS Modules generate scoped class names by default and cannot include Global CSS (:global() selector).
  • ${common.red} ${colors.green} ${shared.blue}와 같은 여러 종류가 모두 안 되는 것이 아니라 여러 구성 요소와 파일 내의 지정에 문제가 없다는 것을 가리킨다.만약 비동기적으로 CSS와'공유.module.css'의 조합에서 이상한 표시가 나타나면 먼저 이 지정한 읽기 순서를 의심해야 한다.

    좋은 웹페이지 즐겨찾기