React-bootstrap-typeahead: Rollup Build error on v3.3.5

Created on 23 Feb 2019  路  7Comments  路  Source: ericgio/react-bootstrap-typeahead

Version

3.3.5

Steps to reproduce

import Typeahead in a react component and run rollup -c

Expected Behavior

It should build without an error

Actual Behavior

Build fails with error below

[!] Error: 'Typeahead' is not exported by node_modules\react-bootstrap-typeahead\lib\index.js
https://github.com/rollup/rollup/wiki/Troubleshooting#name-is-not-exported-by-module
src\lib\input\TypeaheadInput.js (2:8)
1: import React from 'react';
2: import {Typeahead} from 'react-bootstrap-typeahead';
           ^
3: import 'react-bootstrap-typeahead/css/Typeahead.min.css';
4: import 'react-bootstrap-typeahead/css/Typeahead-bs4.min.css';

error Command failed with exit code 1.

bug need info needs repro

All 7 comments

I'm not familiar with rollup, but this seems like it could be an issue with your config. Did you check out the troubleshooting link in the error? I could be wrong, but I don't believe anything has changed in the package recently that would suddenly cause an error.

I think the issue introduced after 3.2.4. If I rollback to that, rollup works fine.

Yeah, I'm really not sure what could have changed to cause an error from 3.2.4 to 3.3.0. I don't have any experience with Rollup so I could use your help troubleshooting here. From the troubleshooting link in the error:

This error frequently occurs with CommonJS modules converted by rollup-plugin-commonjs, which makes a reasonable attempt to generate named exports from the CommonJS code but won't always succeed, because the freewheeling nature of CommonJS is at odds with the rigorous approach we benefit from in JavaScript modules. It can be solved by using the namedExports option, which allows you to manually fill in the information gaps.

Are you using rollup-plugin-commonjs and did you try modifying the namedExports option?

No response from OP, closing for now. @SerdarSanri happy to try and help some more if you can provide more info and help me debug.

I'm having the same issue when I bundle for prod. It seems to be getting stuck with any exports that are not the Typeahead component. Mine is breaking at the Menu import.

Error: 'Menu' is not exported by node_modules/react-bootstrap-typeahead/lib/index.js
https://rollupjs.org/guide/en/#error-name-is-not-exported-by-module

Rolled back to 3.2.4 as @SerdarSanri suggested and it worked.

We've got a lot going on but here is my rollup config. Using commonjs and named exports, maybe if I name Menu, Highlighter, etc.

import fs from 'fs';
import path from 'path';
import Glob from 'glob';

import resolve from 'rollup-plugin-node-resolve';
import babel from 'rollup-plugin-babel';
import { terser } from 'rollup-plugin-terser';
import postcss from 'rollup-plugin-postcss';
import url from 'rollup-plugin-url';
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
import svgr from '@svgr/rollup';
import commonjs from 'rollup-plugin-commonjs';
import json from 'rollup-plugin-json';
import replace from 'rollup-plugin-replace';

import simplevars from 'postcss-simple-vars';
import nested from 'postcss-nested';
import cssnext from 'postcss-cssnext';
import autoprefixer from 'autoprefixer';

const isProduction = process.env.NODE_ENV !== 'development';

const PACKAGE_FORMATS = ['cjs', 'esm', 'system', 'iife'];

const DEST_ROOT = './dist';

const outputOptions = PACKAGE_FORMATS.map(format => ({
  format,
  sourcemap: 'inline',
}));

const ucFirst = str => str.substr(0, 1).toUpperCase() + str.substr(1);

///----------- GATHER PACKAGES
const readPackage = pkg => ({ pkg, ...JSON.parse(fs.readFileSync(pkg)) });

const packages = Glob.sync('./src/components/*/package.json', {
  ignore: './src/components/Styles/*'
}).map(readPackage);

