Skip to main content

Command Palette

Search for a command to run...

[ 살펴보기 ] Rollup - Basics

Updated
6 min readView as Markdown
[ 살펴보기 ] Rollup - Basics
C

A developer living in Busan, Korea

Application을 개발할 때 사용되는 여러 module을 하나의 파일 또는 지정한 여러 file로 bundle할 때 Rollup이나 Webpack과 같은 module bundler를 사용한다. Rollup은 Forntend build tool인 Vite가 내부적으로 사용하고 있는 module bundler이며 해당 포스트를 통해 Rollup의 기초 사용법을 살펴보자.

우선 rollup을 사용하기 위해 package를 설치해준다.

npm install -D rollup

그리고 다음과 같이 package.json에 rollup을 실행하기 위한 script를 추가해준다.

...
"type": "module",
"scripts": {
    "build": "rollup ./src/index.js -o ./dist/bundle.js"
},
...

이제 간단한 테스트를 위해 다음 두 파일을 생성해서 bundle test를 해보자.

src/index.js

import { sum } from "./utils/calculate";

const result = sum(2, 3);

console.log(result);

src/utils/calculate.js

export const sum = (firstNum, secondNum) => {
  return firstNum + secondNum;
};

위의 파일을 추가하고 npm run build command를 실행하면 다음과 같이 dist folder에 bundle.js 파일이 생성된 것을 확인할 수 있다.

dist/bundle.js

const sum = (firstNum, secondNum) => {
  return firstNum + secondNum;
};

const result = sum(2, 3);

console.log(result);

위와 같이 cli를 실행할 때 option을 설정하는 방법도 있지만 configuration file을 생성해서 bundle option을 설정해두는게 좋다. proejct root에 rollup.config.js 파일을 생성하고 위에서 option으로 전달한 값을 config 파일에 설정해준다

rollup.config.js

 export default {
  input: "src/index.js",
  output: {
    file: "./dist/bundle.js",
  },
};

그리고 package.json build script는 다음과 같이 수정해 준다. --config option을 전달하면 configuration file 설정 값을 기반으로 bundle을 수행한다.

package.json

...
"type": "module",
"scripts": {
    "build": "rollup --config"
},
...

--config option을 전달하면 default로 rollup.config.js 파일을 사용하며 default config file이 아닌 다른 config file을 설정해주고자 한다면 다음과 같이 --config option뒤에 사용할 config file의 이름을 명시해준다.

...
"type": "module",
"scripts": {
    "build": "rollup --config rollup.config.dev.js"
},
...

Typescript

Typescript file을 rollup을 통해 bundle 해주기 위해선 plugin을 설치하여 적용해야 한다. typescript package뿐만 아니라 tslib package도 rollup typescript plugin의 peerDependencies이므로 함께 설치해준다.

npm install -D typescript tslib @rollup/plugin-typescript

이제 project root에 typesciprt config 파일인 tsconfig.json을 직접 생성하여 설정하거나 다음 command를 실행하면 기본적인 config file을 생성해준다.

npx tsc --init

그리고 rollup.config.js파일에 다음과 같이 plugin인 적용해준다.

import typescript from "@rollup/plugin-typescript";

export default {
  input: "src/index.ts",
  output: {
    file: "./dist/bundle.js",
  },
  plugins: [typescript()],
};

위와 같이 설정하고 다시 npm run build를 실행하면 정상적으로 typesciprt가 js로 변환되어 bundle 작업이 이루어진 것을 확인 할 수 있다.

rollup이 bundle을 진행하며 plugin을 통해 typesciprt file을 transpile할 때 tsconfig.json 설정된 값에 따라 typesciprt file을 transpile한다. rollup typesciprt plugin에 설정할 수 있는 option은 documentation을 통해 확인할 수 있다. ( Reference - Options )

Npm Packages

Rollup은 default로 npm 또는 다른 registry에서 install한 package resolution을 지원하지 않는다. 만약 다음과 같이 ramda package를 설치해 사용한다고 가정해보자.

import { compose } from "ramda";

const splitWords = (val: string) => val.split(" ");
const arrayLength = (val: any[]) => val.length;
const stringArrayLength = compose(arrayLength, splitWords);
const result = stringArrayLength("aaa bbb ccc");
console.log(result);

그리고 위의 파일을 rollup을 통해 bundle을 수행하면 결과는 아래와 같다.

import { compose } from 'ramda';

const splitWords = (val) => val.split(" ");
const arrayLength = (val) => val.length;
const stringArrayLength = compose(arrayLength, splitWords);
const result = stringArrayLength("aaa bbb ccc");
console.log(result);

위의 코드는 nodejs에서는 동작하지만 browser에서는 동작하지 않는다. Browser는 ramda라는 package를 어떻게 찾아야 하는지 알지 못하기 때문이다.

Browser에서 위의 코드가 동작하려면 ramda package에서 import하고 있는 compose function과 compose function이 의존하는 다른 code가 bundle 파일에 포함 되어야 한다. 그리고 그 역할을 위해 필요한 package가 @rollup/plugin-node-resolve다.

npm install -D @rollup/plugin-node-resolve

rollup.config.js

import typescript from "@rollup/plugin-typescript";
import resolve from "@rollup/plugin-node-resolve";

export default {
  input: "src/index.ts",
  output: {
    file: "./dist/bundle.js",
  },
  plugins: [typescript(), resolve()],
};

이제 다시 npm run build command를 통해 input 파일을 bundle해보자. 그럼 다음과 같이 input 파일에서 사용된 compose function 역시 bundle에 포함된 것을 확인할 수 있다. 아래 예제에서 볼 수 있듯이 compose function이 다른 function에 의존하고 있으므로 bundle을 수행하면 compose function에 필요한 다른 code 역시 함께 bundle file에 추가된다.

