저번 글에서는 익스텐션에서 필수적인 manifest에 대해서 설명을 하였는데 이제 익스텐션 개발을 위해서 웹팩을 설정해보고 팝업을 만드는 작업을 진행했던 과정에 대해서 설명하려고 합니다.
1. package.json 다운로드
필요한 모듈을 설치하기 위해서 package.json파일 생성을 해야됩니다.
npm init -y
2. 초기 설정에 필요한 모듈 다운로드
일단 웹팩을 사용하기 위해서 핵심적인 역할을 하는 webpack와 webpack을 더 쉽게 사용할 수 있도록 다양한 명령을 제공 받기 위해서 webpack-cli까지 설치를 진행하였습니다. 이외에도 html-webpack-plugin, copy-webpack-plugin이 필요하긴 한데 아래부분에서 설명하구 넘어가도록하겠습니다.
npm i --save-dev webpack webpack-cli
타입스크립트를 활용해서 개발을 진행하려고 했기 때문에 typescript와 ts-loader를 다운로드 받았습니다. 만약 javascript를 통해서 개발을 진행하려고 한다면, 다른 로더를 사용해도 상관없습니다.
npm i --save-dev @types/react typescript ts-loader
타입스크립트를 사용하기 위해선 어떻게 타입스크립트를 자바스크립트로 변환 시킬 것인지 컴파일 설정할 파일이 필요합니다. 그래서 아래와 같이 tsconfig.json파일을 생성 후 아래와 같이 설정을 진행하였습니다.
- tsconfig.json
{
"compilerOptions": {
"jsx": "react-jsx",
"module": "ES6",
"target": "ES6",
"moduleResolution": "node",
"esModuleInterop": true
},
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["node_modules"]
}
사용자의 인터페이스를 쉽게 구성하기 위해서 React라이브러리에서 핵심적인 역할을 하는 2가지 패키지 모두 설치를 진행하였습니다.
npm i react react-dom
3. 웹팩 설정을 해보자
위와 같이 팝업창을 만들기 위해서 필요한 모듈들을 모두 설치했으니깐 이제 진짜 웹팩을 구성하러 가봅시다.
그전에 마지막으로 아래와 같이 팝업창에 띄워질 컴포넌트를 src폴더안에 만들어주고 시작해봅시다.
- Popup.tsx
import ReactDom from "react-dom/client";
const Popup = () => {
return <div>제발 열려라</div>
};
export default Popup;
const container = document.createElement("div");
document.body.appendChild(container);
const root = ReactDom.createRoot(container);
root.render(<Popup />);
번들링을 시작할 파일을 entry에 지정 후 output에는 entry의 속성을 이용해서 filename을 지정해줬습니다. 그리고 ouput에서는 이전 빌드된 결과물을 삭제하기 위해서 clean속성을 설정해줬습니다. 설정을 안해두면 이전 파일이 어떤 것인지 확인하기가 힘들더라구요..
그리고 저희는 ts-loader를 설치하였기 때문에 타입스크립트를 자바스크립트로 변환하기 위해서 아래와 같이 설정해주었습니다.
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: {
popup: "./src/Popup.tsx",
},
module: {
rules: [
{
use: "ts-loader",
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
},
],
},
output: {
filename: "[name].js",
clean: true,
},
};
번들링 된 dist폴더안에 똑같이 존재해야 되는 파일이 있습니다. 바로 저번 시간에 설명해드렸던 manifest.json파일이죠. 해당 파일이 없다다면 익스텐션이 어떻게 구성 되어있는지 모르기 때문에 정적 파일로 구분해야 됩니다. 저는 공통성있게 정적 파일들은 src폴더안에 static폴더를 만들어서 관리하도록 진행하였습니다.
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
...
plugins: [
new CopyWebpackPlugin({
patterns: [{ from: "./src/static", to: "." }],
}),
],
};
이제 익스텐션에서 팝업창을 띄울수 있게 해주는 html 파일이 하나 필요합니다. 웹팩으로 빌드한 popup.js를 script태그를 사용해서 연결된 html파일 생성은 html-webpack-plugin을 사용하면 쉽게 할 수 있습니다.
아래와 같이 설정하게 된다면 popup.html을 생성 후 popup이라는 이름을 빌드된 파일을 연결 시켜주는 작업까지 진행하게 됩니다.
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: {
popup: "./src/Popup.tsx",
},
module: {
rules: [
{
use: "ts-loader",
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
},
],
},
plugins: [
new HtmlWebpackPlugin({
filename: "popup.html",
chunks: ["popup"],
}),
],
output: {
filename: "[name].js",
clean: true,
},
};
아래는 최종적인 webpack.config.js 파일이며, 빌드할 시 mode 설정을 하지 않으면 경고가 표시 되기 때문에 development모드로 설정해주었습니다.
devtool에 cheap-module-source-map을 설정하지 않고 빌드한 파일을 확장 프로그램에 로드한 경우 다음과 같은 에러 발생합니다.
위의 속성을 추가해주지 않는다면 빌드 과정에서 eval함수를 생성하게 되는데 해당 함수가 Chorme의 CSP 정책에 의해 차단되었기 때문입니다. 나중엔 production 모드로 배포할 예정이기 때문에 큰 문제가 되지는 않을 거 같긴 합니다.
⚠️ Uncaught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self'".
- webpack.config.js
const CopyWebpackPlugin = require("copy-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: "development",
devtool: "cheap-module-source-map",
entry: {
popup: "./src/Popup.tsx",
},
module: {
rules: [
{
use: "ts-loader",
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
},
],
},
plugins: [
new CopyWebpackPlugin({
patterns: [{ from: "./src/static", to: "." }],
}),
new HtmlWebpackPlugin({
filename: "popup.html",
chunks: ["popup"],
}),
],
output: {
filename: "[name].js",
clean: true,
},
};
이제 webpack 명령어를 활용해서 빌드하게 된다면 아래와 같이 dist 폴더안에 이러한 파일들이 생성됩니다.
dist파일을 확장프로그램에 로드하게 된다면 팝업창을 띄울 수 있게 됩니다. 만들고 다니 형편이 없군요.. 하지만 꾸미면 되니깐 이부분은 나중에 스타일을 입히도록 하겠습니다..
4. Remind
리액트를 활용해서 개발을 진행할 때 항상 Webpack은 어떻게 구성이 되어있을까? 라는 고민이 있었는데 실제 경험을 할 수 있어 좋은 시간이였던 것 같습니다.
5. 참고자료
webpack
웹팩은 모듈 번들러입니다. 주요 목적은 브라우저에서 사용할 수 있도록 JavaScript 파일을 번들로 묶는 것이지만, 리소스나 애셋을 변환하고 번들링 또는 패키징할 수도 있습니다.
webpack.kr
https://webpack.kr/plugins/copy-webpack-plugin/
CopyWebpackPlugin | 웹팩
웹팩은 모듈 번들러입니다. 주요 목적은 브라우저에서 사용할 수 있도록 JavaScript 파일을 번들로 묶는 것이지만, 리소스나 애셋을 변환하고 번들링 또는 패키징할 수도 있습니다.
webpack.kr
https://webpack.kr/plugins/html-webpack-plugin/
HtmlWebpackPlugin | 웹팩
웹팩은 모듈 번들러입니다. 주요 목적은 브라우저에서 사용할 수 있도록 JavaScript 파일을 번들로 묶는 것이지만, 리소스나 애셋을 변환하고 번들링 또는 패키징할 수도 있습니다.
webpack.kr
'ETC' 카테고리의 다른 글
콘텐츠 스크립트에서 HMR 도입 (0) | 2025.02.20 |
---|---|
SPA에서 벗어나 보자 익스텐션 개발기3 (0) | 2025.02.08 |
SPA에서 벗어나 보자 익스텐션 개발기1 (2) | 2024.03.14 |
토큰 재발급 동기화 문제 (0) | 2024.03.11 |
Webpack 너무 느려.. Vite 마이그레이션 (0) | 2024.03.11 |