titicacadev / triple-frontend

Monorepo for Triple Frontend Components and Libraries
https://storybook.triple-corp.com
MIT License
148 stars 9 forks source link

styled-component SSR 시에 css overriding 안되는 이슈 #2588

Open sohnjunior opened 1 year ago

sohnjunior commented 1 year ago

📌 문제 상황

문제 논의 스레드

TF의 ActionSheet에서 css props를 넘겼을 때, 의도한 대로 css 오버라이딩 되지 않는 문제가 있습니다.

이러한 문제는 createPortal을 사용한 컴포넌트들(Modal, ActionSheet ..)에서 공통적으로 발생했습니다.

결론적으로 SSR시에 styled-component 로 스타일된 컴포넌트를 createPortal로 렌더링할때 주입된 ServerStyleSheet 에서 오버라이딩하고자 하는 스타일 클래스가 기본 스타일 클래스보다 먼저 정의되는 이슈로 인한 것이었습니다.

📌 시도해본것

1. TF 패키지 내에서 css 속성 스타일 오버라이딩 유닛 테스트

test('스타일 커스텀 테스트', async () => {
  await act(() => {
    render(
      <ActionSheet open css={{ paddingTop: 10 }}>
        contents
      </ActionSheet>,
    )
  })

  const modal = screen.getByRole('dialog')
  const modalBody = modal.querySelector('[class^="action-sheet-body"]')

  expect(modalBody).toHaveStyle({ paddingTop: '10px' })
})

→ 문제없이 잘 동작함.. 🤔

2. 샌드박스 생성 후 TF 패키지 테스트

로컬에서 프로젝트 생성 후 TF 패키지를 적용해봤는데, 여기서 문제를 찾을 수 있었습니다.

styled-component 의 SSR 설정을 하니, portal 을 사용하는 컴포넌트를 SSR 할 때 스타일 오버라이딩이 안되는 이슈가 있었습니다.

📌 대응방안

다음 두가지 방법중 하나를 이용해서 문제를 우회할 수 있습니다.

1. dynamic import 하기

SSR 하지 않고, 스타일을 커스텀한 action-sheet 를 CSR 하도록 합니다. 다음은 내부에서 스타일 커스텀 된 ActionSheet 를 사용하는 PopularCitiesActionSheet 컴포넌트를 사용하는 예제입니다.

// e.g TNA-WEB-V2 에서 지역선택 팝업을 활용한 예제

const PopularCitiesActionSheet = dynamic(() => import('./popular-cities-action-sheet'), {
  ssr: false,
})

function someComponent() {
  //... some logics

  return (
  <>
     // ... other components 
     <PopularCitiesActionSheet /> 
  </>
 )
}

2. 스타일 우선순위 높이기

!important 를 사용하지 않는 공식 문서에서 권장하는 방법입니다. && 혹은 &&& 선택자로 스타일을 좀 더 구체적으로 정의해서 우선순위를 높일 수 있습니다.

const MyStyledComponent = styled(AlreadyStyledComponent)`
  &&& {
    color: palevioletred;
    font-weight: bold;
  }
`

styled-components 공식문서: FAQs

inbeom commented 1 year ago

전 1안이 좋아 보입니다! SSR할 때 마크업의 크기가 상당히 커서 팝업이나 액션시트 등 최초에 보이지 않는 컴포넌트들은 필요할 때 import하는 게 첫 렌더링 시간을 절약하는 길인 것 같아요.

dongoc commented 1 year ago

1안에서는 css props를 직접 주입할 수 있는 건가요?👀

sohnjunior commented 1 year ago

1안에서는 css props를 직접 주입할 수 있는 건가요?👀

네, 우선순위 강제적용없이 주입할 수 있습니다!