React-webpack 시리즈 - 2 (Polyfill & babel)
아 시리즈1때는 아침6시에 일어났는데....
오늘은 새벽에 소라운스러운 일이 있어서 7시30분 되서야 시작한다...
저번 글에서는 CRA처럼 npm run start를 입력했을때 개발중인 웹을 확인할 수 있도록 webpack-dev-server를 열었다.
정말 열릴정도로만의 패키지를 사용하였고, 이번글에서는 추가적인 모듈들을 추가할예정이다.
(지난번에 추가해야했어할 모듈들도 있었지만 하나씩 어디에 쓰이는지 확인하고자 추가하지 않았던 모듈들을 추가할예정이다)
1. Polyfill 이 뭘까?
폴리필은 JS의 최신문법을 지원하지 않는 구형 브라우저에서 해당기능을 구현하는 코드 조각이다.
즉 오래된 브라우저에서 최신 기능을 사용할 수 있도록 도와주는 코드 조각이나 라이브러리를 말한다.(약간 모방해주는?)
이러한 기능들을 babel을 이용하여 코드를 변환하고 다양한 환경에서 실행 할 수 있도록 도와주는 것 이다.
2. Polyfill 적용 패키지 설치
Polyfill을 적용하기 전에 이전에 설치하지 못했던 패키지를 설치하고 넘어가려한다
npm i -D @babel/cli @babel/core @babel/preset-env
cli: babel의 명령줄 도구이며 babel을 명령줄에서 실행하고 코드를 변환 할 수 있다.
core: babel의 핵심 패키지다.(parser, traverse, generator, template)
preset-env: 대상환경에 따라 필요한 Polyfill 과 플러그인을 추가하는 역할
preset-env를 설치하고 대상환경에서 사용되는 브라우저의 버전을 고려하여 필요한 Polyfills를 자동으로 추가 하거나 제거한다고 한다. 하지만 ES6+ 기능에 대한 최신 Polyfills를 제공하기위해서는 cors-js를 같이 사용해야한다.
npm i -D core-js@3
여기까지 작성한후에 babel설정은 어느정도 끝났다고 생각했지만 core-js@3를 사용할경우 또다른 문제가 발생한다.
네임스페이스 .. 찾아본결과 core-js는 지속적으로 업데이트 되면 최신 ECMAScript 표준에 따라 새로운 Polyfills를 추가한다. 하지만 전역의 오염을 발생시킨 다고한다. 예를 들자면? ES6이후에 Array 객체에 추가된 includes 메서드를 Polyfills이
적용되면서 변수, 함수 이름으로 사용되면서 에러가 발생되는것이다. 하지만 추가된것은 includes만 추가된 것 이 아니기때문에 많은 오류가 발생할수도 있는거다.
이것을 방지하기위해 찾아본결과 아래 명령어를 같이사용하면된다.
npm i -D @babel/plugin-transform-runtime @babel/runtime @babel/runtime-corejs3
@babel/plugin-transform-runtime
Babel이 필요한 Polyfills를 추가할 때 전역 네임스페이스 오염을 방지하고, 필요한 Polyflls를 모듈 스코프 내에서 관리한다.
@babel/runtime
@babel/plugin-transform-runtime에 필요한 런타임 라이브러리를 제공한다. babel이 코드를 효율적으로 변환할수있도록 도움
@babel/runtime-corejs3
core-js@3의 최신버전을 활용하고 코드 변환 과정에서 필요한 Polyfills를 관리하는 역할을 한다.(core-js@3를 포함하고있다.)
3. babel설정 적용하기
//babel.config.json
{
"presets": [
"@babel/preset-react",
"@babel/preset-typescript",
"@babel/preset-env"
//useBuilIns: "usage" , corejs:3 플러그인에서 사용
],
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"corejs": 3
}
]
]
}
@babel/preset-env에 추가해야할 옵션은 @babel/plugin-transform-runtime에서 사용하게 되었다. 공식문서에서는 해당 플러그인을 사용하면 preset-env 의 useBuilIns를 사용하지 말라고 명시되어 있다. 이유가 뭘까? 위에서 언급한 전역 오염에 대한 문제이다. useBuilIns는 여러가지 옵션이 있지만, 그중 usage는 Polyfills를 자동으로 추가해준다. 이것을 사용하지 않고 플러그인을 사용함으로써 Polyfills를 모듈 스코프 내에서 관리한다고 한다. 즉 코드 변환 중에 전역 오염을 방지하는것이다. 또한 위에서 설치한 core-js@3는 설치하지않아도 옵션으로 적용해주어도 된다.
4. style-loader, css-loader
기본적인 babel의 설정을 다했으므로 css파일을 적용해보려한다.
[css파일생성]
// index.css
html,body{
margin: 0;
padding: 0;
height: 100%;
}
body{
display: flex;
background-color: rgb(146, 44, 44);
justify-content: center;
align-items: center;
}
[css 파일 import]
//index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import "./index.css" -- 추가
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
[css 파일 적용을 위한 loader]
npm i -D style-loader css-loader
[webpack에 loader 적용]
// webpack.dev.js
...code
module:{
rules:[
{
test: /\.(ts|tsx|js|jsx)$/,
use: "babel-loader",
exclude: /node_modules/,
},
{
test: /\.css$/,
use: ["style-loader","css-loader"]
},
]
},
정상적으로 적용되는것을 볼수있다. 그런데 여기서 주의할점은 style-loader 과 css-loader의 순서가 바뀌면 에러가 발생한다.
이러한이유를 찾아보았다. webpack의 loader는 역순으로 해석을한다. 즉 글씨를 읽는 왼쪽 -> 오른쪽 방향이 아닌 왼쪽 <- 오른쪽 방향으로 loader을 읽는것이다. 그런데 이렇게 읽는 다고 왜 오류가 날까? 그이유는 각각의 loader의 역할이 있기 떄문이다. css-loader는 css파일을 JS모듈로 해석하고 style-loader는 Js모듈에서 동적으로 스타일을 생성하고, 생성된 스타일은 <head>태그에 추가하여 스타일을 적용한다. 각각의 loader의 순서가 꼬이기때문에 위와같은 에러가 발생하는 것 같다.
5. styled-components
스타일 컴포넌트도 적용해보자
npm i styled-components
import React, {useState} from "react";
import styled from "styled-components";
const Layout = styled.div`
display: flex;
justiyf-content: center;
align-items: center;
gap: 10px;
background-color: gray;
padding: 20px;
border-radius: 10px;
`
function App(){
const [count, setCount] = useState<number>(0);
return(
<Layout>
<span>Count: {count}</span>
<button onClick={()=> setCount( count + 1)}> + </button>
<button onClick={()=> setCount( count - 1)}> - </button>
</Layout>
);
}
export default App;
react의 styled-components는 css-loader, style-loader과 연관이 없다. Css-in-JS 방식이기때문!
이번글도 여기서 마무리하고 다음 글에서 프로덕션 코드를 따로 설정하여 build를 할예정이다.
webpack에는 최적화 플러그인이 여러개 있는것 같다. 처음에 말했듯이, 개발,프로더션, 공통 으로 분리할 예정인데
다음 글에서는 마무리 지을수 있을 것 같다.