mpen
mpen

Reputation: 283053

Rollup TypeScript: declarations in dist + cjs + es

I'm trying to package a TypeScript library using rollup with declaration (d.ts) files, and I want to output both cjs and es versions.

So I came up with this rollup config:

const {nodeResolve} = require('@rollup/plugin-node-resolve')
const nodeExternals = require('rollup-plugin-node-externals');
const json = require('@rollup/plugin-json');
const commonjs = require('@rollup/plugin-commonjs');
const typescript = require('rollup-plugin-typescript2');
const packagePlugin = require('@mpen/rollup-plugin-package');
const cleanPlugin = require('@mpen/rollup-plugin-clean');
const findUp = require('find-up');
const {readFileSync} = require('fs');

module.exports = function rollupPresetTslib(opts = {}) {
    const tsconfigFile = findUp.sync(opts.tsconfig ?? 'tsconfig.json')
    const tsconfig = JSON.parse(readFileSync(tsconfigFile))

    return {
        input: tsconfig.files,
        plugins: [
            commonjs({
                include: 'node_modules/**',
            }),
            nodeExternals({
                builtins: true,
                deps: true,
                devDeps: false,
                peerDeps: true,
                optDeps: false,
            }),
            json(),
            typescript({
                abortOnError: process.env.NODE_ENV === 'production',
                tsconfig: tsconfigFile,
                ...opts.typescriptOptions,
            }),
            nodeResolve({
                extensions: ['.ts', '.json']
            }),
            packagePlugin(),
            cleanPlugin(),
            ...opts.plugins ?? [],
        ],
        watch: {
            buildDelay: 200,
            ...opts.watch,
        },
        preserveSymlinks: true,  // https://www.npmjs.com/package/@rollup/plugin-commonjs#usage-with-symlinks
        preserveModules: false,  // outputs multiple files
        output: {
            dir: 'dist',
            format: 'cjs',
            sourcemap: true,
            inlineDynamicImports: false,
        },
    }
}

This produces pretty good output but only compiles to cjs:

enter image description here

So I tried outputting to both formats by changing output like so:

        output: ['cjs', 'es'].map(format => ({
            dir: `dist/${format}`,
            format: format,
            sourcemap: true,
            inlineDynamicImports: false,
        })),

But now I get two copies of the .d.ts files which I don't want:

enter image description here

So how do I get one copy of the d.ts files plus a cjs and es build?

Upvotes: 2

Views: 2082

Answers (1)

hanorine
hanorine

Reputation: 7825

I have configured rollup to emit a single file to dist/index.d.ts, append the content of my declarations.d.ts to it using a postbuild script:

cat declarations.d.ts >> dist/index.d.ts

This is the content of my rollup.config.js:

import commonjs from '@rollup/plugin-commonjs';
import clear from 'rollup-plugin-clear';
import ts from 'rollup-plugin-ts';
import styles from 'rollup-plugin-styles';
import image from '@rollup/plugin-image';
import { builtinModules } from 'module';
import pkg from './package.json';

module.exports = {
  input: pkg.source,
  output: [
    { file: pkg.main, format: 'cjs', sourcemap: true },
    { file: pkg.module, format: 'esm', sourcemap: true }
  ],
  external: [
    ...builtinModules,
    ...(pkg.dependencies ? Object.keys(pkg.dependencies) : []),
    ...(pkg.devDependencies ? Object.keys(pkg.devDependencies) : []),
    ...(pkg.peerDependencies ? Object.keys(pkg.peerDependencies) : [])
  ],
  watch: {
    include: 'lib/**'
  },
  plugins: [
    clear({
      targets: ['dist'],
      watch: false
    }),
    ts({
      hook: {
        // Always rename declaration files to index.d.ts to avoid emitting two declaration files with identical contents
        outputPath: (path, kind) =>
          kind === 'declaration' ? './dist/index.d.ts' : path
      }
    }),
    image(),
    styles({
      modules: true,
      autoModules: /\.module\.\S+$/
    }),
    commonjs()
  ]
};

I hope this help anyone looking for a solution.

Upvotes: 1

Related Questions