question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

create-react-app + jsconfig.json paths: modules/scripts not found

See original GitHub issue

Describe the bug When using CRA and “jsconfig.json”: if I set “path” property to solve imports alias, the app works as expected running CRA, but Storybook crashes saying it can’t resolve imports.

To Reproduce Steps to reproduce the behavior:

  1. Start a new CRA app
  2. Create some containers and import them using aliases.
  3. Fill jsconfig.json file with paths/alias and make sure it works ok when building using CRA
  4. Try running Storybook: it crashes
  5. See modules not found error

Expected behavior Shouldn’t Storybook take the paths from jsconfig.json file - or solve it someway with full control mode, where I could solve the imports using “resolve” with Webpack?

Code snippets

This is my current jsconfig.json file (Using it with Create React App it works perfectly and the app builds with no errors):

// jsconfig.json
{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@mycompany/app/*": ["./packages/app/*"],
      "@mycompany/http/*": ["./packages/http/*"],
      "@mycompany/icons/*": ["./packages/icons/*"],
      "@mycompany/ui/*": ["./packages/ui/*"]
      // etc...
    }
  },
  "exclude": ["node_modules", "build", "coverage", "dist", "lib"]
}

This is the .storybook/config.js file.

// .storybook/config.json
import { addDecorator, configure } from '@storybook/react';
import { withKnobs } from '@storybook/addon-knobs/react';
import JssProvider from 'react-jss/lib/JssProvider';
import MuiThemeProvider from '@material-ui/core/styles/MuiThemeProvider';
import React from 'react';

import TooltipProvider from '../src/packages/ui/src/Tooltip/TooltipProvider';
import theme from '../src/packages/app/src/theme';

addDecorator(withKnobs);

const generateClassName = (rule, styleSheet) =>
  `${styleSheet.options.classNamePrefix}-${rule.key}`;

addDecorator(story => (
  <JssProvider generateClassName={generateClassName}>
    <MuiThemeProvider theme={theme}>
      <TooltipProvider>
        <div
          style={{
            position: 'absolute',
            top: 0,
            right: 0,
            bottom: 0,
            left: 0,
            width: '100%',
            height: '100%'
          }}
        >
          {story()}
        </div>
      </TooltipProvider>
    </MuiThemeProvider>
  </JssProvider>
));

const req = require.context('../src', true, /.*.stories.js$/);

const loadStories = () => {
  req.keys().forEach(filename => req(filename));
};

configure(loadStories, module);

Also, I’ve tried to use the full control mode, with this config:

// .storybook/webpack.config.js
const path = require('path');

module.exports = async ({ config }) => {

  config.resolve = Object.assign(config.resolve, {
    alias: {
      "@mycompany/app": path.resolve(__dirname, "../src/packages/app/"),
      "@mycompany/http": path.resolve(__dirname, "../src/packages/http"),
      "@mycompany/icons": path.resolve(__dirname, "../src/packages/icons"),
      // etc...
    }
  });

  return config;
}

System:

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

20reactions
ppalmeidacommented, Jul 2, 2019

Hey, @mrmckeb. Thank you for your reply.

Actually I have to say I was completely WRONG when said that CRA was assuming jsconfig.json file and using it to resolve the paths/alias. No no. Not, at least, not YET

So, I think we can close this issue.

For those who is interested in having CRA working with paths (or, if you prefer alias) to your folders/packages, here it is what I did to make it work (without eject CRA)

Step 1

I prefer not to eject CRA, so I went with some plugin: I used the well known create-react-app-rewired

Step 2

After install it, I created a config-overrides.js in the root of the app and put this inside:

const path = require("path");

const resolve = dir => path.resolve(__dirname, dir);

module.exports = function(config, env) {
  config.resolve.alias = Object.assign(config.resolve.alias, {
    "@mycompany/app": resolve("src/packages/app"),
    "@mycompany/core": resolve("src/packages/core"),
    "@mycompany/http": resolve("src/packages/http"),
    // etc...
  });

  return config;
};

Step 3

Then, I created the jsconfig.json file with these lines:

{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@mycompany/app/*": ["packages/app/*"],
      "@mycompany/core/*": ["packages/core/*"],
      "@mycompany/http/*": ["packages/http/*"],
      // etc... you got the idea...
    }
  },
  "exclude": ["node_modules", "build", "coverage", "dist", "lib"]
}

And then you would ask: “But why use this file if you already did the rewired webpack in step 2?”. Because jsconfig.json file helps your IDE to find your modules and files, etc. At least, my VSCode works better on this way.

Step 4: JEST

JEST: now, you must run your tests, right? So, add these lines to your package.json also:

// etc...
"jest": {
    "moduleNameMapper": {
      "^@mycompany/app(/?)(.*?)$": "packages/app$1$2",
      "^@mycompany/core(/?)(.*?)$": "packages/core$1$2",
      "^@mycompany/http(/?)(.*?)$": "packages/http$1$2",
    }
  },

Pretty nasty, ahn? The keys are RegExp that Jest uses to find your files. And “Why did you use 2 groups in your regex, if they are at the end of the string anyway?”. Well, this is how Webpack (or Jest, I’m not sure) will match your files:

So, these both will work:

import MyAwesomeModule from '@mycompany/app'
import MyOtherAwesomeModule from '@mycompany/app/folder1/folder2/MyOtherAwesomeModule';

Step 5: Storybook

Well, let’s put Storybook in full-control mode, so we can apply the same concepts to Storybook as well. To do that, you must create a webpack.config.js file inside .storybook folder and add there your packages “binds” too:

const path = require("path");

const resolve = dir => path.resolve(__dirname, dir);

module.exports = async ({ config }) => {
  config.resolve = Object.assign(config.resolve, {
    alias: {
      "@mycompany/app": resolve("../src/packages/app"),
      "@mycompany/core": resolve("../src/packages/core"),
      "@mycompany/http": resolve("../src/packages/http"),
    }
  });

  return config;
};

Note that, since this file is inside .storybook folder, the path needs the ../ before all src/etc folder.

Bottom Line:

I don’t know if there is a better strategy here. Maybe there is a really better way. Keep NODE_PATH in .env file and ignore the CRA warning? Maybe eject CRA? Maybe use NextJS?

As I put in the link in the beginning, I think CRA will soon have it’s “way” of offering path out of the box. But, for now, I don’t think it’s worth to do all these configurations. For me, it’s too much effort. Anyway, maybe it can help someone.

cheers

8reactions
yairEOcommented, May 21, 2020

@xppalmeida - I was facing problems where eslint complained about not being able to resolve my absolute paths but I’ve managed to fix them!

Using this resolver: eslint-import-resolver-node

eslint configuration file (relevant part)

settings: {
    'import/resolver': {
        'node': {
            'paths': ['./', './src']
    }
}

.env

...
NODE_PATH=./

jsconfig.json

{
    "compilerOptions": {
        "jsx": "react",
        "baseUrl": "./",
        "paths": {
            "stories/*": ["stories/*"],
            "shared/*": ["src/shared/*"],
        },
    },
    "include": ["src/**/*", "stories/**/*"]
}

only with 'paths': ['./', './src'] in my eslint config things the linter worked resolving the paths correctly.

Storybook seems to work well with the above configuration and nothing else.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Module not found when specifying "paths" in jsconfig.json
Any idea why this is happening? EDIT. I Tried using this: { "compilerOptions": { "baseUrl": "src" }, " ...
Read more >
jsconfig.json not working react - You.com | The AI Search ...
It's a configuration file to assist your editor's Language Server (LSP) with the javascript usage in your project folder.
Read more >
Module Not Found When Specifying "Paths" In Jsconfig.Json
It lets your React components read data from a Redux store and dispatch actions Redux + Plain JS templatenpx createreactapp myapp template redux....
Read more >
React JS imports made easy with Absolute paths using ...
Absolute paths for adding components from where without drilling backwards was my need and achieved it adding “jsconfig.json” file. No npm installation ...
Read more >
react-app-rewire-alias - npm
Currently, create-react-app (CRA) does not support more than one src ... enumerate aliases in jsconfig.paths.json or tsconfig.paths.json ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found