Describe the bug
Introducing @storybook/addon-docs to my repo, everything in the Docs tab works fine except for the source code which is not available.
To Reproduce
Started creating a repro repo using the cra-ts gist but got stuck in unrelated issues when ejecting to simulate my own main repo, hence no steps available at this point, please refer to below information.
Expected behavior
The source code should be displayed in the Docs tab.
Screenshots
My Docs tab (as you can see just about everything works fine, except for the lack of source code):

Code snippets
main.js
module.exports = {
stories: ['../src/**/Alert.stories.tsx'],
addons: [
'@storybook/addon-actions/register',
'@storybook/addon-viewport/register',
'@storybook/addon-a11y/register',
'@storybook/addon-backgrounds/register',
{
name: '@storybook/addon-docs',
options: {
configureJSX: true,
},
},
],
}
preview.js
import { addDecorator, addParameters } from '@storybook/react'
import { withA11y } from '@storybook/addon-a11y'
import centered from '@storybook/addon-centered/react'
// import '../src/Styles/_global.scss'
// addDecorator(centered)
addDecorator(withA11y)
addParameters({
backgrounds: [
{ name: 'light', value: '#eff0f9', default: true },
{ name: 'dark', value: '#392b64' },
],
})
webpack.config.js
const path = require('path')
const fs = require('fs')
const { mergeDeepLeft } = require('ramda')
// Make sure any symlinks in the project folder are resolved:
// https://github.com/facebook/create-react-app/issues/637
const appDirectory = fs.realpathSync(process.cwd())
const resolveApp = relativePath => path.resolve(appDirectory, relativePath)
const storybookCfg = {
module: {
rules: [
{
test: /\.(ts|tsx)$/,
include: [resolveApp('src')],
loaders: [
{
loader: require.resolve('babel-loader'),
options: {
presets: [['react-app', { flow: false, typescript: true }]],
},
},
{
// This is used to display TypeScript types under the "Docs" tab in Storybook.
loader: require.resolve('react-docgen-typescript-loader'),
options: {
// Provide the path to your tsconfig.json so that your stories can
// display types from outside each individual story.
tsconfigPath: path.resolve(__dirname, '../tsconfig.json'),
},
},
],
},
{
test: /\.(js|jsx)$/,
include: [resolveApp('src'), resolveApp('.storybook')],
loaders: [
{
loader: require.resolve('babel-loader'),
options: {
presets: [['react-app']],
},
},
],
},
{
test: /\.module\.scss$/,
loaders: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
modules: {
localIdentName: '[name]__[local]___[hash:base64:5]',
},
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009',
},
stage: 3,
}),
],
},
},
{
loader: require.resolve('sass-loader'),
options: {
importLoaders: 2,
modules: true,
localIdentName: '[name]__[local]___[hash:base64:5]',
},
},
],
},
{
test: /\.scss$/,
exclude: /\.module\.scss$/,
loaders: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009',
},
stage: 3,
}),
],
},
},
{
loader: require.resolve('sass-loader'),
options: {
importLoaders: 2,
},
},
],
},
{
test: /\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani)(\?.*)?$/,
loader: 'file-loader',
query: { name: 'static/media/[name].[hash:8].[ext]' },
},
{
test: /\.(mp4|webm|wav|mp3|m4a|aac|oga)(\?.*)?$/,
loader: 'url-loader',
query: { limit: 10000, name: 'static/media/[name].[hash:8].[ext]' },
},
],
},
}
module.exports = ({ config }) => {
config.resolve.extensions.push('.ts', '.tsx', '.module.scss', '.scss')
config.output.publicPath = process.env.PUBLIC_URL
return mergeDeepLeft(storybookCfg, config)
}
Alert.stories.tsx
import React from 'react'
import Alert from './Alert'
export default {
title: 'Components/Alert',
component: Alert,
}
export const warning = () => (
<Alert testSelector="alert-selector" title="This is an alert." />
)
Alert.tsx
import React from 'react'
interface AlertProps {
/** they see me commenting */
testSelector?: string
title?: string
}
/** Alert stuff */
const Alert = ({ testSelector = 'hej', title }: AlertProps) => {
return (
<div data-testid={testSelector}>
<div>
<p>
<strong>{title}</strong>
</p>
</div>
</div>
)
}
export default Alert
System:
Environment Info:
System:
OS: Windows 10 10.0.18362
CPU: (12) x64 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
Binaries:
Node: 12.16.1 - C:\Program Files\nodejs\node.EXE
npm: 6.14.2 - ~\source\repos\Common-Component-Library\node_modules.bin\npm.CMD
Browsers:
Edge: 44.18362.449.0
Additional context
I've studied similar issues meticulously and tried the suggested fixes, in particular https://github.com/storybookjs/storybook/issues/8104
Worth mentioning is that it doesn't matter if I use CSF or storiesOf, same issue applies.
You might need to add source-loader to the .tsx? rules since it looks like you're overriding them: https://github.com/storybookjs/storybook/tree/next/addons/docs#manual-configuration
Confirmed solution. Appended
{
loader: require.resolve('@storybook/source-loader'),
},
to the tsx-matching block in webpack.config.js and that worked wonders. 馃挴
Before we close I have one more clarifying question to help others who may end up in a similar situation:
Are you saying that by specifying a tsx-loader I am overwriting some out of the box @storybook/source-loader configuration?
Thanks a lot for the support. 馃檹
@jgarplind you're running mergeDeepLeft(storybookCfg, config) and it appears that's overwriting the typescript rules. i think the devil's in the details about how you merge the rules, so i wouldn't generalize that statement.
also, for clarification, it's the addon-docs preset that's configuring source-loader AFAIK.
@shilman @jgarplind I have the same problem with not showing the Show code, however, I'm not using typescript and also not using a custom webpack config.
This is my config:
module.exports = {
stories: ['../src/**/*.stories.(jsx|mdx)', '../docs/**/*.stories.(jsx|mdx)'],
addons: [
'@storybook/preset-create-react-app',
'@storybook/addon-actions',
'@storybook/addon-links',
'@storybook/addon-knobs/register',
'@storybook/addon-viewport/register',
'@storybook/addon-storysource/register',
'@storybook/addon-a11y/register',
'@storybook/addon-notes/register',
'@storybook/addon-options/register',
'@storybook/addon-backgrounds/register',
'@storybook/addon-docs/register',
],
presets: [
{
name: '@storybook/addon-docs/preset',
options: {
configureJSX: true,
},
},
],
};
@elderalves try changing it to:
module.exports = {
stories: ['../src/**/*.stories.(jsx|mdx)', '../docs/**/*.stories.(jsx|mdx)'],
addons: [
'@storybook/preset-create-react-app',
'@storybook/addon-actions',
'@storybook/addon-links',
'@storybook/addon-knobs/register',
'@storybook/addon-viewport/register',
'@storybook/addon-storysource/register',
'@storybook/addon-a11y/register',
'@storybook/addon-notes/register',
'@storybook/addon-options/register',
'@storybook/addon-backgrounds/register',
'@storybook/addon-docs', // removed "register"
],
};
If that doesn't work, let me know if you have a repro repo I can look at
@shilman I changed and it still doesn't show... It's a private repo.
for example... my Button.stories.jsx looks like it:
import React from 'react';
import { Box } from '@material-ui/core';
import { Download } from 'mdi-material-ui';
import { action } from '@storybook/addon-actions';
import {
withKnobs, boolean,
} from '@storybook/addon-knobs';
// COMPONENTS
import Button from '../Button';
import { AppProvider } from '../../../../.storybook/components';
// DOC
import docs from './Button.docs.mdx';
export default {
title: 'Components|Button',
component: Button,
decorators: [withKnobs],
parameters: {
docs: { page: docs },
},
};
export const Primary = () => (
<AppProvider>
<Button
disabled={boolean('Disabled', false)}
appearance="primary"
onClick={action('clicked')}
>
Click here
</Button>
</AppProvider>
);
is it right?
@jgarplind you're running
mergeDeepLeft(storybookCfg, config)and it appears that's overwriting the typescript rules. i think the devil's in the details about how you merge the rules, so i wouldn't generalize that statement.also, for clarification, it's the addon-docs preset that's configuring source-loader AFAIK.
Thanks, from my side this issue can be closed.
For anyone facing this problem in general, even without using typescript:
In my project I am overriding the default storybook webpack config with my own custom webpack config. This meant that any of the default module.rules from storybook webpack config were not being applied. Due to this the source-loader rule was also not being applied, and DocsPage was showing 'No code available' .
I re-added the source-loader rule and it works fine.
Most helpful comment
You might need to add
source-loaderto the.tsx?rules since it looks like you're overriding them: https://github.com/storybookjs/storybook/tree/next/addons/docs#manual-configuration