ionicons
ionicons copied to clipboard
Cannot import anything from IonIcons in Storybook
Originally I encountered the error while trying to render components from @ionic/react
in Storybook, but I was able to narrow it down to ionicons
and so I post the issue in this repo.
TLDR;
If you try to import anything from @ionic/react
in a Storybook story, you get this error:
Here is a minimal example: https://github.com/anatoliyarkhipov/ionic-react-in-storybook
Details
Object(...) is not a function
seems a little bit obscure, but it actually this line in the bundle:
Object(ionicons__WEBPACK_IMPORTED_MODULE_0__["addIcons"])(ionicons_icons__WEBPACK_IMPORTED_MODULE_1__["ICON_PATHS"]);
And this is the original line in the @ionic/react
sources:
addIcons(ICON_PATHS);
Webpack wraps every direct call of an imported symbol with Object()
and there is nothing wrong with it. The problem is that ionicons__WEBPACK_IMPORTED_MODULE_0__["addIcons"]
is undefined
and so Object(undefined)
returns an empty object which is "not a function".
And that problem appears only for the addIcons
- other symbols are imported correctly and aren't undefined
:
I also tried to remove everything from from .storybook/config.js
, import the function directly and console.log
it, and it again was undefined
:
// .storybook/config.js
import { addIcons } from "ionicons"
console.log(addIcons)
Then I rewrote the import to const ionicons = require("ionicons")
and run config.js
directly via node config.js
and ionicons
was an empty object.
// .storybook/config.js
const ionicons = require("ionicons")
console.log(ionicons)
At the same time, I have no problems when I use it in create-reactp-app
! I set up the project following guide in this announcement and everything is fine: if I import { addIcons } from "ionicons"
it's a normal function. I tried to figure out what's so special in the CRA's Webpack config, but had no success due to its complexity.
And here we are 😀.
I'm using storybook/html with stenciljs and the ionic framework. I had similar issues. Check out adding a custom head tag:
https://storybook.js.org/docs/configurations/add-custom-head-tags/
In my case I added:
<link href="https://unpkg.com/@ionic/[email protected]/css/ionic.bundle.css" rel="stylesheet" />
<script src="https://unpkg.com/@ionic/[email protected]/dist/ionic.js"></script>
<link href="https://unpkg.com/[email protected]/dist/css/ionicons.min.css" rel="stylesheet" />
I didn't have to do anything special to the config.js
or a custom webpack.config.js
rule. I haven't worked with React in some time so I may be a bit off here. You also might want to use the latest version of Storybook. I've had much better success with v5. Hope this helps a bit.
@tm-3 thanks! I also added the js script for the icons (I import ionic as module in the story itself for the missing js)
<link href="https://unpkg.com/@ionic/[email protected]/css/ionic.bundle.css" rel="stylesheet" />
<link href="https://unpkg.com/[email protected]/dist/css/ionicons.min.css" rel="stylesheet" />
<script src="https://unpkg.com/[email protected]/dist/ionicons.js"></script>
Local dependencies could be copied over to the dist via the webpack copy plugin. This is how I loaded my local ionicons dependency;
.storybook/main.js
const CopyPlugin = require('copy-webpack-plugin');
module.exports = {
stories: ['../src/**/*.stories.ts'],
webpackFinal: config => {
config.plugins.push(
new CopyPlugin({
patterns: [{ from: './node_modules/ionicons/dist/ionicons', to: './ionicons/' }],
})
);
return config;
},
};
.storybook/preview-head.html
<script async type="module" src="/ionicons/ionicons.esm.js"></script>
Thanks @onderceylan - this pointed me downt he right path. What I needed to do was copy the svg folder:
// main.ts
import * as CopyPlugin from 'copy-webpack-plugin';
export const stories = [
'../**/*.stories.mdx',
'../**/*.stories.@(js|jsx|ts|tsx)',
];
export const addons = ['@storybook/addon-essentials', '@storybook/addon-a11y'];
export const webpackFinal = (config) => {
config.plugins.push(
new CopyPlugin({
patterns: [
{ from: './node_modules/ionicons/dist/ionicons/svg', to: './svg/' },
],
})
);
return config;
};
@corysmc Massive thanks for posting your solution. It worked for me.
This was my final config
import type { StorybookConfig } from '@storybook/angular';
import CopyPlugin from 'copy-webpack-plugin';
const config: StorybookConfig = {
stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'],
staticDirs: ['../src/assets'],
framework: {
name: '@storybook/angular',
options: {},
},
webpackFinal: (config) => {
config.plugins?.push(
new CopyPlugin({
patterns: [
{ from: './node_modules/ionicons/dist/ionicons/svg', to: './svg/' },
],
}),
);
return config;
},
};
export default config;
// To customize your webpack configuration you can use the webpackFinal field.
// Check https://storybook.js.org/docs/react/builders/webpack#extending-storybooks-webpack-config
// and https://nx.dev/recipes/storybook/custom-builder-configs