Mark James
Mark James

Reputation: 558

React Rollup: 'name' is not exported by node_modules/

I am trying to make a library/package from my component.

Tech-stack is: React, Typescript... and a bunch of other dependencies.

I am using Rollup and when I try to build the package I get the following error:

[!] Error: 'DisplayHint' is not exported by ../node_modules/@bestowinc/enroll-sdk-core/build/lib/question-common.js, imported by ../src/utils/answerTypeConversions.ts https://rollupjs.org/guide/en/#error-name-is-not-exported-by-module

Rollup:

import babel from 'rollup-plugin-babel';
import resolve from '@rollup/plugin-node-resolve';
import external from 'rollup-plugin-peer-deps-external';
import { terser } from 'rollup-plugin-terser';
import postcss from 'rollup-plugin-postcss';
import reactSvg from 'rollup-plugin-react-svg';
import typescript from 'rollup-plugin-typescript2';
import svg from 'rollup-plugin-svg';
import commonjs from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import replace from '@rollup/plugin-replace';
import urlResolve from 'rollup-plugin-url-resolve';

export default [
  {
    input: './src/index.ts',
    output: [
      {
        file: './dist/index.js',
        format: 'cjs',
        sourcemap: true,
      },
      {
        file: './dist/index.es.ts',
        format: 'es',
        exports: 'named',
        sourcemap: true,
      },
    ],
    plugins: [
      typescript({
        tsconfig: './tsconfig.build.json',
        verbosity: 3,
        clean: true,
        check: true,
      }),
      babel({
        exclude: ['/node_modules'],
        presets: [
          '@babel/preset-react',
          '@babel/preset-flow',
          '@babel/preset-env',
        ],
        extensions: ['.ts', '.tsx'],
      }),
      commonjs({
        include: './node_modules',
        dynamicRequireTargets: [
          // include using a glob pattern (either a string or an array of strings)
          '/node_modules/@bestowinc/enroll-sdk-core/build/lib/question-common.js',
          './node_modules/@bestowinc/enroll-sdk-core/build/lib/question-common.js',
        ],
      }),
      resolve({
        browser: true,
        preferBuiltins: true,
        mainFields: ['browser'],
      }),
      urlResolve(),
      postcss({
        plugins: [],
        minimize: true,
      }),
      external(),
      terser(),
      reactSvg({
        jsx: false,
        include: ['custom.d.ts'],
        exclude: null,
      }),
      svg(),
      replace({
        include: ['../src/icons/**'],
        preventAssignment: true,
        // Replace ReactComponent to allow resolution of SVG files under Rollup
        ReactComponent: 'default',
      }),
      json(),
    ],
  },
];

DisplayHint:

/**
 * An indication of how clients should display a question.
 *
 * This is inferred from the answer_format and answer_display api properties.
 * Those properties should not be used directly, and clients should rely instead
 * solely on DisplayHint.
 */
export declare const DisplayHint: {
    readonly ButtonGroup: "DisplayHint::ButtonGroup";
    readonly Checkbox: "DisplayHint::Checkbox";
};
export declare type DisplayHint = typeof DisplayHint[keyof typeof DisplayHint];

Upvotes: 9

Views: 12225

Answers (2)

ragauskl
ragauskl

Reputation: 41

I've had similar issue just happening with linked library (with typescript plugin in place), in my case solution was to add the linked library to config 'external' property. But node_modules should be treated as external anyway so not sure if this will apply

Upvotes: 4

hackape
hackape

Reputation: 19947

Looks like DisplayHint is a TS type/interface, not an exported JS value.

Rollup per se is a bundler not a TS language analyzer. It cannot tell if a named export is a concrete JS value or merely a non-existing TS type, thus the reported error.

Rollup plugin order matters. To resolve this specific problem, just lift the typescript plugin up in order, at least before babel. TS plugin, if put to work first, will correctly erase TS type from JS code output.


Update

I know another trick, but it’s a workaround-ish one. The trick is to use import type syntax to explicitly mark DisplayHint as a TS type.

import type { DisplayHint } from "@bestowinc/enroll-sdk-core"
import { otherNonTypeStuff } from "@bestowinc/enroll-sdk-core"

This trick is not satisfying because it requires you to explicitly mark everywhere you need a TS type, and you have to separate concrete JS exports from TS type ones, like shown above. This is fine if it’s a one-off thing but if you have a large codebase it’s very tedious.

I have to add, it’s unexpected to me that original solution doesn’t work. My guess is that this module @bestowinc/enroll-sdk-core is somehow quirky. (Why you include them as dynamic import target in the config anyway?)

It’s a JS module with .d.ts annotation, that I can tell, but looks like it’s a private module, I cannot see the code thus cannot dive deeper. My guess is that .d.ts declaration is broken, it doesn’t match up to the real export of JS code.

Anyway, I hope this trick resolve your problem. If you need me to look closer, I’ll have to ask you to setup a minimal reproducible example. With current info there’s not much I can do.

Upvotes: 6

Related Questions