UI 확장: React 19 업그레이드

UI 확장: React 19 업그레이드

Argo CD 3.5부터 UI 확장(extension)은 reactreact-dom에 더해 react/jsx-runtime도 외부화(externalize)해야 합니다. 호스트 애플리케이션은 JSX 런타임을 window.ReactJSXRuntime으로 노출합니다. 자체 런타임 사본을 번들로 포함하는 확장은 로드에 실패합니다.

출처: 문서

본문

UI 확장: React 19 업그레이드

Argo CD 3.5부터 확장은 reactreact-dom에 더해 react/jsx-runtime도 외부화해야 합니다. 호스트 애플리케이션은 JSX 런타임을 window.ReactJSXRuntime으로 노출합니다. 자체 런타임 사본을 번들로 포함하는 확장은 로드에 실패합니다.

감지(Detection)

이전 Argo CD UI를 대상으로 빌드된 확장은 TypeError로 로드에 실패합니다. 호스트 UI는 이를 다음과 같이 표시합니다:

Extension <name>.js failed to load: TypeError: Cannot read properties of undefined (reading '<prop>')

메시지의 속성 이름과 스택 추적의 함수 이름은 확장 번들이 압축(minify)되었는지에 따라 달라지므로, 매칭 기준으로 신뢰할 수 없습니다. 모든 빌드에서 유지되는 두 가지 신호는 다음과 같습니다:

  • 실패가 확장이 렌더링되기 전, 로드 시점의 TypeError이고,
  • 확장의 번들러 구성의 externals 맵에 react/jsx-runtime이 나열되어 있지 않습니다.

antd 같은 의존성은 react/jsx-runtime을 직접 import합니다. react/jsx-runtime이 외부화되지 않으면 번들러가 자체 런타임 사본을 포함하게 되는데, 이 런타임은 React 19에서 제거된 React 내부 객체에 접근해 호스트의 React 19 인스턴스와 충돌하여 크래시가 발생합니다.

수정(Remediation)

번들러 구성의 externals 맵에 react/jsx-runtime을 추가하여 모든 JSX 런타임 import가 window.ReactJSXRuntime의 호스트 런타임으로 해석되게 하세요:

// webpack.config.js
externals: {
  react: 'React',
  'react-dom': 'ReactDOM',
  'react/jsx-runtime': 'ReactJSXRuntime',
  moment: 'Moment',
}

다시 빌드하면 확장이 호스트 애플리케이션의 React 19 인스턴스를 공유하고 성공적으로 로드됩니다.

호환되지 않는 의존성

react/jsx-runtime을 외부화하면 가장 흔한 실패 모드가 해결됩니다. 이 변경 후에도 여전히 로드에 실패하는 확장은 React 19 자체와 호환되지 않는 라이브러리 버전에 의존하고 있을 가능성이 높습니다. 대부분의 경우 패키지를 React 19를 지원하는 버전으로 올리면 해결됩니다. 활발히 유지보수되는 대부분의 라이브러리에는 이미 그런 버전이 있습니다.

참고

다음 풀 리퀘스트는 이 수정을 적용한 것으로, 다른 확장 저장소에 유용한 템플릿입니다:

  • argoproj-labs/argocd-ephemeral-access#141 — Ephemeral Access 확장.
  • argoproj-labs/rollout-extension#104 — Argo Rollouts 확장.

Argo CD UI가 노출하는 전역 변수(Globals)

호스트 UI는 현재 확장이 externals를 통해 소비할 수 있도록 다음 모듈을 window에 노출합니다:

모듈 전역
react React
react-dom ReactDOM
react/jsx-runtime ReactJSXRuntime
moment Moment

더 알아보기 (Learn more)