전에 React 체험을 했었는데 그 이후로 별다른 진전이 없다가 이제 조금 시간을 내어 더 공부해보려고 한다. 시작은 역시 시작문서로 하는게 좋을 것 같아서 Getting Started를 읽기 시작했다.
난관
We recommend using React with a CommonJS module system like browserify or webpack.
첫 문장에서 '턱!'하고 막혔다. 너무 오랜시간 javascript 세계를 떠나 있었나보다. 무슨 말인지 하나도 모르겠다. babel로 JSX를 javascript로 변환만 하면 되는거 아닌가 싶었는데 browserify, webpack를 사용한다고 한다. 그 것도 뭔지 모르지만 CommonJS module system도 뭔지 모른다. 빠르게 움직이는 세상에서 가만히 있다보니 바보가 되어있었다.
CommonJS
다행히 아주 유명한 것이라 잘 정리된 문서들이 많았다. 그 중에 네이버 D2에서 작성한 문서가 초보자에게 제일 친절한 것 같다. 정리해보자면 CommonJS module system 이라는 것은 require
를 사용해서 필요한 모듈을 가져다 쓸 수 있도록 하는 것이고 그 모듈을 만드는 방법이 module.exports
를 사용하는 것이다. AMD는 define
을 사용하는 것 같다.
아하! 그러니까 예제 코드에서 require를 사용해서 필요한 모듈을 로드하는 것이 바로 CommonJS module system인 것이고 browserify나 webpack이 require에 명시된 모듈을 가져와 넣어주는 역할을 하는 것이다.
// main.js
var React = require('react');
var ReactDOM = require('react-dom');
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
예제에서 이미 전역인 React나 ReactDOM을 왜 require하는 것인지 궁금했는데 이런 이유였다. 이제 이게 뭔지 알았으니 browserify와 webpack을 살펴봐야겠다.
browserify
browserify는 require
로 사용한 모듈을 포함시켜주는 도구다. 사용방법은 아래와 같은데 react의 preset으로 babelify를 transform으로 사용하였다.
$ npm install --save react react-dom babelify babel-preset-react
$ browserify -t [ babelify --presets [ react ] ] main.js -o bundle.js
package.json에 transform을 미리 지정해두면 좀 더 간단한 명령어로 수행이 가능하다.
"browserify": {
"transform": [
["babelify", {"presets": ["react"]}]
]
}
browserify은 옵션을 매번 지정해야하므로 단독으로 사용하기는 어렵고 grunt나 glup에서 browserify를 사용하도록 하는 작업이 필요해 보인다. (지금까지 알아본 바로는...)
webpack
webpack은 browserify와 같은 일을 하지만 조금 다른 점이 있다. webpack.config.js 라는 설정파일을 사용하는 것이다.
$ npm install --save react react-dom babel-preset-react
$ webpack
Getting Started 문서에서 말한 위 명령은 그냥 실행해서는 정상동작하지 않는다. 아래와 같은 설정파일을 먼저 만들어두고 실행해야 정상적으로 동작한다.
// webpack.config.js
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /\.jsx?$/,
loader: 'babel',
query: {
presets: ['react']
}
}
]
}
}
webpack 자체를 잘 몰랐으니 모르면서 무작정 해본 내 잘못이긴 하지만 적어도 어떤 loader를 사용해야 하는 지는 문서에서 좀 말해줬다면 좋았을텐데 하는 아쉬움이 있다. 정말 오랜 시간 삽질했다.
당연히 babel-loader가 있다고 생각했어야 한걸까? jsx-loader를 사용하도록 했다가 jsx-loader github에 가 보고서야 babel을 사용해야함을 알았다.
용량
위의 과정으로 만든 bundle.js는 browserify, webpack 모두 670kb에 달했다. React, ReactDOM의 모든 코드가 bundle.js에 포함되기 때문이었다. 공개된 cdn이 있는 라이브러리를 굳이 이렇게 포함할 필요는 없으니 제외해보기로 했다. webpack으로만 해봤다.
externals: {
'react': 'React',
'react-dom': "ReactDOM"
}
webpack.config.js에 위 내용을 포함하면 require('react')는 전역의 React를 그대로 사용하게 된다. 이로써 용량은 1.7kb가 되었다. 다만 이렇게 할 경우 아래와 같이 cdn의 라이브러리도 반드시 로드를 해주어야 한다.
<script src="https://fb.me/react-0.14.3.min.js"></script>
<script src="https://fb.me/react-dom-0.14.3.min.js"></script>
<script src="bundle.js"></script>
이제 시작
Getting Started 문서의 짧은 따라하기가 끝났다. (ㅠㅠ) 이제 시작이다.