Storybook: Import of markdown fails after hot reload

Created on 3 Nov 2020  路  4Comments  路  Source: storybookjs/storybook

Describe the bug
I'm getting "Cannot find module './something.mdx' or its corresponding type declarations" error on reload when using webcomponents storybook.

I'm using storybook 6 for a webcomponents project. The stories are typescript files. I'm generating a markdown documentation with an external tool that creates 'mdx' files next to the story files. In the stories I'm using code like this:

import doc from "./some-component.mdx"

export default {
    title: "Some Component,
    parameters: {
        docs: { page: doc }
    }
}

When I start storybook, this works as expected. The stories are displayed and the markdown docs are there in the docs tab. Everything works fine.

However, when I change something in the story and save the file, the storybook is reloading the page and now I get the following error:

ERROR in /Users/.../some-component.stories.ts(3,17)
      TS2307: Cannot find module './some-component.mdx' or its corresponding type declarations.

In the preview.js I have the following configuration (taken from setup docs):

const req = require.context('../src', true, /\.stories\.ts$/);
configure(req, module);

if (module.hot) {
    module.hot.accept(req.id, () => {
        const currentLocationHref = window.location.href;
        window.history.pushState(null, null, currentLocationHref);
        window.location.reload();
    });
}

In main.js I have a custom webpack rule defined:

module.exports = {
    webpackFinal: async (config) => {
        config.module.rules.push({
            test: /\.(ts|tsx)$/,
            exclude: /(node_modules)/,
            use: {
                loader: 'ts-loader',
                 options: {
                    compilerOptions: {
                        rootDir: '.'
                    }
                / }
            }
        });

If I remove this rule, then it works with the reload but I don't understand why.
It looks like it's using a different webpack config when doing a reload? I don't understand why it's working initially but not on reload.

System
Environment Info:

System:
OS: macOS 10.15.7
CPU: (8) x64 Intel(R) Core(TM) i7-7820HQ CPU @ 2.90GHz
Binaries:
Node: 14.14.0 - ~/.nvm/versions/node/v14.14.0/bin/node
Yarn: 1.22.10 - ~/.nvm/versions/node/v14.14.0/bin/yarn
npm: 6.14.8 - ~/.nvm/versions/node/v14.14.0/bin/npm
Browsers:
Chrome: 86.0.4240.111
Firefox: 81.0.2
Safari: 14.0
npmGlobalPackages:
@storybook/cli: 6.0.26

docs mdx question / support

Most helpful comment

I've found a solution for my problem. I've added a declarations.d.ts with

declare module '*.mdx' {
    const value: string;
    export default value;
}

This way the typescript compiler doesn't complain about mdx imports anymore. So the actual problem is solved but I'm still curious why it was working on the initial request but not with after hot-reloading.

All 4 comments

@manuel-mauky not entirely sure what's going on, but SB6 has built-in typescript support, so that ts-loader rule is redundant with an existing rule in storybook:

https://storybook.js.org/docs/react/configure/typescript#gatsby-focus-wrapper

The problem is that (if I understand correctly) by default Storybook uses babel to transpile TypeScript and not the "real" TypeScript compiler (tsc).
We are using the tsc to create our production bundles and therefore now we have a mismatch.
From time to time there are differences between babel and tsc and at the moment we have a problem that babel introduces some errors that aren't there with tsc. So if we remove the ts-loader config, we get exceptions in the Storybook.
Using ts-loader fixes this but now we have the bug described above.

So the other question is: How can we configure storybook to use tsc and not babel to transform typescript code? In the docs it says that angular is using ts-loader instead of babel-loader so it should be possible?

@manuel-mauky theoretically possible but not currently supported. cc @mrmckeb

I've found a solution for my problem. I've added a declarations.d.ts with

declare module '*.mdx' {
    const value: string;
    export default value;
}

This way the typescript compiler doesn't complain about mdx imports anymore. So the actual problem is solved but I'm still curious why it was working on the initial request but not with after hot-reloading.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zvictor picture zvictor  路  3Comments

shilman picture shilman  路  3Comments

ZigGreen picture ZigGreen  路  3Comments

levithomason picture levithomason  路  3Comments

shilman picture shilman  路  3Comments