모든 CI 단계에서 React 앱의 재구축을 방지하여 시간 절약

반응 앱이 있는 경우 응용 프로그램에서 REACT_APP_MY_ENV_VAR와 같은 환경 변수를 사용할 수 있으며 React는 프로덕션 응용 프로그램을 빌드할 때 자동으로 앱으로 가져옵니다.

이는 매우 유용하지만 각 환경에 대해 변경되는 변수가 있고 애플리케이션 빌드에 시간이 오래 걸리는 경우 CI에서 불필요하게 빌드하는 것을 방지할 수 있습니다. 예를 들어 구성이 다른 QA 환경과 스테이징 환경이 있을 수 있습니다.

우리는 각 빌드에서 코드를 유형 확인했으며 각 환경을 빌드하는 데 5분 이상 걸렸으므로 더 빠르게 만들어야 했습니다. REACT_APP 환경 변수를 사용하는 것에서 CI를 사용하여 빠르게 작성할 수 있는 구성 파일을 사용하는 것으로 앱을 변경했습니다.

우리 CI 시스템은 Azure DevOops이므로 여기의 CI 스크립트는 특별히 Azure DevOps용이지만 약간의 변경 사항이 있는 대부분의 CI 시스템에 적용됩니다.

실제 작업은 어디서나 작동하는 노드 스크립트에서 발생합니다.

파일에 환경 변수를 쓰는 스크립트 추가



여기에 매핑 구성에서 매핑한 모든 환경 변수를 가져와 자바스크립트 파일에 쓰는 스크립트가 있습니다. 스크립트가 실행될 때 구성을 창에 첨부합니다.

이 스크립트는 유형 검사가 있는 빌드의 경우 5-10분에 비해 몇 초 만에 실행됩니다.

const fs = require('fs')
const { exit } = require('process')

if (!process.argv[2]) {
  const message =
    'You must provide a file path to write the generated file to as an argument to this script'
  console.error(message)
  exit(1)
}

const providedFilePath = process.argv[2]

const envVarMappings = [
  {
    runTimeConfigProperty: 'appVariableOne',
    envVarName: 'REACT_APP_VARIABLE_ONE',
  },
  {
    runTimeConfigProperty: 'appVariableTwo',
    envVarName: 'REACT_APP_VARIABLE_TWO',
  },
]

const mappedVariables = envVarMappings.map((x) => {
  if (process.env[x.envVarName] === undefined) {
    const message = `The webapp property configured does not have an environment variable set. The environment variable must be present : ${JSON.stringify(
      x
    )}`

    console.error(message)
    exit(1)
  }

  return `\r\n${x.runTimeConfigProperty}: '${process.env[x.envVarName]}',`
})

// write out the lines to a script that attaches the variables to the window
const runtimeConfigFileAsLines = [].concat(
  [`window['runtimeConfig']= {`],
  mappedVariables,
  ['\r\n}']
)

fs.writeFileSync(providedFilePath, runtimeConfigFileAsLines.join(' '))


구성 파일을 사용하도록 앱 수정



React 애플리케이션에서 index.html의 헤드 섹션에 스크립트 태그를 추가합니다. 여기서 %PUBLIC_URL% 변수를 사용합니다. 이 변수는 react로 대체됩니다.

<head>
  <script src="%PUBLIC_URL%/runtime-config.js"></script>
</head>


이것은 React가 window 객체에 구성 객체를 설정할 구성 파일을 로드하도록 지시합니다.

다음으로 typescript를 사용하는 경우 인터페이스에서 구성 개체를 래핑합니다. Javascript를 사용하는 경우 이 중 일부를 건너뛸 수 있습니다.

// These values will be sent to the client so do not add
// secrets here.
export interface RuntimeConfig {
  appVariableOne: string
  appVariableTwo: string
}

export const runtimeConfig: RuntimeConfig = window.runtimeConfig
export default runtimeConfig


이제 이전에 REACT_APP_ 변수를 사용했던 모든 위치에서 구성 개체에 액세스할 수 있습니다.

변수 액세스 문에서 구성 파일을 사용하려고 하지만 존재하지 않으면 이전 환경 변수를 찾습니다. 이것은 환경 변수와 하위 호환되는 방식으로 작동합니다.

myThingThatDependsOnEnvironmentVariable(
  runtimeConfig.appVariableOne || process.env.REACT_APP_VARIABLE_ONE
)


환경별 구성 파일을 생성하는 CI 단계 추가



인프라 폴더에서 구성 파일 생성기를 실행하는 CI 단계를 추가합니다.

먼저 실행 가능해야 합니다chmod.

- script: |
    chmod +x ./infrastructure/pipeline/write-webapp-runtime-config.js
    node ./infrastructure/pipeline/write-webapp-runtime-config.js ./packages/react-client/build/runtime-config.js
  env:
    REACT_APP_VARIABLE_ONE: $(appVariableOne)
    REACT_APP_VARIABLE_TWO: $(appVariableTwo)
  displayName: 'Write react app runtime variables'


Jest 구성



구성에 의존하는 테스트가 있는 경우 테스트를 실행하기 전에 파일을 로드하도록 Jest에 지시해야 합니다.

이렇게 하려면 preRun 파일을 추가하고(이미 없는 경우) 이를 jest 구성의 "setup"속성에 추가합니다.

// add this to a file called "jest.prerunsetup.js" or similar
window.runtimeConfig = window.runtimeConfig || {}


이제 jest.config.js 해당 설정 파일에 대한 참조를 추가하십시오.

module.exports = {
  setupFiles: ['./jest.prerunsetup.js'],
}


다른 도구 구성



React 구성 요소를 사용하는 모든 도구에는 구성이 주입되어야 합니다. Jest 방법은 위에서 언급했습니다. 각자의 주입 방식도 있을 것입니다. 예를 들어 반응 스토리북을 사용하는 경우 설명된 스토리북 방법을 사용하여 헤더에 스크립트를 추가해야 합니다here.

파일.storybook/preview-head.html을 추가하고 거기에서 위에서 헤더 스크립트를 팝니다.

로컬 구성 파일 추가(원하는 경우)


<<app>>/private 를 사용하는 경우 create-react-app 폴더로 이동해야 합니다.

window['backrRuntimeConfig'] = {
  appVariableOne: 'value1',
  appVariableTwo: 'value2',
}


여기에 개발 설정을 넣을 수 있습니다.

Git은 로컬 구성 파일을 무시합니다.



.env 파일과 마찬가지로 구성의 로컬 복사본을 원할 것입니다.gitignore.
.gitignore에 추가

runtime-config.js

좋은 웹페이지 즐겨찾기