[React] Rollup 를 이용해 npm 배포하기 - 1

이한형·2022년 10월 5일
0

Rollup

Rollup은 Webpack 같은 모듈 번들러입니다.
Rollup은 Webpack과 달리 코드들을 동일한 수준으로 호이스팅 한 후 번들링을 진행하기 때문에 속도가 빠르고 결과물이 가볍다는 장점이 있고 es 모듈 형태로 빌드를 할 수 있어 라이브러리나 패키지를 작업하는데 활용할 수 있습니다.

그렇다면 Rollup이 속도도 빠르고 결과물이 가벼운데 Webpack보다 좋은것이 아니냐라고 생각하실 수 있습니다.

Rollup이 성능면에서는 Webpack보다 좋을 수 있지만 안정성과, 개발서버가 다른 번들러보다 Webpack이 뛰어납니다.
라이브러리 작업에서는 Rollup을 사용하는게 성능면에서 이득을 볼 수 있다고 생각하시면 되겠습니다.

Rollup + React + Typescript 구축

우선 프로젝트를 생성하여 줍니다.

yarn init

그리고 필요한 모듈들을 설치해주겠습니다.

//react
yarn add -D react react-dom

// babel
yarn add -D @babel/core babel-preset-react-app

// styled-components 기반으로 작성할 예정이라 설치하였습니다.
yarn add -D babel-plugin-styled-components

// typescript
yarn add -D typescript

// rollup
yarn add -D rollup rollup-plugin-typescript2 @rollup/plugin-commonjs @rollup/plugin-node-resolve rollup-plugin-peer-deps-external @rollup/plugin-image

이렇게 필요한 모듈들을 모두 다운 받고 우선 package.json을 수정하도록 하겠습니다.
react, react-dom 모듈을 devDependencies에서 peerDependencies로 이동을 시키도록 하겠습니다.

package.json

"peerDependencies": {
	"react": 18.2.0,
    "react-dom": 18.2.0
}

그리고 package.json 상단에 빌드 된 후 위치할 경로들을 적어줍니다.

{
	...
    "main": "dist/index.js",
	"module": "dist/index.es.js",
	"types": "dist/types/index.d.ts"
    ...
}

그리고 script에 빌드를 해주는 명령어를 선언해주겠습니다.

{
	...
    "scripts": {
    	"build": "tsc --emitDeclarationOnly & rollup -c"
    },
    ...
}

그리고 babelrc.json 파일을 최상단 루트경로에 만들어주도록 합니다.

{
	"presets": [["react-app", { "flow": false, "typescript": true }]],
    "plugins": ["babel-plugin-styled-components"]
}

그리고 tsconfig.json 파일을 최상단 루트 경로에 만들어주도록 하겠습니다.

설정은 원하시는대로 커스텀 하시면 됩니다.

{
  "compilerOptions": {
    "declaration": true,
    "declarationDir": "./lib",
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "sourceMap": true,
    "rootDir": "packages/src",
    "outDir": "./dist",
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "react",
    "baseUrl": "./",
  },
  "include": ["**/*.tsx", "**/*.ts", "@types", "index.ts"],
  "exclude": ["node_modules", "build", "dist", "lib", "example",
    "rollup.config.js.js"
  ]
}

이제 마지막으로 최상단 루트경로에 rollup.config.js 파일을 만들어줍니다.

import peerDepsExternal from 'rollup-plugin-peer-deps-external';
import resolve from '@rollup/plugin-node-resolve';
import image from '@rollup/plugin-image';
import babel from '@rollup/plugin-commonjs';
import typescript from 'rollup-plugin-typescript2';
import commonjs from '@rollup/plugin-commonjs';

const packageJson = require('./package.json');
const extensions = ['js', 'jsx', 'ts', 'tsx'];
const external = ['react', 'react-dom', 'styled-components'];

process.env.BABEL_ENV = 'production';

export default {
    input: 'package/src/index.ts',
    output: [
        {
            file: packageJson.main,
            format: 'cjs',
            sourcemap: true
        },
        {
            file: packageJson.module,
            format: 'esm',
            sourcemap: true
        }
    ],
    plugins: [
        peerDepsExternal(),
        resolve({ extensions }),
        babel({
            extensions,
            include: ['packages/src/**/*'],
            exclude: /node_modules/,
            babelHelpers: 'runtime'
        }),
        commonjs({
            include: /node_modules/
        }),
        typescript({ useTsconfigDeclarationDir: true }),
        image()
    ],
    external
};

이제 간단한 컴포넌트를 하나 만들어서 번들링을 진행해보도록 하겠습니다.

package/src/Button/Button.tsx

import React, { FC } from 'react';
import ButtonProps from './Button.type


const Button: FC<ButtonProps> = ({ children, type }) => {
  return (
    <button type={type}>
    	{children}
	</button>
	)
}

export default Button

package/src/Button/Button.type.tsx

import React, { PropsWithChildren } from 'react';

export interface ButtonProps extends PropsWithChildren {
  type: string
}

package/src/Button/index.tsx

export { default as Button } from './Button/Button';

이제 npm run build를 하면 끝이 납니다!
다음 포스팅에는 npm에 라이브러리를 배포해보도록 하겠습니다~

profile
풀스택 개발자를 지향하는 개발자

0개의 댓글