create-react-app을 사용하여 chrome extension 만들기
create-react-app을 사용하여 chrome extension 만들기
create-react-app(CRA)는 React 앱을 손쉽게 빌드 및 배포할 수 있는 환경을 제공합니다. 최근 Chrome 확장 프로그램 세팅을 진행하면서 CRA를 사용해 손쉽게 확장 프로그램을 제작하고 싶었지만, CRA는 기본적으로 SPA 만을 지원하여 추가적인 설정이 필요했습니다.
만들려 하는 크롬 익스텐션에서 팝업 환경과 옵션 페이지가 모두 필요하여 빌드 엔트리를 나눌 필요가 있었으나, options_page
에 관련된 정보를 찾을 수 없었어서 직접 작업하면서 겪은 과정을 정리합니다.
React App 만들기
우선, create-react-app을 사용하여 React 앱을 만들어 줍니다. 타입스크립트를 사용하기 위해 --template typescript
옵션을 추가하여 생성하겠습니다.
npx create-react-app chrome-extension --template typescript
manifest.json 수정
create-react-app 에서 자동으로 생성해준 manifest.json
이 public/
경로에 있지만, chrome extension에서 요구하는 사항에 맞춰 변경해야 합니다.
{
"name": "Create React App Sample",
"version": "0.0.1",
"manifest_version": 2,
"description": "create-react-app for extensions",
"icons": {
"128": "logo128.png"
},
"permissions": [],
"background": {
"scripts": [
"background.js"
],
"persistent": true
},
"browser_action": {
"default_icon": "logo128.png",
"default_popup": "popup.html"
},
"options_page": "index.html"
}
option_page
로 index.html
을 설정하였으며, popup
은 popup.html
로 설정하였습니다.
파일 구조 작업
우선, public
경로에 popup.html
을 만들어 준 뒤, src
내에 popup
디렉토리와 page
디렉토리를 각각 생성한 뒤, index.tsx
파일을 만들어줍니다. popup.html
의 내용은 index.html
을 복사하여 생성하면 됩니다. popup
과 page
경로에서 공통으로 사용해야 하는 상수, 컴포넌트가 있다면 src
경로 아래 common
디렉토리를 생성합니다. 구조는 다음과 같이 구성됩니다.
또한, src
내에 background.js
파일을 생성한 뒤, chrome extension에서는 인라인 자바스크립트를 허용하지 않으므로 .env
파일을 생성하여 아래 구문을 입력합니다.
INLINE_RUNTIME_CHUNK = false
├─ public
| ├─ popup.html // popup/index.tsx 가 바라보는 html
| └─ index.html // page/index.tsx 가 바라보는 html
├─ src
| ├─ background.js
| ├─ common // 웹 페이지 및 팝업에서 공용으로 사용되는 로직
| | ├─ component // 공용 컴포넌트
| | └─ lib // 공용 라이브러리
| ├─ page // 크롬 확장 프로그램 웹 페이지
| | ├─ index.tsx // 웹 페이지 코드
| | ├─ component // 웹 페이지 컴포넌트
| | └─ lib // 웹 페이지 라이브러리
| ├─ popup // 크롬 확장 프로그램 팝업
| | ├─ index.tsx // 팝업 코드
| | ├─ component // 팝업 컴포넌트
| | └─ lib // 팝업 라이브러리
| |
...
빌드 설정 하기
이제, CRA를 커스터마이징하기 위해 다음 패키지를 추가해줄 필요가 있습니다.
yarn add customize-cra react-app-rewired copy-webpack-plugin react-app-rewire-multiple-entry --dev
customize-cra
와 react-app-rewired
는 웹팩을 재정의하며, copy-webpack-plugin
을 사용해 public 폴더를 byuld 폴더로 복사할 것입니다. 또한, react-app-rewire-multiple-entry
를 이용해 여러 페이지를 빌드할 수 있도록 구성해야 합니다.
루트 경로에 config-overrides.js
를 생성한 뒤, 아래와 같이 입력합니다.
const {
override,
overrideDevServer,
addWebpackPlugin
} = require("customize-cra");
const CopyPlugin = require('copy-webpack-plugin');
const RewireMultipleEntry = require('react-app-rewire-multiple-entry');
const multipleEntry = RewireMultipleEntry([
{
entry: 'src/popup/index.tsx',
template: 'public/popup.html',
outPath: '/popup.html'
},
{
entry: 'src/page/index.tsx',
template: 'public/index.html',
outPath: '/index.html'
}
]);
const devServerConfig = () => config => {
return {
...config,
writeToDisk: true
}
}
const copyPlugin = new CopyPlugin({
patterns: [
{ from: 'public', to: '' },
{ from: 'src/background.js', to: '' }
]
})
module.exports = {
webpack: override(
addWebpackPlugin(
copyPlugin
),
multipleEntry.addMultiEntry,
),
devServer: overrideDevServer(
devServerConfig()
),
};
이제 package.json
내의 scripts
를 수정하면 커스터마이징한 웹팩 설정을 이용해 빌드할 수 있습니다.
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject"
},
start, build
yarn run start
명령어를 실행하면 dist 폴더가 생성됩니다. 해당 dist
폴더를 chrome://extensions
에 추가하여 개발을 진행할 수 있습니다. 개발이 완료되면 yarn run build
명령어를 실행하여 build
폴더를 생성할 수 있습니다.
모든 것이 정상적으로 완료되었다면 크롬 익스텐션을 클릭하였을 때 아래와 같은 팝업이 노출될 것입니다.
'Advanced > React' 카테고리의 다른 글
[React] sagen을 사용해서 간단히 상태 관리하기 (1) | 2021.05.16 |
---|---|
[React] useEffect의 동작 원리 (1) | 2021.01.31 |
React Redux에서 ContextAPI performance issue를 해결한 방법 (0) | 2020.11.07 |
useEffect Dependency (0) | 2020.10.21 |
ContextAPI 렌더링 이슈 (4) | 2020.10.17 |
댓글
이 글 공유하기
다른 글
-
[React] sagen을 사용해서 간단히 상태 관리하기
[React] sagen을 사용해서 간단히 상태 관리하기
2021.05.16 -
[React] useEffect의 동작 원리
[React] useEffect의 동작 원리
2021.01.31 -
React Redux에서 ContextAPI performance issue를 해결한 방법
React Redux에서 ContextAPI performance issue를 해결한 방법
2020.11.07 -
useEffect Dependency
useEffect Dependency
2020.10.21