nx icon indicating copy to clipboard operation
nx copied to clipboard

Storybook v7 / React / Vite: can not import/resolve nx library

Open unrealsolver opened this issue 1 year ago • 7 comments

Current Behavior

Storybook's serve target can not resolve import of nx library: import { DeleteUserConfirm } from '@libraryname/settings' with following error:

Error: The following dependencies are imported but could not be resolved:

  @libraryname/settings (imported by /home/username/dev/project/project/packages/app/src/app/SettingsStories/userForms.stories.tsx)

Are they installed?

Expected Behavior

I expect Storybook to be able to reslve aliases defined in base ts config, the same way as nx serve app does.

GitHub Repo

No response

Steps to Reproduce

  1. Create react+vite+ts monorepo
  2. Create a react app
  3. Add storybook v7 to the app
  4. Create a react+ts+no bundler library
  5. Create a story in the App project that imports any entity from the nx library using alias (e.g. @workspace/library)

Nx Report

>  NX   Report complete - copy this into the issue template

   Node   : 16.15.1
   OS     : linux x64
   yarn   : 3.5.0
   Hasher : Native

   nx                 : 16.0.1
   @nx/js             : 16.1.4
   @nx/linter         : 16.0.3
   @nx/workspace      : 16.0.1
   @nx/cypress        : 16.0.3
   @nx/eslint-plugin  : 16.0.3
   @nx/react          : 16.0.3
   @nx/storybook      : 16.1.4
   @nx/vite           : 16.0.3
   @nx/web            : 16.1.4
   typescript         : 5.0.4
   ---------------------------------------
   The following packages should match the installed version of nx
     - @nx/[email protected]
     - @nx/[email protected]
     - @nx/[email protected]
     - @nx/[email protected]
     - @nx/[email protected]
     - @nx/[email protected]
     - @nx/[email protected]
     - @nx/[email protected]

   To fix this, run `nx migrate [email protected]`

Failure Logs

Error: The following dependencies are imported but could not be resolved:

  @libraryname/settings (imported by /home/username/dev/project/project/packages/app/src/app/SettingsStories/userForms.stories.tsx)

Are they installed?

Operating System

  • [ ] macOS
  • [X] Linux
  • [ ] Windows
  • [ ] Other (Please specify)

Additional Information

This should be possible to workaround using viteFinal and resolver property in the .storybook/main, but that should work by default. main.ts (default):

import type { StorybookConfig } from '@storybook/react-vite';

const config: StorybookConfig = {
  stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
  addons: ['@storybook/addon-essentials'],
  framework: {
    name: '@storybook/react-vite',
    options: {
      builder: {
        viteConfigPath: 'packages/app/vite.config.ts',
      },
    },
  },
};

export default config;

// To customize your Vite configuration you can use the viteFinal field.
// Check https://storybook.js.org/docs/react/builders/vite#configuration
// and https://nx.dev/packages/storybook/documents/custom-builder-configs

ts/vite config are also default. Related issues #16208 (for WebPack)

unrealsolver avatar May 23 '23 12:05 unrealsolver

For anyone looking for a quick workaround:

import type { StorybookConfig } from '@storybook/react-vite';
import { mergeConfig } from 'vite';
import path from 'path';

const config: StorybookConfig = {
  stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
  addons: ['@storybook/addon-essentials'],
  framework: {
    name: '@storybook/react-vite',
    options: {
      builder: {
        viteConfigPath: 'packages/app/vite.config.ts',
      },
    },
  },
  viteFinal: async (config, { configType }) => {
    console.log(__dirname);
    return mergeConfig(config, {
      resolve: {
        alias: {
          '@workspacename/libraryname': path.resolve(
            __dirname,
            '../../libraryname/src/index.ts'
          ),
        },
      },
    });
  },
};

unrealsolver avatar May 23 '23 13:05 unrealsolver

getting the exact same issue in windows. within the scope of an nx library using vite, storybook presents that same error for any nx libraries imported into a component used in a story.

Good temp fix recommendation @unrealsolver, saved me breaking another keyboard...

binaryartifex avatar May 24 '23 22:05 binaryartifex

@binaryartifex @unrealsolver