dist/bundle.js

...

function compose() {
  if (arguments.length === 0) {
    throw new Error('compose requires at least one argument');
  }
  return pipe.apply(this, reverse(arguments));
}

const splitWords = (val) => val.split(" ");
const arrayLength = (val) => val.length;
const stringArrayLength = compose(arrayLength, splitWords);
const result = stringArrayLength("aaa bbb ccc");
console.log(result);

Peer Dependency resolution

만약 현재 application을 만드는 것이 아닌 npm에 배포할 library를 만든다고 가정해 보자. React project에서 사용할 수 있는 library를 만들고 있다면 react, react-dom package는 만들고 있는 library의 peerDependency가 되며 peerDependency는 library bundle 파일에 포함되는 것이 아닌 library를 install하여 사용하는 application의 dependencies로 설치되어야 하므로 library의 peerDepency는 다음과 같이 external property에 추가하여 해당 package code가 library bundle에 포함되지 않도록 설정할 수 있다.

import typescript from "@rollup/plugin-typescript";
import resolve from "@rollup/plugin-node-resolve";

export default {
  input: "src/index.ts",
  output: {
    file: "./dist/bundle.js",
  },
  plugins: [typescript(), resolve()],
  external: ["react", "react-dom"],
};

Plugins

위의 예제에서 살펴볼 수 있듯이 rollup은 다양한 plugin을 통해 bundle에 필요한 기능 추가할 수 있다. 예를 들어 source code에서 json 파일을 사용하려고 하면 @rollup/plugin-json plugin을 설치하면 rollup이 bundle시 json파일을 처리할 수 있다.

npm install -D @rollup/plugin-json

rollup.config.js

import typescript from "@rollup/plugin-typescript";
import resolve from "@rollup/plugin-node-resolve";
import json from "@rollup/plugin-json";

export default {
  input: "src/index.ts",
  output: [
    {
      file: "./dist/bundle.js",
    },
  ],
  plugins: [typescript(), resolve(), json()],
  external: ["ramda"],
};

information.json

{
  "username": "test name",
  "address": "test address"
}

src/index.ts

import { address } from "../information.json";

const result = address;

console.log(result);

Babel

Rollup을 통해 source code를 bundle할 때 babel을 통해 target ecmascript version으로 transpile하고 싶다면 babel plugin을 통해 transpile 작업을 수행할 수 있다. 우선 babel을 적용하기 위해 필요한 package들을 설치한다.

npm i -D @babel/core @babel/preset-env @rollup/plugin-babel @rollup/plugin-node-resolve

그리고 project root에 bable.config.json 파일을 생성하고 preset을 설정해준다. Babel에 대한 기본적인 내용은 [ 살펴보기 ] Babel - Basics 포스트를 통해 확인할 수 있다.

babel.config.json

{
  "presets": ["@babel/preset-env"]
}

그리고 rollup configuration file에 다음과 같이 bable plugin을 추가해주자.

import typescript from "@rollup/plugin-typescript";
import resolve from "@rollup/plugin-node-resolve";
import babel from "@rollup/plugin-babel";

export default {
  input: "src/index.ts",
  output: [
    {
      file: "./dist/bundle.js",
    },
  ],
  plugins: [
    typescript(),
    resolve(),
    babel({
      babelHelpers: "bundled",
      extensions: [".js", ".ts"],
    }),
  ],
  external: ["ramda"],
};

위의 예제와 같이 babel plugin을 추가하고 bundle을 진행해보면 babel에 적용되어 arrow function이 다음과 같이 일반 function으로 transpile되는 것을 확인할 수 있다.

index.ts ( bundle 전 )

export const sum = (firstNum: number, secondNum: number) => {
  return firstNum + secondNum;
};

const result = sum(1, 2);

console.log(result);

bundle.js ( bundle 후 )

var sum = function sum(firstNum, secondNum) {
  return firstNum + secondNum;
};
var result = sum(1, 2);
console.log(result);

export { sum };

Babel을 통해 transpile할 때 특정 browser version을 target하여 output을 transpile하고자 한다면 아래와 같이 babel.config.json의 preset option에서 target browser를 설정해 준다.

babel.config.json

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "chrome": "70" // target browser version
        }
      }
    ]
  ]
}

또는 다음과 같이 rollup.config.js에 설정한 babel plugin의 option을 통해 설정해줄 수도 있다.

import typescript from "@rollup/plugin-typescript";
import resolve from "@rollup/plugin-node-resolve";
import babel from "@rollup/plugin-babel";

export default {
  input: "src/index.ts",
  output: [
    {
      file: "./dist/bundle.js",
    },
  ],
  plugins: [
    typescript(),
    resolve(),
    babel({
      babelHelpers: "bundled",
      extensions: [".js", ".ts"],
      targets: {
        chrome: "70", // target browser version
      },
    }),
  ],
  external: ["ramda"],
};

More from this blog

[ 살펴보기 ] TypeORM - Transactions, Migration

Transation Database 종류에 따라 detail한 부분은 차이점이 조금씩 있겠지만 각 sql statement는 개별적인 transaction block을 통해 실행되며 Database 설정에 따라 sql statement의 실행 결과가 자동으로 commit되어 영구히 적용되거나 commit을 직접 실행하기 전까지는 영구히 적용되지 않을 수 있다. 대부분의 경우 default로 sql statement 실행 결과가 자동으로 comm...

Feb 9, 20256 min read
[ 살펴보기 ] TypeORM - Transactions, Migration

Dev Diary

184 posts