알다시피, JS 런타임은 크게 브라우저와 Node.js가 있다.
그리고 각각 ESM, CJS의 모듈 방식이 있다.
요즘 개발 환경은 웹 개발을 할 때에도 node가 필요한 경우가 많기에, 라이브러리를 구성한다면 두 환경 모두에서 작동할 수 있도록 작성하는 것이 좋다.
이번에 개인적으로 라이브러리를 만져보면서 rollup을 사용하여 mjs, cjs를 생성하고 어떻게 설정했는지, 기록을 남기고자 했다.
✨ rollup.config.js 설정하기
import { defineConfig } from 'rollup';
import typescript from '@rollup/plugin-typescript';
export default defineConfig({
input: {
index: 'index.ts',
cli: 'src/cli.ts',
},
output: [
{
dir: 'dist',
format: 'cjs',
entryFileNames: '[name].cjs', // 또는 [name].[format].js 같은 방식으로 설정 가능
},
{
dir: 'dist',
format: 'es',
entryFileNames: '[name].mjs',
},
],
plugins: [
typescript({
declaration: true,
declarationDir: 'dist/types',
exclude: ['node_modules/**'],
}),
],
});
output에 배열로 두 가지 설정을 할 수 있다.
cjs와 es 파일을 둘 다 생성하는 옵션을 설정해준다.
package.json에 설정하기 🍇
{
"main": "dist/index.cjs",
"module": "dist/index.mjs",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs",
"types": "./dist/types/index.d.ts"
}
},
"types": "dist/types/index.d.ts",
}
이번 내용과 관련된 부분만 살펴보자면, main은 commonJS, module은 ESM 코드를 연결시켜 준다.
그리고 각각 import와 require에 코드가 대응될 수 있도록 exports에 import, require, types 설정을 해준다.
😌 main과 module 필드를 설정하더라도, 최신 Node.js와 모듈 번들러들이 exports 필드를 우선적으로 사용하게 되어, 이를 설정함으로써 더 나은 제어와 호환성을 제공할 수 있다.
exports는 작성하는 것이 좋다 !
- main과 module 필드가 전통적인 방식으로 중요한 역할을 하지만, exports 필드는 모듈 해석을 더 안전하고 명확하게 제어할 수 있게 해준다.
- exports 필드를 사용하면 TypeScript 타입 파일, 브라우저 환경과 Node.js 환경에 맞춘 파일, 특정 서브 모듈의 공개 여부 등을 더욱 정교하게 관리할 수 있다.
- 최신 Node.js 및 번들러 환경에서는 exports를 통해 모듈 구조를 명확히 정의함으로써, 패키지 사용자가 불필요한 내부 구현에 접근하지 못하게 하고, 모듈의 일관된 API를 제공한다.
위와 같이 설정을 통해서 하나의 코드에서 mjs, cjs 코드를 생성하고, 배포한 패키지가 import될 때 적절하게 types와 프로젝트에서 사용중인 모듈 시스템에 맞는 코드를 따라갈 수 있도록 할 수 있다 👍
👻 다만, exports에 import를 mjs로 설정해놔서 node.js에서 import로 모듈을 불러오면, 문제가 발생할 수 있다. (node에서는 require를 사용해야 한다)
- 실제 작성한 코드 전문은 아래 깃헙에서 확인할 수 있다.
https://github.com/citron03/colors-helper-tools/tree/1.7.9
'웹 개발' 카테고리의 다른 글
resize Event와 ResizeObserver 비교해보기 🙌 (0) | 2024.10.18 |
---|---|
requestIdleCallback 알아보기 (브라우저가 idle할 때, 콜백함수를 대기열에 👍) (0) | 2024.09.05 |
브라우저 탭 사이의 통신 (chrome postMessage, BroadcastChannel API 사용해보기) (3) | 2024.07.14 |
프론트엔드 개발 생태계에서 Rust 개발 툴들 (0) | 2024.07.02 |
Biome.js 사용 후기 (prettier + eslint) (0) | 2024.06.24 |