react 컴포넌트 제작부터 배포까지의 과정을 다뤄보고자 한다.
이번 포스팅은 컴포넌트 제작을 위환 환경 구축 과정까지 할 예정이다. react-simple-image-slider를 제작하면서 쓰는 포스팅.
세부적인 내용을 확인하기 전에, 대략적으로 필요한 것들을 정리해보자.
대략 정리를 해보면 위와 같지만, 사실 실제 할 일들은 그리 많지 않다.
나는 그동안 개발을 해오면서 gulp
와 webpack
이 2가지를 사용한 경험이 있다.
하지만, 이번 컴포넌트 제작은 rollup
이라는 번들 도구를 사용할 예정이다.
리액트를 제작한 페이스북에서도 rollup으로 현재 빌드를 하고 있고,
Webpack and Rollup: the same but different란 제목의 재밌는 글을 읽은 이유도 있다.
이 글에서 Use webpack for apps, and Rollup for libraries
구문이 눈에 들어왔다.
또, rollup은 react
, vue
, ember
, D3
, ThreeJs
등에서도 사용하는 도구로 소개를
하고 있으니, 이정도면 한 번 경험해 볼 만한 가치는 충분할 것이다.
Rollup 공식홈페이지의 소개를 보면, rollup
은 작거나 큰 단위 조각의 코드, 혹은 라이브러리나 애플리케이션과 같이 더 복잡한 조각들의 코드들을 컴파일해주는 도구로 소개되어 있다. 또한, ES6, CommonJS, AMD와 같은 방식들의 모듈 제작 환경을 모두 지원한다.
install
제작하고자하는 컴포넌트 디렉토리를 생성 후, 설치를 해주자.
mkdir react-simple-image-slider
cd react-simple-image-slider
..
( npm init을 통해 package.json을 생성 )
..
npm install rollup rollup-plugin-babel --save-dev
위에서 설명했던대로 babel을 사용할 예정이므로 plugin도 설치를 같이 해준다. babel에 대한 자세한 설정은 아래에서 다시 다루겠다.
rollup.config.js
rollup config 파일을 아래와 같이 작성하였다.
import babel from 'rollup-plugin-babel';
import pkg from './package.json';
const external = (id) => !id.startsWith('/') && !id.startsWith('.');
export default {
input: './src/ImageSlider.jsx',
output: {
file: pkg.main,
format: 'cjs',
},
plugins: [babel({ runtimeHelpers: true })],
external,
};
만약, external에서 외부 의존성이 있는 모듈이라면 해당 모듈은 번들링시 포함하지 않게 된다. 예를 들어 지금은 react 컴포넌트를 제작하는 것이므로 reactjs와 같은 모듈은 npm으로 설치하여 import하여 사용을 하게 될 것이다. 여기서 이러한 external한 외부 모듈들은 번들링 결과물에 포함이 되지 않는다.
external: ['react'];
위와 같이 직접 모듈명을 작성해주어도 되지만, 외부 모듈들이 많아지면 번거롭게 다 지정해주어야 하기 때문에, 함수를 하나 작성하여 처리해주었다. 아래와 같이 import하는 모듈들의 경로를 기준으로 판단하면 쉽게 외부 모듈인지 확인이 가능하다.
import React from 'react';
import ImageSliderPropTypes from './ImageSliderPropTypes';
import ImagePreLoader from './ImageSliderPreLoader';
package.json
scripts에 rollup 명령어를 아래와 같이 추가해준다.
{
"scripts": {
"build": "rollup -c",
"build:watch": "rollup -c --watch"
}
}
-c
flag는 --config
와 동일하며, config파일명이 rollup.config.js
일 경우, 파일명은 적지 않아도 된다.
--config
뒤에 파일명을 적어 특정 파일의 설정을 참조할 수 도 있다.
또, watch flag을 통해 소스 변경시마다 번들링이 되게 해준다.
babel에 대해선 따로 설명을 하진 않겠으나, 간략하게 말하자면 ES2015+ 자바스크립트 코드를 구형 브라우저, 환경에서 적용할 수 있게 해주는 컴파일러이다.
babel은 버전이 바뀌면서 셋팅값들이 바뀌는 부분이 있으므로 꼭 Babel 공식홈페이지에서 필요한 부분을 확인하자.
install
설치해야 할 리스트는 아래와 같다.
위의 리스트들을 모두 설치해주자.
npm install ... --save-dev
.babelrc
babel의 설정은 아래와 같이 해준다.
{
"presets": [
["@babel/preset-env", {
"loose": true,
"modules": false,
"targets": "> 0.25%, not dead"
}],
"@babel/preset-react"
],
"plugins": [
"@babel/plugin-transform-runtime",
"@babel/plugin-proposal-class-properties"
]
}
어떤 preset과 plugin들을 쓸 것인지 명시만 해주면 된다.
잠깐, 확인할 부분이 있다면 babel 7.0에서부터는 preset 설정이 조금 바뀌었다는 것이다.
기존에 es-2015
, stage-0
과 같은 preset들은 deprecated 되었고 위처럼 target을 지정해주면 된다.
> 0.25%, not dead
은 점유율이 0.25%인 브라우저들을 타겟으로 컴파일 된다는 의미이다.
( IE10, Blackberry와 같은 보안업데이트가 중단된 브라우저는 무시한다고 한다. )
Babel 공식홈페이지에서 더 자세히 확인 할 수 있다.
테스트 개발 환경 설정은, 실제 제작한 컴포넌트가 react App에서 import하여 잘 작동이 되는지를 위한 것이다. 4.x대의 버전의 Webpack으로 테스트 환경을 설정할 예정이다. Webpack에 대한 소개나 설정 방법 등의 자세한 설명은 생략할 예정이다. ( Webpack을 주목적으로 다루는 내용이 아니므로. )
install
아래와 같이 설치해준다.
npm install webpack webpack-cli webpack-dev-server --save-dev
// "webpack": "^4.17.2",
// "webpack-cli": "^3.1.0",
// "webpack-dev-server": "^3.1.7"
webpack 4.x버전부터는 webpack-cli를 같이 설치해줘야 커맨드라인에서 webpack 명령어를 사용할 수 있다. 또, 개발모드 지원을 위해 webpack-dev-server를 설치하자.
webpack.config.js
const path = require('path');
module.exports = {
entry: {
index: ['@babel/polyfill', './example/App.jsx'],
},
output: {
filename: '[name].js',
path: path.join(__dirname, 'example'),
},
module: {
rules: [
{
test: /\.jsx$/,
exclude: /node_modules/,
use: 'babel-loader',
},
],
},
mode: 'production',
plugins: [],
devServer: {
contentBase: './example',
host: '0.0.0.0',
},
};
테스트 App을 위한 Webpack 설정파일이다.
현재 컴포넌트의 디렉토리에서 테스트 App의 경로를 ./example
로 설정하였고,
babel-loader
와 webpack-dev-server
관련된 내용을 확인할 수 있다.
( babel의 preset과 plugin인 설정 등은 위에서 생성한 .babelrc 파일을 따른다. )
이외에 기본적인 React App을 빌드 시 필요한 html파일과 reactjs 설치 등은 생략하겠다.
./example/App.jsx
간략하게 React 소스의 index부분만 잠깐 살펴보자.
import React from 'react';
import ReactDOM from 'react-dom';
import ImageSlider from '..';
class App extends React.Component {
render() {
return (
<div>
<h1>Image Slider Example</h1>
<ImageSlider />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('App'));
import ImageSlider from "..";
를 보면 상위 디렉토리( =컴포넌트 루트 디렉토리 )에서 모듈을 import하는 것을
확인할 수 있다.
( rollup으로 빌드한 컴포넌트의 소스가 package.json
의 main
값으로 지정하였기 때문 )
package.json
scripts에 webpack 명령어를 아래와 같이 추가해준다.
"scripts": {
"example": "webpack-dev-server --mode development",
"build": "rollup -c",
"build:watch": "rollup -c --watch"
},
npm run example
을 통해 webpack-dev-server를 실행시키면 된다.
--inline
이나 --hot
과 같은 flag를 추가하여 Live Reloading, Hot Module Reloading의 기능을
쓰면 더 편리할 수도 있다.
Live Reloading은 전체 페이지가 리로드 되고, Hot Module Reloading은 수정된 소스의 해당 모듈만 리로딩이 된다.
마지막으로 eslint 설정, 폴더구조 등 정리를 하자면..
eslint
아마 react를 사용하고 babel을 사용한다면 대부분 비슷한 설정이 될 수도 있겠지만, 자신들의 코딩컨벤션을 적용하여 설정을 해두자. 나는 여기서 아래와 같이 설정하였다.
directory structure
현재 디렉토리의 index가 없지만, package.json
에서 main
속성을 dist의 배포용 소스로 지정하였다.
따라서 추후에 컴포넌트를 import할 때 index를 못 찾거나 하는 문제가 발생하지 않는다.
React 컴포넌트 제작기를 총 3번에 나눠 포스팅 계획을 세웠는데, 2번째는 실제 React 컴포넌트 소스를 개발과정을, 3번째는 npm, git에 업로드까지의 과정을 다룰 예정이다.