const globals = {
  'prop-types': 'PropTypes',
  PropTypes: 'PropTypes',
  react: 'React',
  'react-dom': 'ReactDOM',
};

const externals = ['prop-types', 'react', 'react-dom'];

///----------- BUILD CONFIGS
const normalizeEntryFile = entry => {
  let dir = path.dirname(entry);
  let file = path.basename(entry);

  let search = `${dir}/${file}`;

  const REGEX_FORMAT = /\.(cjs|esm|system|iife)\.js$/;

  if (fs.existsSync(search)) {
    return search;
  }

  if (REGEX_FORMAT.test(file)) {
    file = file.replace(REGEX_FORMAT, '.js');
    search = `${dir}/${file}`;

    if (fs.existsSync(search)) {
      return search;
    }
  }

  file = ucFirst(path.basename(entry)); // reset `file`
  search = `${dir}/${file}`;

  if (fs.existsSync(search)) {
    return search;
  }

  if (REGEX_FORMAT.test(file)) {
    file = file.replace(REGEX_FORMAT, '.js');
    search = `${dir}/${file}`;

    if (fs.existsSync(search)) {
      return search;
    }
  }

  console.error(`Could not find entry file for ${entry}.`);
  return entry;
};

const plugins =  [
  replace({
    'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')
  }),
  resolve(),
  svgr(),
  json(),
  url(),
  postcss({
    extract: true,
    plugins: [
      simplevars(),
      nested(),
      autoprefixer(),
      cssnext({ warnForDuplicates: false }),
    ],
  }),
  babel({
    presets: ['@babel/preset-react'],
    plugins: [
      '@babel/plugin-proposal-object-rest-spread',
      '@babel/plugin-proposal-optional-chaining',
      '@babel/plugin-syntax-dynamic-import',
      '@babel/plugin-proposal-class-properties',
    ],
    exclude: 'node_modules/**',
  }),
  peerDepsExternal({
    includeDependencies: true,
  }),
  commonjs(),
  isProduction && terser(),
];

const makeConfig = ({ pkg, name, main, pkgTitle }) => {
  const input = normalizeEntryFile(`${path.dirname(pkg)}/${main}`);

  const output = outputOptions.map(({ format, ...option }) => {
    let outputName = main
      .substr(main.lastIndexOf('/') + 1)
      .replace(/(\.cjs|\.esm|\.system|\.iife)?\.js$/, '');
    const dir = name.replace('@prism/', '');

    if (dir === 'library') {
      outputName = 'index';
    }

    const returnObj = {
      ...option,
      globals,
      format,
      name: outputName,
      exports: 'named',
      sourcemap: isProduction ? true : 'inline',
      file: `${DEST_ROOT}/${dir}/${outputName}.${format}${isProduction ? '.min' : ''}.js`,
    };

    if (isProduction) {
      returnObj.sourcemapFile = `${DEST_ROOT}/${dir}/${outputName}.${format}.min.js.map`
    }

    if (format === 'iife') {
      returnObj.name = pkgTitle ? pkgTitle : ucFirst(outputName);
    }

    return returnObj;
  });

  return {
    input,
    output,
    external: [...externals],
    plugins: [...plugins],
  };
};
console.log('!!', path.resolve(__dirname, '../'));
///----------- ROLL IT UP
export default packages.map(makeConfig);

@devjefe: Did you try the namedExports option as described in the error description? It should look something like:

commonjs({
  namedExports: {
    'react-bootstrap-typeahead': [ 'Typeahead', 'Menu', ... ]
  }
});

@ericgio I tried that and it results in
Uncaught TypeError: Cannot assign to read only property 'exports' of object '#<Object>'. No idea if I did that correctly though

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ashanjayasundara picture ashanjayasundara  路  4Comments

hslojewski picture hslojewski  路  3Comments

damonmiller picture damonmiller  路  3Comments

orekav picture orekav  路  5Comments

DaveyEdwards picture DaveyEdwards  路  5Comments