Igor Bykov
Igor Bykov

Reputation: 2822

How to avoid code duplication between entry points in Rollup?

I want to configure rollup to take a bunch of files on input & produce a bunch of files in dist that share some common code between them.

Here's the rollup config I use:

import path from 'path';
import pathsTransformer from 'ts-transform-paths';
import alias from '@rollup/plugin-alias';
import commonjs from '@rollup/plugin-commonjs';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import typescript from 'rollup-plugin-typescript2';
import peerDepsExternal from 'rollup-plugin-peer-deps-external';

const plugins = [
  peerDepsExternal(),
  alias({
    entries: [
      { find: '@', replacement: path.join(__dirname, '/src') },
      { find: '$root', replacement: __dirname },
    ],
  }),
  nodeResolve(),
  typescript({
    transformers: [() => pathsTransformer()],
  }),
  commonjs({
    extensions: ['.js', '.ts'],
  }),
];

export default [
  {
    input: './src/a.ts',
    output: {
      file: 'dist/a.js',
      format: 'esm',
      sourcemap: true,
    },
    plugins,
  },
  {
    input: './src/b.ts',
    output: {
      file: 'dist/b.js',
      format: 'esm',
      sourcemap: true,
    },
    plugins,
  },
];

The problem with this set-up is that if a.ts & b.ts both depend on some code, this common code gets bundled into each output file unnecessarily increasing the bundle size.

Since the output.format is esm (so, imports are available in the output), I'd rather expect rollup to split the shared code between the 2 files in a separate chunk & then make both files import that common code (which seems to be the thing rollup does by default anyway).

I assume the problem to be somewhere around nodeResolve or commonjs calls, but, I want my dependencies to be bundled. I just don't want to have them duplicated.

How do I optimize my output? Here's a reproduction to visualize it (dist included).

Upvotes: 4

Views: 2014

Answers (1)

Igor Bykov
Igor Bykov

Reputation: 2822

By returning an array of objects, you specify to rollup that you want to have independent bundles. If you just want to produce multiple files (which was exactly my case) you can just specify input as an object.

import path from 'path';
import pathsTransformer from 'ts-transform-paths';
import alias from '@rollup/plugin-alias';
import commonjs from '@rollup/plugin-commonjs';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import typescript from 'rollup-plugin-typescript2';
import peerDepsExternal from 'rollup-plugin-peer-deps-external';

const plugins = [
  peerDepsExternal(),
  alias({
    entries: [
      { find: '@', replacement: path.join(__dirname, '/src') },
      { find: '$root', replacement: __dirname },
    ],
  }),
  nodeResolve(),
  typescript({
    transformers: [() => pathsTransformer()],
  }),
  commonjs({
    extensions: ['.js', '.ts'],
  }),
];

export default   {
  input: {
    a: './src/a.ts',
    b: './src/b.ts',
  },
  output: {
    dir: 'dist',
    format: 'esm',
    sourcemap: true,
  },
  plugins,
};

Upvotes: 7

Related Questions