#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'
};