The issue is the following:

If you import a workspace library (a Nx library) into another Nx project (library or app) that's using @storybook/react-vite or some Storybook vite builder, then:

  1. Storybook WILL find the paths correctly if the library is imported in a component file
  2. Storybook WILL NOT find the paths correctly if the library is imported in a story file.

Here is a reproduction I've created and shared with the Storybook team, because I think that this is an issue on the Storybook side at the moment.

In that reproduction, you will see that if you remove the library imports from the .stories.ts files then Storybook builds correctly, and I am still importing the library into the components.

mandarini avatar May 25 '23 13:05 mandarini

Potentially related: https://github.com/nrwl/nx/issues/17257

mandarini avatar May 29 '23 13:05 mandarini

Totally looks the same @mandarini !  Except on my repro in #17257 it works for the stories of the app, but not in libs …

Thanks @unrealsolver for the workaround !

JalilArfaoui avatar May 29 '23 14:05 JalilArfaoui

for anyone finding it annoying to keep adding the same config to every lib's .storybook/main.js, i made a simple JS config file in the root of my monorepo and exported it:

import { mergeConfig } from "vite";
import path from 'path'

export const viteModuleResolver = async (config) => mergeConfig(config, {
  resolve: {
    alias: {
      '@monorepo/core': path.resolve(
        __dirname,
        './libs/core/src/index.ts'
      ),
      '@monorepo/blocks': path.resolve(
        __dirname,
        './libs/blocks/src/index.ts'
      ),
      // add rest of libs!
    },
  },
});

export default viteModuleResolver

then i imported the file in each .storybook/main.js

import viteModuleResolver from '../../../vite.config'

const config = {
  ...rest of config...
  viteFinal: viteModuleResolver
}

in this case, blocks and core were 2 libs i had

worked like a charm. props again to @unrealsolver for the solution!

cidkhode avatar Jun 15 '23 11:06 cidkhode

Thank you all for all these workarounds. I want to find a good solution to solve this internally, but have not managed to do it yet.

mandarini avatar Jun 15 '23 11:06 mandarini

for anyone finding it annoying to keep adding the same config to every lib's .storybook/main.js, i made a simple JS config file in the root of my monorepo and exported it:

import { mergeConfig } from "vite";
import path from 'path'

export const viteModuleResolver = async (config) => mergeConfig(config, {
  resolve: {
    alias: {
      '@monorepo/core': path.resolve(
        __dirname,
        './libs/core/src/index.ts'
      ),
      '@monorepo/blocks': path.resolve(
        __dirname,
        './libs/blocks/src/index.ts'
      ),
      // add rest of libs!
    },
  },
});

export default viteModuleResolver

then i imported the file in each .storybook/main.js

import viteModuleResolver from '../../../vite.config'

const config = {
  ...rest of config...
  viteFinal: viteModuleResolver
}

in this case, blocks and core were 2 libs i had

worked like a charm. props again to @unrealsolver for the solution!

I had trouble generating the list of aliases, taking your idea a little further, here is an alias generator, that read libs paths from tsconfig.

const fs=require("fs");

const data = fs.readFileSync("tsconfig.base.json");
const json = JSON.parse(data);
const paths = json.compilerOptions.paths;
const list = Object.keys(paths).map(pkg => {

return `'${pkg}': path.resolve(__dirname,'./${paths[pkg]}')`

});

console.log(list.join(",\n"));

Save this as gen-alias.js at the top of your project and run node gen-alias.js, it will use console.log to print the config in stdout, then paste into vite.config alias section.

hanspoo avatar Jun 20 '23 20:06 hanspoo

Ok found the issue - solved the issue - with the help of @shilman!!! In your project's tsconfig.app.json or tsconfig.lib.json, remove the .stories.* paths from the excludes array. Then it works!!!!! :D No need for resolve.alias.

mandarini avatar Jun 23 '23 08:06 mandarini

Once #17749 is merged and makes into our next minor release, you can nx migrate and a better solution will take effect!

mandarini avatar Jun 26 '23 13:06 mandarini

This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.

github-actions[bot] avatar Jul 27 '23 00:07 github-actions[bot]