Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript modules not resolved when using "baseUrl". #4136

Closed
cwmrowe opened this issue Sep 7, 2018 · 13 comments
Closed

TypeScript modules not resolved when using "baseUrl". #4136

cwmrowe opened this issue Sep 7, 2018 · 13 comments

Comments

@cwmrowe
Copy link

cwmrowe commented Sep 7, 2018

Support request summary

@storybook/angular is not resolving non-relative imports. I believe non-relative imports are a relative new feature of TypeScript that allow you to reference imports from a baseUrl rather than always using relative imports to your own code.

I think that support for this feature should be a priority as VS Code will now rename all your modules to use non-relative imports automatically when you move/rename a file so its difficult problem to avoid.

Steps to reproduce

Create a strorybook project with Angular 6.1.1 and use non-relative imports in your code, e.g.

src/app/somefile.ts

import { environment } from 'environments/environment';
// instead of import { environment } from '../environments/environment';

Please specify which version of Storybook and optionally any affected addons that you're running

"@storybook/addon-actions": "^4.0.0-alpha.20",
"@storybook/addon-centered": "^4.0.0-alpha.20",
"@storybook/addon-knobs": "^4.0.0-alpha.20",
"@storybook/addon-links": "^4.0.0-alpha.20",
"@storybook/addon-notes": "^4.0.0-alpha.20",
"@storybook/addon-storysource": "^3.4.10",
"@storybook/addons": "^4.0.0-alpha.20",
"@storybook/angular": "^4.0.0-alpha.20",

Affected platforms

Windows 10

Workaround

I have managed to work around this using the TsconfigPathsPlugin and modifying my tsconfig.json file to use compilerOptions.paths (note the mappings look slightly ridiculous).

.storybook/tsconfig.json

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "module": "es2015",
    "paths": {
      "app/*": ["app/*"],
      "pages/*": ["pages/*"],
      "shared/*": ["shared/*"],
      "environments/*": ["environments/*"]
    }
  },
  "exclude": [
    "../src/test.ts",
    "../src/**/*.spec.ts",
    "../src/**/*.stories.ts"
  ],
  "include": ["../src/**/*"]
}

NB: compilerOptions.baseUrl has a value of "./src" in my root tsconfig.json

.storybook/webpack.config.js

const path = require('path');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');

module.exports = (baseConfig, env, config) => {
  config.resolve.plugins = config.resolve.plugins || [];
  config.resolve.plugins.push(
    new TsconfigPathsPlugin({
      configFile: path.resolve(__dirname, '../tsconfig.json')
    })
  );
  return config;
};

NB: The initial build is also excruciatingly slow, but I don't think its related.

@igor-dv
Copy link
Member

igor-dv commented Sep 10, 2018

Regarding the absolute paths, there was a similar issue - #3916. Maybe we should add 'baseUrl' to resolve.modules by default 🤔

For build time, please check this - #3968

@cwmrowe
Copy link
Author

cwmrowe commented Sep 11, 2018

Thanks @igor-dv its all working a treat now. And the build time has gone from 7 minutes down to 20 seconds 🚗 💨

Here's my .storybook/webpack.config.js for anyone that needs it, although hopefully this will be fixed in the angular storybook project soon.

const path = require('path');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');

module.exports = (baseConfig, env, config) => {
  // To get tsconfig baseUrl working
  // There is likely a better way to extract the baseUrl from tsconfig.
  config.resolve.modules.push(path.resolve(__dirname, '../src'));

  // To dramatically increase the build speed.
  let rule = config.module.rules.find(rule => {
    const { loader } = rule.use[0];
    return loader && loader.includes('ts-loader');
  });
  rule.use[0].options.transpileOnly = true;
  config.plugins.push(
    new ForkTsCheckerWebpackPlugin({
      tslint: path.resolve(__dirname, '../tslint.json'),
      tsconfig: path.resolve(__dirname, 'tsconfig.json')
    })
  );
  return config;
};

@gaurav5430
Copy link

@cwmrowe
adding this to the storybook webpack config works:

