Closed elie222 closed 5 years ago
I have tried to update the Storybook webpack.config.js
file in lots of different ways, but have not had any luck getting it working.
I have tried both the Storybook v4 and v5 notes in the Gatsby readme.
Attempt with Gatsby Storybook v5 instructions:
const path = require("path");
module.exports = ({ config }) => {
// Transpile Gatsby module because Gatsby includes un-transpiled ES6 code.
config.module.rules[0].exclude = [/node_modules\/(?!(gatsby)\/)/]
// use installed babel-loader which is v8.0-beta (which is meant to work with @babel/core@7)
config.module.rules[0].use[0].loader = require.resolve("babel-loader")
// use @babel/preset-react for JSX and env (instead of staged presets)
config.module.rules[0].use[0].options.presets = [
require.resolve("@babel/preset-react"),
require.resolve("@babel/preset-env"),
]
// use @babel/plugin-proposal-class-properties for class arrow functions
config.module.rules[0].use[0].options.plugins = [
require.resolve("@babel/plugin-proposal-class-properties"),
]
// Prefer Gatsby ES6 entrypoint (module) over commonjs (main) entrypoint
config.resolve.mainFields = ["browser", "module", "main"]
// Add typescript loader
config.module.rules.push({
test: /\.(ts|tsx)$/,
include: path.resolve(__dirname, "../src"),
loader: require.resolve("ts-loader"),
options: {
configFile: ".storybook/tsconfig.json"
}
});
config.resolve.extensions.push(".ts", ".tsx");
// Add markdown loader
config.module.rules.push({
test: /\.md$/,
include: path.resolve(__dirname, "../src"),
loader: require.resolve("raw-loader")
});
config.resolve.extensions.push(".md");
// Add svg loader
// modify storybook's file-loader rule to avoid conflicts with svgr
const fileLoaderRule = config.module.rules.find(rule => rule.test.test('.svg'));
fileLoaderRule.exclude = path.resolve(__dirname, "../src");
config.module.rules.push({
test: /\.svg$/,
include: path.resolve(__dirname, "../src"),
use: [{
loader: '@svgr/webpack',
options: {
icon: true,
},
}],
});
return config
}
@elie222 i've picked up on your issue and based on the information you supplied i have circunvented that issue and i'm able to get build with storybook and gatsby. I'm going to break down my answer into smaller parts for better understanding:
gatsby-config.js
without any options, to keep it simple.@svgr/cli
package aswell to cover my basis..config.js
inside .storybook
folder as per Gatsby documentation here for v5.
Originating the following:
import { configure } from '@storybook/react';
// automatically import all files ending in *.stories.js const req = require.context('../src', true, /.stories.js$/); function loadStories() { req.keys().forEach(filename => req(filename)); } // Gatsby's Link overrides: // Gatsby defines a global called loader to prevent its method calls from creating console errors you override it here global.loader = { enqueue: () => {}, hovering: () => {}, } // Gatsby internal mocking to prevent unnecessary errors in storybook testing environment global.PATH_PREFIX_ = "" // This is to utilized to override the window.navigate method Gatsby defines and uses to report what path a Link would be taking us to if it wasn't inside a storybook window.___navigate = pathname => { action("NavigateTo:")(pathname) }
configure(loadStories, module);
- Created a `webpack.config.js` inside `.storybook` folder and added the Gatsby configuration used for v5 mentioned in [here](https://www.gatsbyjs.org/docs/visual-testing-with-storybook/) and as Gatsby uses babel under the hood and you're using typescript i added also the configuration mentioned here for [typescript](https://storybook.js.org/docs/configurations/typescript-config/#setting-up-typescript-with-babel-loader).
Making the following the contents of the file:
```javascript
module.exports = ({ config }) => {
// Transpile Gatsby module because Gatsby includes un-transpiled ES6 code.
config.module.rules[0].exclude = [/node_modules\/(?!(gatsby)\/)/]
// use installed babel-loader which is v8.0-beta (which is meant to work with @babel/core@7)
config.module.rules[0].use[0].loader = require.resolve("babel-loader")
// use @babel/preset-react for JSX and env (instead of staged presets)
config.module.rules[0].use[0].options.presets = [
require.resolve("@babel/preset-react"),
require.resolve("@babel/preset-env"),
]
// use @babel/plugin-proposal-class-properties for class arrow functions
config.module.rules[0].use[0].options.plugins = [
require.resolve("@babel/plugin-proposal-class-properties"),
]
// Prefer Gatsby ES6 entrypoint (module) over commonjs (main) entrypoint
config.resolve.mainFields = ["browser", "module", "main"]
config.module.rules.push({
test: /\.(ts|tsx)$/,
loader: require.resolve('babel-loader'),
options: {
presets: [['react-app', { flow: false, typescript: true }]],
},
});
config.resolve.extensions.push('.ts', '.tsx');
return config
}
Five-pointed_star.svg
, that's nothing more, nothing less than well...a five points star, saved it inside the components
folder for simplicity.StarComponentContainer.tsx
inside that folder with the following code:
import * as React from 'react';
import starUrl, { ReactComponent as Star } from './Five-pointed_star.svg'
const StarComponentContainer:React.FunctionComponent=()=>(
); export default StarComponentContainer;
- Created a story for that component with the following code:
```javascript
import React from 'react';
import { storiesOf } from '@storybook/react';
import StarComponentContainer from './StarComponentContainer';
storiesOf('Star', module)
.add('StarComponent default',()=><StarComponentContainer/>)
Issued npm run storybook
. The build goes fine as you can see below:
It's when i open http://localhost:6006
that the problem pops up.
I'm presented with the following:
Created a new page called test
under pages
folder and a storybook story file to test it out
Page code:
import * as React from 'react';
import StarComponentContainer from '../components/StarComponentContainer';
const TestPage:React.FunctionComponent=()=>(
); export default TestPage;
Storybook story code:
```javascript
import React from 'react';
import { storiesOf } from '@storybook/react';
import TestPage from './test';
storiesOf('Test Page',module)
.add('default',()=><TestPage/>)
npm run storybook
with the same outcome, the build went ok, but the same result as above.webpack.config.js
to accomodate the code inside the library's gatsby-node
file here, same result as above.There might be something here i'm not seeing and something else in terms of configuration might be needed. Sorry i could not be more of assistance.
What an awesome response! Thanks for taking the time. Will take a look at this soon!
@elie222 no need to thank, glad i could be of some assistance. Sorry that i could not fix the issue entirely.
Just read through it all now. Thanks for the help.
This is my attempt at getting things working:
https://github.com/elie222/elie-tech/tree/storybook
But no luck either. To see the issue at hand:
git clone git@github.com:elie222/elie-tech.git
cd elie-tech
git checkout storybook
yarn storybook
@elie222 It doesn't look like you're declaring @svgr/webpack
in your dependencies; is it being loaded by Storybook? Can you go ahead and add it and see if that resolves your issue? For what it's worth, gatsby-plugin-svgr
2.0.2 resolves an incorrect (overly narrow) peer dependency and could be related.
@coreyward @svgr/webpack
is added to the project's dependencies, as you can see here. @elie222 i'm currently making some tests to see if i have figured out is actually the problem here. I'll post my findings as soon as i can. Sounds good?
Sounds awesome ❤️ . This may be a problem with the latest version of Storybook. v5 just came out and there were a fair number of issues related to importing svgs/pngs on SB repo. I have posted there too:
@elie222 looks like it worked. I'm going to break down the answer into smaller bits so that you can make adjustments as you go along. Going to start off with the typescript part and then move onto the storybook part.
When i was working on your issue, one thing kept bugging me while i was trying to make the reproduction work and it's that when you import a svg file into any component a squigly line keeps popping up below, saying it can't resolve it. And i was seeing it in your code aswell.
So, to make typescript and svg "play nice", in the root of the project i've created a file called custom.d.ts
with the following code:
declare module "*.svg" {
const content: any;
export default content;
}
Modified the tsconfig.json to the following:
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "commonjs",
"target": "esnext",
"jsx": "react",
"lib": ["dom", "esnext"]
},
"include": [
"./src/**/*"
],
"files": [
"custom.d.ts"
]
}
No more issues with svg and typescript inside the components.
I saw that you have copied over the image files and svg files to the static
folder and have some of them replicated inside the some of the project's components folders.
I understood your reasoning, when you issue start-storybook -p 9001 -c .storybook -s ./static
you're expecting that based on the arguments you supplied it will pick up the contents of the static
folder and will automatically serve them. Based on your current setup that's not the case, because the exact folder structure will be served as is. And inside a component, for instance ArticleItem.tsx
you have the following import import favorite from "./favorite.svg
and with that the contents weren't being shown for me. What i did was was move all of the svg files to src/assets/icons
and the images to src/assets/images
. and updated the mentioned import to import Favorite from "../../assets/icons/favorite.svg";
. And you'll understand why later in the comment.
Also in that "department"(pardon the bad pun), i saw that you're making the folder available to graphql and if you absolutely need it, fine by me, just ignore this part of the comment. But as a good practice with gatsby, items inside the folder are already available to you directly, so you shouldn't need to add a extra layer to your code. More on that here.
Onto the question at hand, to make storybook and gatsby "play nice".
The first thing i've done while looking at your code, was to remove @storybook/react": "^5.1.0-alpha.10
and revert it back to @storybook/react": "^5.0.3
, reason why, basically it's an alpha and i'm seeing some chatter that it's still a bit brittle.
Then @coreyward's comment made me take a step back and think about the webpack config. And he was right, i know for sure that storybook has support for svgs out of the box. But this, this is a special case, you're treating a svg like a React component. And the @svgr/webpack
loader was not being added.
With that in mind i made a few tweaks to the webpack.config.js
file for storybook. Transforming the code into:
const path= require('path');
const pathToInlineSvg = path.resolve(__dirname, '../src/assets/icons/');
module.exports = ({ config }) => {
// Transpile Gatsby module because Gatsby includes un-transpiled ES6 code.
config.module.rules[0].exclude = [/node_modules\/(?!(gatsby)\/)/]
// use installed babel-loader which is v8.0-beta (which is meant to work with @babel/core@7)
config.module.rules[0].use[0].loader = require.resolve("babel-loader")
// use @babel/preset-react for JSX and env (instead of staged presets)
config.module.rules[0].use[0].options.presets = [
require.resolve("@babel/preset-react"),
require.resolve("@babel/preset-env"),
]
// use @babel/plugin-proposal-class-properties for class arrow functions
config.module.rules[0].use[0].options.plugins = [
require.resolve("@babel/plugin-proposal-class-properties"),
]
// Prefer Gatsby ES6 entrypoint (module) over commonjs (main) entrypoint
config.resolve.mainFields = ["browser", "module", "main"]
config.module.rules.push({
test: /\.(ts|tsx)$/,
loader: require.resolve('babel-loader'),
options: {
presets: [['react-app', { flow: false, typescript: true }]],
},
});
config.resolve.extensions.push('.ts', '.tsx');
// svg with @svgr
const fileLoaderRule = config.module.rules.find(rule => rule.test.test('.svg'));
fileLoaderRule.exclude = pathToInlineSvg;
config.module.rules.push({
test: /\.svg$/,
include: pathToInlineSvg,
use: [{
loader: '@svgr/webpack',
options: {
icon: true,
},
}],
});
//
return config
}
Focusing on the important parts of the code here:
The following line, const pathToInlineSvg = path.resolve(__dirname, '../src/assets/icons/');
, like i said above, as i moved all the svg files inside /src/assets/icons/
, so this const will hold an array with all of them.
The following bit:
const fileLoaderRule = config.module.rules.find(rule => rule.test.test('.svg'));
fileLoaderRule.exclude = pathToInlineSvg;
config.module.rules.push({
test: /\.svg$/,
include: pathToInlineSvg,
use: [{
loader: '@svgr/webpack',
options: {
icon: true,
},
}],
});
When it reaches here, it will exclude the out of the box svg support for the svgs in the above array and adds a new rule for loading svgs, but this time with @svgr/webpack
.
All that is missing is change the components accordingly. For instance your component ArticleItem.tsx
is modified to the following, i left out the majority of the code to focus on the important parts:
// import favorite from "./favorite.svg"
import Favorite from "../../assets/icons/favorite.svg";
export default (props: ArticleItemProps) => {
return (
<Wrapper href={props.link} target="_blank">
......
<Main>
<Bottom>
<Likes>
{props.likes || 0}
{/* <LikesIcon src={favorite} /> */}
<Favorite/>
</Likes>
<Tags>{props.tags.map((tag) => `#${tag.toLowerCase()}`).join(", ")}</Tags>
</Bottom>
</Main>
</Wrapper>
)
}
npm run storybook
now yelds the following:Sorry for the extremely long post, hope i could shed some insights and helpd solve your issue.
Thanks so much for the help. Working through this now, but just fixing the TS import and reverting to SB 5.0.3 has got SB loading again at least!
Can I buy you a coffee (or 3), on something like: https://www.buymeacoffee.com/? Or send you a tip in Bitcoin/Eth?
Also, I didn’t quite understand what you meant about me exposing items to graphql. I do load the data on the homepage using graphql so that I can use gatsby image. Is there another place I’m doing this for no need?
@elie222 i'm glad i could be of assistance. No need for the coffee but thanks for the offer. Also ok...i didn't go through the code with a fine tooth comb, just focused on the storybook part, so disregard the exposing items to graphl part of the comment.
Description
I have been struggling to get Storybook v5, Gatsby working with SVG loader and TS to work nicely together.
Steps to reproduce
Install the
gatsby-plugin-svgr
plugin. Import an SVG into a.tsx
file. Gatsby should load this fine. Run Storybook.Expected result
Storybook should run and import the SVG.
Actual result
Storybook does not load. The error is:
Environment