시작하기전에, NPM을 사용하기 위해서 Node.js 가 설치 되어 있어야합니다.
또한 당신의 기기에서 커맨드 라인(터미널 같은)에 접근할수 있는 방법을 알아야합니다.
우리가 Rollup에 가장 쉽게 접근할 수 있는 방법은 CLI를 사용하는 것입니다.
지금부터, 우리는 rollup을 전역적으로 설치 할 것입니다.(나중에 로컬 설치를 하는 방법도 말씀 드릴 것이니 걱정하실 필요 없어요).
이런 명령어를 입력하시면 됩니다.
npm install rollup --global
# or `npm i rollup -g` for short
이제 rollup을 사용하실 수 있어요!
rollup
아무런 추가 명령어 없이 rollup 만 작성하신다면, rollup은 사용 설명서를 출력해줍니다.
이건 rollup --help나 rolup -h 같은 명령어와 똑같은 역할을 합니다.
mkdir -p my-rollup-project/src
cd my-rollup-project
첫번째로, 진입점이 필요헙니다.
src 경로에 main.js 파일을 만들어줄게요.
// src/main.js
import foo from './foo.js';
export default function () {
console.log(foo);
}
그리고 우리의 진입점에서 import 하는 foo.js 모듈을 만들어주겠습니다.
// src/foo.js
export default 'hello world!';
이제 번들을 만들어 봅시다.
rollup src/main.js -f cjs
여기서 "-f" 옵션 (--format의 줄입말입니다.) 은 우리가 만들고 있는 번들의 형태를 특정화 해줍니다.
이 경우에서는 CommonJS (Node.js 환경에서 실행 되는 형태) 일 것입니다.
우리가 output 파일을 구체화 해주지 않았기 때문에, 표준 출력 방식으로 바로 출력 됩니다.
'use strict';
const foo = 'hello world!';
const main = function () {
console.log(foo);
};
module.exports = main;
아니면 이런식으로 번들을 저장해줄수도 있어요.
rollup src/main.js -o bundle.js -f cjs
(또 rollup src/main.js -f cjs > bundle.js 로 명령을 실행 시켜줄수도 있습니다. 하지만 이 방식은 소스맵을 사용한다면 유연성이 떨어집니다.)
이 코드를 실행시켜보세요.
node
> var myBundle = require('./bundle.js');
> myBundle();
'hello world!'
축하합니다! 첫 번들을 만드는데에 성공하셨습니다.
지금까진 괜찮았습니다.
하지만 더 많은 옵션들을 추가하기 시작하면, 명령어를 입력하는데에 조금 귀찮아집니다.
이러한 반복들을 줄이기 위해서, 우리가 필요한 옵션들을 전부 담고 있는 config 파일을 만들 수 있어요.
config 파일은 자바스크립트로 쓰여져 있고, CLI로 입력하는 것보다 훨씬 유연합니다.
rollup.config.mjs 라는 파일을 루트 경로에 만들어주고 밑의 코드를 넣어보세요.
// rollup.config.mjs
export default {
input: 'src/main.js',
output: {
file: 'bundle.js',
format: 'cjs'
}
};
( CJS 모듈을 사용할수 있다는 것을 기억하세요. 만약 그렇게 된다면 module.exports = {/ config /} 식으로 작성하셔야합니다.
config 파일을 사용하기 위해서, 우리는 --config 나 -c 문자를 사용해야합니다.
rm bundle.js # so we can check the command works!
rollup -c
또 동일한 명령어 옵션으로 config 안에 있는 다른 옵션들을 덮어 씌울수도 있습니다.
rollup -c -o bundle-2.js // # `-o` is equivalent to `--file` (formerly "output")
알아둘점 : rollup 은 rollup 그 자체가 config 파일을 수행합니다. 그래서 export default (내보내기 기본 모듈) 문법을 사용할수가 있는겁니다.
코드들은 바벨이나 다른것들로 트랜스파일 되지 않기 때문에, 당신이 실행시키고 있는 Node.js 버전이 지원되는 ES2015 기능들을 사용할수 있는 겁니다.
rollup --config rollup.config.dev.mjs
rollup --config rollup.config.prod.mjs
우리가 만약 제한된 환경이나 팀으로 협업을 하게 된다면, rollup을 로컬 의존성으로써 확장 시킬 수 있습니다.
rollup을 로컬에서 설치하는 것은 다수의 기여자들이 rollup 을 따로따로 설치해주어야하는 것을 방지하고, 같은 버전의 rollup 을 사용하는것을 보장해줍니다.
NPM을 사용해서 rollup 을 로컬에서 설치해봅시다.
npm install rollup --save-dev
// or
yarn -D add rollup
설치가 끝난후에, rollup은 당신의 프로젝트 root 디렉토리에서 실행 될수 있습니다.
npx rollup --config
// or
yarn rollup --config
설치가 됐다면, package.json에 build 스크립트를 추가해주는것이 관례입니다.
이는 모든 기여자들에게 편리성을 제공해줍니다.
{
"scripts": {
"build": "rollup --config"
}
}
알아둘점 : 로컬에서 한번 설치가 되면, npm 과 yarn 은 패키지 스크립트에서 호출될때 종속성의 bin 파일을 확인하고 Rollup을 실행시킵니다.
지금까지, 우리는 엔트리 포인트와 상대 경로에서 import 된 모듈로부터 간단한 번들만 만들어보았습니다.
만약 더 복잡한 번들을 빌드해보고 싶다면, 더 많은 유연성이 필요할거에요.
예를들어서 npm으로 설치된 모듈들을 import 해온다던가, 바벨로 코드를 컴파일 한다던가, JSON파일을 이용해서 작업을 한다던가 등이요
이를 위해서, 우리는 번들링 과정에서 Rollup의 행동을 변화시켜주는 중요한 플러그인들을 사용할 것입니다.
이런 멋진 플러그인들은 Rollup Awesome List에 나열되어 있습니다.
이 튜토리얼을 위해서, 우리는 @rollup/pugin-json 이라는 플러그인을 사용해볼 것입니다.
이는 JSON 파일로부터 데이터를 Rollup이 import 해오도록 해줍니다.
루트폴더 package.json에 파일을 만들고 밑의 코드를 추가해봅시다.
{
"name": "rollup-tutorial",
"version": "1.0.0",
"scripts": {
"build": "rollup -c"
}
}
@rollup/plugin-json을 개발용 의존성으로 설치해줍시다.
npm install --save-dev @rollup/plugin-json
(우리가 --save 보다 --save-dev로 해주는 이유는, 우리의 코드가 실질적으로 플러그인에 의존하고 있지 않기 때문입니다. 이는 번들을 빌드할때만 작동하기 때문이에요.)
src/main.js 파일을 package.json에서 import 하기 위해서 src/foo.js 대신에 업데이트 해주세요.
// src/main.js
import { version } from '../package.json';
export default function () {
console.log('version ' + version);
}
JSON파일을 포함하기 위해서 rollup.config.mjs 코드를 변경해주세요.
// rollup.config.mjs
import json from '@rollup/plugin-json';
export default {
input: 'src/main.js',
output: {
file: 'bundle.js',
format: 'cjs'
},
plugins: [json()]
};
Rollup을 npm run build와 실행시켜주세요. 결과물은 대략 이렇습니다.
'use strict';
var version = '1.0.0';
function main() {
console.log('version ' + version);
}
module.exports = main;
알아둘점 : 우리가 실질적으로 필요한 데이터만 가져옵니다. 이름이나, 개발자용 의존성이나 다른 package.json 같은 경우는 무시됩니다. 실행시에 트리쉐이킹 됩니다.
몇몇 플러그인들은 특정한 몇몇 결과물에게 적용될수 있습니다.
기술적인 디테일들을 위해, 이 plugin hooks를 살펴보세요.
output plugin들이 무엇을 할수 있는지 작성 되어있습니다.
간단히 말해서, 이러한 플러그인들은 Rollup의 주요한 분석이 완료된 후에 코드들을 수정할수 있습니다.
Rollup은 만약에 호환되지 않는 플러그인이 output 플러그인으로 사용된다면 경고해줍니다.
가능한 사용사례는, 브라우저에서 사용되는 번들을 최소화 하는 것 입니다.
한번 이전의 예를 확장해서, 축소되지 않은 빌드와 축소된 빌드를 예로 제공해보겠습니다.
@rollup/plugin-terser를 설치해봅시다.
npm install --save-dev @rollup/plugin-terser
rollup.config.mjs 를 두번째 축소된 결과물을 추가 하기 위해서 수정해주세요.
형식적으로, 우리는 즉시실행함수를 작성해줍니다.
이 형식은 다른 코드들과의 원치 않는 상호작용을 피함과 동시에 브라우저 내에서 스크립트 태그를 삽입하여 실행시키기 위해 코드를 한번 감싸줍니다.
내보내기가 있으므로, 우리는 전역 변수의 이름을 제공해야합니다.
이 전역변수는 우리의 번들에 의해 만들어졌습니다.
이 ㅇ전역변수를 통해서 다른 코드들은 우리의 export에 접근할 수 있습니다.
// rollup.config.mjs
import json from '@rollup/plugin-json';
import terser from '@rollup/plugin-terser';
export default {
input: 'src/main.js',
output: [
{
file: 'bundle.js',
format: 'cjs'
},
{
file: 'bundle.min.js',
format: 'iife',
name: 'version',
plugins: [terser()]
}
],
plugins: [json()]
};
bundle.js 외에도, Rollup은 bundle.min.js 라는 2번째 파일을 만들 것입니다.
var version = (function () {
'use strict';
var n = '1.0.0';
return function () {
console.log('version ' + n);
};
})();
코드를 분리하기 위해서, 동적인 로딩이나, 다수의 진입점들 같이 Rollup은 자동으로 코드들을 덩어리 단위로 쪼개는 경우들이 있습니다.
그리고 output.manualChunks 옵션을 통해서 Rollup에게 명시적으로 어떤 모듈들을 별도의 덩어리로 분리할 것인지 지정해주는 방법도 있습니다.
코드 분할 기능을 사용하여서 몇몇 특정 모듈만 함수가 실행 된후에 가져오도록 하는 lazy loading 기능을 사용하려면, 우리는 원래의 예였던 src/main.js 로 돌아가서 정적이었던 src/foo.js가 동적으로 로드 되도록 수정해주어야 합니다.
// src/main.js
export default function () {
import('./foo.js').then(({ default: foo }) => console.log(foo));
}
Rollup은 요청시에만 로드되는 분리된 청크를 생성하기 위해서 dynamic import 기능을 사용합니다.
Rollup이 두번째 청크를 어디에 위치시켜야하는지 알도록 하기 위해서, --file 옵션을 사용하기 보다 --dir 옵션을 사용해서 결과물이 저장될 폴더를 지정해줍니다.
rollup src/main.js -f cjs -d dist
이는 두가지의 파일을 담고있는 dist 파일을 만들것입니다. main.js 와 chunk-[hash].js 인데 , [hash]는 hash string을 기본으로 한 컨텐츠 내용입니다.
또 output.entryFileNames나 output.chunkFileNames 를 사용해서 당신만의 독자적인 네이밍 패턴을 적용시킬 수도 있습니다.
그리고 여전히 코드를 전과 똑같이 같은 결과물로 실행시킬 수 있습니다.
./foo.js의 로드 및 파싱 작업은 내보낸 함수를 처음 호출한 후에만 시작되므로 조금 느리기는 합니다.
node -e "require('./dist/main.js')()"
우리가 만약 --dir 옵션을 사용하지 않는다면, Rollup은 청크들을 기본 출력 형식으로 출력하고,
청크 바운더리들에 하이라이트 되어서 커멘트를 남깁니다.
//→ main.js:
'use strict';
function main() {
Promise.resolve(require('./chunk-b8774ea3.js')).then(({ default: foo }) =>
console.log(foo)
);
}
module.exports = main;
//→ chunk-b8774ea3.js:
('use strict');
var foo = 'hello world!';
exports.default = foo;
이는 만약 한번만 사용되어야하는 무거운 기능들을 로딩하고 파싱하여야할때 유용합니다.
코드 분할의 다른 사용 용도는 같은 의존성들을 공유하는 여러 엔트리 포인트들을 지정하는데에 있습니다.
또다시 우리의 2번째 진입점인 src/main2.js를 추가하기 위해서 우리의 예를 확장시켜보겠습니다.
이 src/main2.js 는 우리가 원래 예에서 했던것처럼 src/foo.js를 정적으로 import 해옵니다.
// src/main2.js
import foo from './foo.js';
export default function () {
console.log(foo);
}
만약 우리가 이 진입점들 둘다에 Rollup을 실행시키면, 총 3개의 청크들이 만들어집니다.
rollup src/main.js src/main2.js -f cjs
결과물은 이렇습니다.
//→ main.js:
'use strict';
function main() {
Promise.resolve(require('./chunk-b8774ea3.js')).then(({ default: foo }) =>
console.log(foo)
);
}
module.exports = main;
//→ main2.js:
('use strict');
var foo_js = require('./chunk-b8774ea3.js');
function main2() {
console.log(foo_js.default);
}
module.exports = main2;
//→ chunk-b8774ea3.js:
('use strict');
var foo = 'hello world!';
exports.default = foo;
어떻게 두개의 엔트리 포인트에서 똑같은 chunk를 import 해오는 것인지 알아야합니다.
Rollup은 코드를 절대 복제하지 않습니다.
대신에 로드하기 위한 최소한의 추가적인 청크만 생성합니다.
--dir 옵션은 파일을 디스크에 저장합니다.
ES 모듈, AMD 로더나 시스템JS를 통해서 브라우저에 대한 동일한 코드를 빌드 할 수 있습니다.
예를 들어서 -f es 를 네이티브 모듈에 사용하면 이와 같습니다.
rollup src/main.js src/main2.js -f es -d dist
<!doctype html>
<script type="module">
import main2 from './dist/main2.js';
main2();
</script>
또는 -f system 으로 SystemJS 를 사용하는 경우입니다.
rollup src/main.js src/main2.js -f system -d dist
SystemJS를 설치하세요.
npm install --save-dev systemjs
그리고 필요에 따라서 HTML 페이지에서 하나나 두가지의 엔드리 포인트들을 로드합니다.
<!doctype html>
<script src="node_modules/systemjs/dist/s.min.js"></script>
<script>
System.import('./dist/main2.js').then(({ default: main }) => main());
</script>
예를 들어서 rollup-starter-code-splitting을 예로 들수 있는데, 이는 브라우저에서 네이티브 es모듈을 사용하는 웹앱들을 어떻게 설정해야하는지 알수 있습니다.
그리고 그것들을 만약 필요하다면 SystemJs를 사용해서 대체 할수 있습니다.