// To get tsconfig baseUrl working
  // There is likely a better way to extract the baseUrl from tsconfig.
  config.resolve.modules.push(path.resolve(__dirname, '../src'));

how does it work though? This seems specific to how webpack resolves module, and may or may not be directly co-related to how tsconfig is setup (?)

@davidgilbertson
Copy link

If it's useful to anyone, I'm doing this to avoid duplicating resolve.modules and tsconfig.json baseUrl:

// webpack.config.js
const path = require('path');
const { compilerOptions } = require('./tsconfig.json');

module.exports = {
  // other stuff
  resolve: {
    modules: [
      path.resolve(__dirname, 'node_modules'),
      path.resolve(__dirname, compilerOptions.baseUrl),
    ],
  },
};

@kylemh
Copy link
Member

kylemh commented Aug 19, 2020

I highly recommend using tsconfig-paths-webpack-plugin for aliases.

CC: @shilman - i feel like this is worth recommending at least in FAQ or maybe out of the box

setup:

const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');

module.exports = {
  stories: ['../**/*.stories.mdx', '../**/*.stories.@(js|jsx|ts|tsx)'],
  addons: ['@storybook/addon-links', '@storybook/addon-essentials'],
  webpackFinal: async (config) => {
    config.resolve.plugins.push(new TsconfigPathsPlugin({}));
    return config;
  },
};

@guilhermemarconi
Copy link

@kylemh I'm using it but it still not working on my project.

I have a NextJS project and everything works as expected locally, but the Storybook's build breaks because of baseUrl configuration.

it warns about every import on the project (including everything inside node_modules folder)

I'm using the latest versions of everything in the project

@kylemh
Copy link
Member

kylemh commented Aug 17, 2021

Share your config

@guilhermemarconi
Copy link

guilhermemarconi commented Aug 17, 2021

@kylemh I don't have a webpack.config.js in .storybook dir, but this is the content of the main.js

const path = require('path')
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin')

module.exports = {
  stories: ['../src/components/**/stories.tsx'],
  addons: ['@storybook/addon-essentials', 'storybook-addon-next-router'],
  babel: async (options) => ({
    ...options,
    plugins: [
      ...options.plugins,
      require.resolve('@babel/plugin-transform-react-jsx')
    ]
  }),
  webpackFinal: async (config) => {
    config.resolve.modules = [
      ...(config.resolve.modules || []),
      path.resolve(__dirname, '../src')
    ]

    config.resolve.plugins = [
      ...(config.resolve.plugins || []),
      new TsconfigPathsPlugin()
    ]

    return config
  }
}

EDIT:

my project's structure is something like this

./
-- .storybook/
---- main.js
---- preview.js
-- src/
---- components/
---- pages/

@kylemh
Copy link
Member

kylemh commented Aug 17, 2021

I worry that your module resolve is getting in the way of the TS Config Paths plugin. Can you copy my webpackFinal value exactly as I listed it? Additionally, what does your tsconfig.json look like?

@guilhermemarconi
Copy link

@kylemh still doesn't work but the error was different though.
I need to set config.resolve.modules with the src directory off the app, because without it Storybook stops working even locally.

here my tsconfig.json:

{
  "compilerOptions": {
    "baseUrl": "src",
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve"
  },
  "exclude": ["node_modules"],
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
}

@kylemh
Copy link
Member

kylemh commented Aug 18, 2021

Is it because you should have

stories: ['../src/components/**/*.stories.tsx'],

@guilhermemarconi
Copy link

guilhermemarconi commented Aug 18, 2021

@kylemh but my files actually are named as stories.tsx, and they exists inside each component folder. the structure is something like this:

Component/
-- Component.tsx
-- index.ts
-- stories.tsx
-- style.ts
-- tests.ts

index.ts is only to make easier to import the components in other files, so it just import the actual component from Component.tsx and exports it.

as I told earlier: Storybook works just fine in localhost. the problem is just when I build it to generate the static files to host it online.

@kylemh
Copy link
Member

kylemh commented Aug 18, 2021

Damn. Well I'm not certain, but you shouldn't be using a customer module resolver along with the TS plugin 🤷‍♂️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants