How to include external dependencies in UMD bundle with rollup
Asked Answered
H

2

11

I'm using rollup to bundle a library and I want to include external dependencies together with my code in the UMD bundle. I can't find any useful information about this in the docs. It could be that I'm missing something obvious but it seems like the docs only demonstrates how to mark relative modules as external. I've been trying to achieve this without any success. Is it doable and if yes, how?

My code making use of an external component: src/index.ts

import { ExternalComponent } from 'external-component'

function MyComponent() {
  const externalComponent = ExternalComponent()
  // ...
}

export default MyComponent

Desired output: bundle.umd.js

function ExternalComponent() {
 // ...
}

function MyComponent() {
  const externalComponent = ExternalComponent()
  // ...
}

rollup.config.js

import babel from '@rollup/plugin-babel'
import typescript from 'rollup-plugin-typescript2'
import resolve from '@rollup/plugin-node-resolve'
import { terser } from 'rollup-plugin-terser'
import localTypescript from 'typescript'

const CONFIG_BABEL = {
  extensions: ['.js', '.jsx', '.ts', '.tsx'],
  exclude: 'node_modules/**',
  babelHelpers: 'bundled',
}

const CONFIG_TYPESCRIPT = {
  tsconfig: 'tsconfig.json',
  typescript: localTypescript,
}

const kebabCaseToPascalCase = (string = '') => {
  return string.replace(/(^\w|-\w)/g, (replaceString) =>
    replaceString.replace(/-/, '').toUpperCase(),
  )
}

export default [
  {
    input: 'src/index.ts',
    output: [
      {
        file: `${packageJson.name}.umd.js`,
        format: 'umd',
        strict: true,
        sourcemap: false,
        name: kebabCaseToPascalCase(packageJson.name),
        plugins: [terser()],
      }
    ],
    plugins: [resolve(), typescript(CONFIG_TYPESCRIPT), babel(CONFIG_BABEL)],
  },
]

package.json

{
  "types": "index.d.ts",
  "scripts": {
    "build": "rollup -c",
    "start": "rollup -c --watch",
  },
  "devDependencies": {
    "@babel/core": "7.17.0",
    "@rollup/plugin-babel": "^5.3.0",
    "@rollup/plugin-node-resolve": "13.1.3",
    "husky": "^4.3.8",
    "npm-run-all": "^4.1.5",
    "prettier": "2.5.1",
    "rollup": "^2.67.0",
    "rollup-plugin-terser": "^7.0.2",
    "rollup-plugin-typescript2": "^0.31.2",
    "typescript": "^4.5.5"
  },
}

Thanks in advance,
David

Harridan answered 15/6, 2022 at 7:35 Comment(4)
Were you able to implement this?Unfurl
Unfortunately no @NickMcB. I haven't found any useful information on the web about how to achieve this. Upvoting this question might help if you would like to know how to achieve this with rollup too.Harridan
Any updates here? 🤓Polygamy
also stuck hehehBhakti
A
0

I find something from the rollup documentation:

If you do want to include the module in your bundle, you need to tell Rollup how to find it. In most cases, this is a question of using @rollup/plugin-node-resolve.

But the @rollup/plugin-node-resolve doc does not help.

Alessi answered 21/10, 2022 at 20:48 Comment(1)
Thank you for looking into this. Yes I read that too but if it’s possible to achieve this with @rollup/plugin-node-resolve they should link directly to the relevant section in the plugin documentation. If the plugin documentation doesn’t show how to achieve this, the rollup documentation should either show it in their documentation or remove the part that says that this is possible to do.Harridan
W
0

You'll want to use external with output.globals

For example:

import packageJson from './package.json';

const peers = Object.keys(packageJson.peerDependencies);

export default [
  {
    input: 'src/index.ts',
    external: id => peers.some(dep => dep === id || id.startsWith(dep)),
    output: [
      {
        file: `${packageJson.name}.umd.js`,
        format: 'umd',
        strict: true,
        sourcemap: false,
        name: kebabCaseToPascalCase(packageJson.name),
        plugins: [terser()],
        globals: {
          react: 'React',
        },
      },
    ],
  }
]

globals maps the package name to the variable name in the global scope. In this case, the 'react' package uses upper-first, so we map react to 'React' to make that dependency work

Winkler answered 19/9, 2023 at 5:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.