Понимание экспорта накопительной внешней библиотеки — сторонняя библиотека не входит в комплект

#reactjs #formik #rollupjs

#reactjs #formik #rollupjs

Вопрос:

В настоящее время я разрабатываю проект общей библиотеки, в котором используется Formik.

С точки зрения структуры каталогов. Представьте это.

 MyProject
MySharedLibrary
 

MySharedLibrary использует Formik для создания компонентов формы.

 MySharedLibrary
   Forms
     FormComponent > FormComponent.js
   index.js
 

Index.js выглядит примерно так:

 import FormComponent from './FormComponent/FormComponent';
export { FormComponent };
 

Ошибка, которую я получаю, заключается в следующем: я не уверен, является ли это отвлекающим маневром или нет..

 VM608:37 Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
 

У меня такое чувство, что он выдает эту ошибку, потому что он не может выполнить часть магии formik, а не что-то связанное с тем, как импортируется компонент (к чему обычно относится эта ошибка).

Эта библиотека компилируется с помощью свертки. Вот как выглядит конфигурация накопительного пакета

 import babel from '@rollup/plugin-babel';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import postcss from 'rollup-plugin-postcss';
import filesize from 'rollup-plugin-filesize';
import precss from 'precss';
import autoprefixer from 'autoprefixer';
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
import localResolve from 'rollup-plugin-local-resolve';
import externals from 'rollup-plugin-node-externals';
import builtins from 'rollup-plugin-node-builtins';
import globals from 'rollup-plugin-node-globals';
import image from 'rollup-plugin-inline-image';
import { terser } from 'rollup-plugin-terser';

import pkg from './package.json';

const INPUT_FILE_PATH = 'src/index.js';
const OUTPUT_NAME = 'Example';

const ENVIRONMENT = process.env;
const PRODUCTION = ENVIRONMENT.production || ENVIRONMENT.production === 'true';

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

const PLUGINS = ({ cssPlugin }) => {
  return [
    globals(),
    PRODUCTION amp;amp; builtins(),
    PRODUCTION amp;amp; externals(),
    babel({
      babelHelpers: 'runtime',
      exclude: 'node_modules/**',
      presets: ['@babel/env', '@babel/preset-react'],
    }),
    commonjs({
      include: 'node_modules/**',
    }),
    PRODUCTION amp;amp; peerDepsExternal(),
    postcss({ extract: cssPlugin, plugins: [autoprefixer, precss] }),
    PRODUCTION amp;amp; json({ include: 'node_modules/**' }),
    PRODUCTION amp;amp; localResolve(),
    resolve({
      browser: true,
      resolveOnly: [/^(?!react$)/, /^(?!react-dom$)/, /^(?!prop-types)/],
    }),
    PRODUCTION amp;amp; filesize(),
    image(),
    PRODUCTION amp;amp; terser(),
  ];
};

// If using any imports of 3rd party depencies folders, need to be added here
const EXTERNAL = [
  ...Object.keys(pkg.peerDependencies || {}),
  ...Object.keys(pkg.dependencies || {}),
];

// https://github.com/rollup/plugins/tree/master/packages/babel#babelhelpers
const CJS_AND_ES_EXTERNALS = EXTERNAL.concat(/@babel/runtime/);

// Use directory to define index file, instead of the build folder defined in the package.json
const OUTPUT_DATA = (dir) => {
  const umd = {
    file: dir ? `/index.js` : pkg.browser,
    format: 'umd',
  };
  const cjs = {
    file: dir ? `/index.cjs.js` : pkg.main,
    format: 'cjs',
  };
  const es = {
    file: dir ? `/index.esm.js` : pkg.module,
    format: 'es',
  };

  if (PRODUCTION) return [{ ...umd }, { ...cjs }, { ...es }];
  return [{ ...umd }];
};

const WATCH = {
  chokidar: {
    usePolling: true,
    paths: 'src/**',
  },
};

/* 
  @input: references the directory that the index file to build resides
  @output: 
    - references the directory where the build folder name will output to 
      -(do not prepend with a `/` will cause to build in wrong location)
    - will need to the build folder into package.json files array property i.e "form"
    - will also need to add build folder to .gitignore file i.e `/form`
    - will also need to add build folder to .eslintignore file i.e `/form`
    - optional, you can also hide in the build folder from the workspace view
      - by going to `.vscode/settings.json`
      - under the `files.exlcude` property you can add the following to only target the root directory folder not all folders by said name
        - i.e "form": true,
  @cssPlugin: if there are css files within the @input directory, set to true, otherwise set to false
*/
const OUTPUT_FILES = [
  {
    input: INPUT_FILE_PATH,
    output: '',
    cssPlugin: true,
  },
  {
    input: 'src/form/index.js',
    output: 'form',
    cssPlugin: false,
  },
  {
    input: 'src/buttons/index.js',
    output: 'buttons',
    cssPlugin: false,
  },
];

// Concat array of arrays into single array of all output folders and output files for config
const arr = [];
const config = arr.concat.apply(
  [],
  OUTPUT_FILES.map(({ input, output, cssPlugin }) =>
    OUTPUT_DATA(output).map(({ file, format }) => ({
      input,
      output: {
        file: `${output}${file}`,
        format,
        name: OUTPUT_NAME,
        globals: GLOBALS,
      },
      watch: WATCH,
      external: ['cjs', 'es'].includes(format) ? CJS_AND_ES_EXTERNALS : EXTERNAL,
      plugins: PLUGINS(cssPlugin),
    }))
  )
);

export default config;
 

Это позволяет разделить код таким образом, чтобы

 import { FormComponent } from "@project/project-ui/form";
 

позволяет импортировать из общей библиотеки для работы в MyProject.

теперь мой вопрос в том, как мне гарантировать, что Formik, который является зависимостью внутри FormComponent , будет экспортироваться вместе с пакетом библиотеки, чтобы он не требовался в MyProject в качестве дополнительной зависимости в package.json?Этот раздел в накопительном пакете, по-видимому, использует (и экспортирует?) зависимости внутри package.json — из которых Formik уже указан в пакете для MySharedLibrary. Так что я не уверен на 100%, чего мне не хватает в накопительном пакете.

 const EXTERNAL = [
      ...Object.keys(pkg.peerDependencies || {}),
      ...Object.keys(pkg.dependencies || {}),
    ];
 

package.json внутри MySharedLibrary:

 "peerDependencies": {
    ....
    "formik": "^2.2.5"
  },

  "dependencies": {

    "formik": "^2.2.5",
  }
}
 

Вещи, которые я пробовал, которые не сработали ниже. Любая помощь приветствуется, не уверен, что делать дальше.

 const EXTERNAL = [
      ...Object.keys(pkg.peerDependencies || {}),
      ...Object.keys(pkg.dependencies || {}),
      'formik'
];

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