How to create umd bundle with fetch polyfill, rollup and typescript?

Viewed 1105

I'm trying to bundle a library with rollup.

In this library i'm making http requests. I would like to use fetch and have a polyfill be used when the code is run on node. I can not get the configuration right. Either it works on node but not in the browser, or the opposite.

This is how my config file looks like:

 module.exports = [{
    input: 'src/mylibrary.ts',
    output: {
      name: LIB_NAME,
      file: getOutputFileName(
        resolve(ROOT, pkg.browser),
        env === 'production'
      ),
      format: 'umd',
      globals: {
        fetch: 'cross-fetch',
      },
    },
    plugins: [
     typescript({
      useTsconfigDeclarationDir: true,
      tsconfigOverride: {
        allowJs: false,
        includes: ['src'],
        exclude: ['tests', 'examples', '*.js', 'scripts'],
        esModuleInterop: true,
      },
     }),
      nodeResolve({
        mainFields: ['jsnext', 'main'],
        preferBuiltins: true,
        browser: true,
      }),
      commonjs({
        include: ['node_modules/**'],
      }),
      json(),
      env === 'production' ? terser() : {}, // will minify the file in production mode
    ],
  }]

This is the how I import fetch in my code :

import 'cross-fetch/polyfill'

In browser it works great ✅

In node I have the following error ❌:

  throw new Error('unable to locate global object');
        ^

Error: unable to locate global object

When I look into the bundled umd it comes from here:

var getGlobal = function () {
        // the only reliable means to get the global object is
        // `Function('return this')()`
        // However, this causes CSP violations in Chrome apps.
        if (typeof self !== 'undefined') { return self; }
        if (typeof window !== 'undefined') { return window; }
        if (typeof global !== 'undefined') { return global; }
        throw new Error('unable to locate global object');
    };

Any idea what might be the problem ?

1 Answers

I forgot to add cross-fetch in the external key (line 2)

The following example works for me:

 {
    input: 'src/meilisearch.ts', // directory to transpilation of typescript
    external: ['cross-fetch', 'cross-fetch/polyfill'],
    output: {
      name: LIB_NAME,
      file: getOutputFileName(
        // will add .min. in filename if in production env
        resolve(ROOT, pkg.browser),
        env === 'production'
      ),
      format: 'umd',
      sourcemap: env === 'production', // create sourcemap for error reporting in production mode
    },
    plugins: [
     typescript({
      useTsconfigDeclarationDir: true,
       tsconfigOverride: {
        allowJs: false,
        includes: ['src'],
        exclude: ['tests', 'examples', '*.js', 'scripts'],
        esModuleInterop: true,
       },
      }),
      babel({
        babelrc: false,
        extensions: ['.ts'],
        presets: [
          [
            '@babel/preset-env',
            {
              modules: false,
              targets: {
                browsers: ['last 2 versions', 'ie >= 11'],
              },
            },
          ],
        ],
      }),
      nodeResolve({
        mainFields: ['jsnext', 'main'],
        preferBuiltins: true,
        browser: true,
      }),
      commonjs({
        include: ['node_modules/**'],
      }),
      json(),
      env === 'production' ? terser() : {}, // will minify the file in production mode
    ],
  },
Related