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

Resolve alias in webpack config #3339

Closed
allangrds opened this issue Apr 1, 2018 · 19 comments
Closed

Resolve alias in webpack config #3339

allangrds opened this issue Apr 1, 2018 · 19 comments

Comments

@allangrds
Copy link

allangrds commented Apr 1, 2018

Tools version

  • webpack: 4.2.0,
  • storybook/cli: 3.3.15,
  • storybook/react: 3.3.15,

Problem

Even using alias at webpack.config.js inside the .storybook folder, and in my root project folder, it seems storybook doesn't apply the aliases, resulting in a conflict of paths. If I want to run storybook, I need to update my static files paths to ../../../, and if I want to run a webserver, I need to update my static files paths to ../.

My code

.storybook/webpack.config.js

const path = require('path');
const includePath = path.resolve(__dirname, '..');

module.exports = {
  resolve: {
    alias: {
      atoms: path.resolve(__dirname, 'src/client/atoms/'),
      client: path.resolve(__dirname, 'src/client/'),
      fonts: path.resolve(__dirname, 'src/fonts/'),
      helpers: path.resolve(__dirname, 'src/helpers/'),
      images: path.resolve(__dirname, 'src/images/'),
      stories: path.resolve(__dirname, 'src/stories/'),
      styles: path.resolve(__dirname, 'src/styles/'),
      tests: path.resolve(__dirname, 'src/tests/'),
    },
    extensions: ['.js', '.jsx', '.css', '.png', '.jpg', '.gif', '.jpeg'],
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          require.resolve('style-loader'),
          {
            loader: require.resolve('css-loader'),
            options: {
              importLoaders: 1,
              modules: 1,
              localIdentName: '[path]-[name]-[local]',
            },
          },
          {
            loader: require.resolve('postcss-loader'),
            options: {
              ident: 'postcss',
              plugins: () => [
                require('postcss-import'),
                require('postcss-cssnext')({
                  features: {
                    customProperties: false,
                  },
                }),
              ],
            },
          },
        ],
      },
      {
        test: /\.(woff|jpg|png|gif|jpeg)$/,
        use: {
          loader: 'url-loader',
          options: {
            limit: 65000,
          },
        },
      },
    ],
  },
};

fonts.css

@font-face {
  font-family: "Roboto";
  src: url("../../../fonts/Roboto-Regular.woff");
  font-weight: normal;
}

button.js

const getImage = () => {
    const imageTypes = {
      positive: {
        src: require('../../../images/icons/up.png'), //eslint-disable-line
        alt: 'Positivo',
      },
      negative: {
        src: require('../../../images/icons/down.png'), //eslint-disable-line
        alt: 'Negativo3',
      },
      neutral: {
        src: 'neutral.jpg',
        alt: 'Neutro',
      },
    }

    return imageTypes[type]
  }

Extra explication

Command "start": "webpack-dev-server --mode development --open"
All paths ../../../ will only works if changed to ../.

Command "storybook": "start-storybook -p 9001",
All paths ../../../ will works.

Who to contact

@allangrds

@Hypnosphi
Copy link
Member

Hypnosphi commented Apr 1, 2018

__dirname in node is the directory of current module, in this case it's your .storybook directory. So it probably should be atoms: path.resolve(__dirname, '../src/client/atoms/') etc

@allangrds
Copy link
Author

Hi @Hypnosphi! Thanks for answering me.
So, even after changing to code posted by you, I still have the problem with the path for my css file and js - importing a image.

I need to use the same path when run command to storybook or webserver.

@allangrds allangrds changed the title Resolve alias in webpack confiG Resolve alias in webpack config Apr 2, 2018
@Hypnosphi
Copy link
Member

Hypnosphi commented Apr 2, 2018

But the whole point of adding resolve.alias is to avoid relative paths. You should be able to require('images/icons/down.png') etc

@Hypnosphi
Copy link
Member

Anyway, it's weird that you have to change the path, assuming that your files stay in same location. Can you share some minimal reproduction part of your project on GitHub so that I could debug it myself?

@allangrds
Copy link
Author

myProject/src
├── client
│   ├── App.css
│   ├── App.js
│   ├── atoms
│   │   ├── Button
│   │   │   ├── index.css
│   │   │   └── index.js
├── fonts
│   ├── Roboto-Regular.woff
├── helpers
│   ├── http.js
│   └── request.js
├── images
│   └── icons
│       ├── down.png
│       └── up.png
├── index.html
├── index.js
├── stories
│   ├── Button
│   │   ├── index.js
│   │   └── style.css
└── styles
    ├── generic
    │   ├── normalize.css
    │   └── others.css
    ├── index.css
    └── settings
        ├── colors.css
        └── fonts.css

myProject/.storybook
├── config.js
└── webpack.config.js

@Hypnosphi
Copy link
Member

Sorry, I meant in a repo. I can't debug just by folder structure

@allangrds
Copy link
Author

I solved my problem, following the code:

.storybook/webpack.config.js

const path = require('path');
const paths = require('./paths.js')
const includePath = path.resolve(__dirname, '..');

module.exports = {
  resolve: {
    alias: {
      atoms: path.resolve(__dirname, '../src/client/atoms/'),
      client: path.resolve(__dirname, '../src/client/'),
      fonts: path.resolve(__dirname, '../src/fonts/'),
      helpers: path.resolve(__dirname, '../src/helpers/'),
      images: path.resolve(__dirname, '../src/images/'),
      molecules: path.resolve(__dirname, '../src/client/molecules/'),
      stories: path.resolve(__dirname, '../src/stories/'),
      styles: path.resolve(__dirname, '../src/styles/'),
      tests: path.resolve(__dirname, '../src/tests/'),
    },
    extensions: ['.js', '.jsx', '.css', '.png', '.jpg', '.gif', '.jpeg'],
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          require.resolve('style-loader'),
          {
            loader: require.resolve('css-loader'),
            options: {
              importLoaders: 1,
              modules: 1,
              localIdentName: '[path]-[name]-[local]',
            },
          },
          {
            loader: require.resolve('postcss-loader'),
            options: {
              ident: 'postcss',
              plugins: () => [
                require('postcss-import'),
                require('postcss-cssnext')({
                  features: {
                    customProperties: false,
                  },
                }),
              ],
            },
          },
        ],
        include: paths.appSrc,
      },
      {
        test: /\.(jpg|png|gif|jpeg)$/,
        use: {
          loader: 'url-loader',
          options: {
            limit: 65000,
          },
        },
      },
      {
        test: /\.woff$/,
        use: {
          loader: 'file-loader',
          options: {
            name: '[path][name].[ext]',
            outputPath: 'fonts',
            publicPath: '../fonts',
          },
        },
      },
    ],
  },
};

path.js

const path = require('path')
const fs = require('fs')
const url = require('url')

const appDirectory = fs.realpathSync(process.cwd())
const resolveApp = relativePath => path.resolve(appDirectory, relativePath)

const envPublicUrl = process.env.PUBLIC_URL

function ensureSlash (path, needsSlash) {
  const hasSlash = path.endsWith('/')

  if (hasSlash && !needsSlash) {
    return path.substr(path, path.length - 1)
  }

  if (!hasSlash && needsSlash) {
    return `${path}/`
  }

  return path
}

const getPublicUrl = appPackageJson =>
  envPublicUrl || require(appPackageJson).homepage

function getServedPath (appPackageJson) {
  const publicUrl = getPublicUrl(appPackageJson)

  const servedUrl =
    envPublicUrl || (publicUrl ? url.parse(publicUrl).pathname : '/')
  return ensureSlash(servedUrl, true)
}

module.exports = {
  appPublic: resolveApp('public'),
  appHtml: resolveApp('public/index.html'),
  appBuild: resolveApp('public/'),
  appIndexJs: resolveApp('src/index.js'),
  appPackageJson: resolveApp('package.json'),
  appSrc: resolveApp('src'),
  yarnLockFile: resolveApp('yarn.lock'),
  appNodeModules: resolveApp('node_modules'),
  publicUrl: getPublicUrl(resolveApp('package.json')),
  servedPath: getServedPath(resolveApp('package.json')),
}

I put a file with all my paths, and use in storybook webpack config file.

@nnennajohn
Copy link

@allangrds You are awesome!!! Thank you! Searched all day for this. :)

@jdevries3133
Copy link

For anyone finding themselves here more recently, storybook no longer has a .storybook/webpack.config.js file. Instead, if you want to hook into the Webpack configuration to add your own file path alias or otherwise, you can do it as described in their documentation here

For example, I was able to bring all my project aliases into storybook quite easily like this:

// .storybook/main.js

const myProjectConfig = require("../webpack.config");

module.exports = {
  webpackFinal: (config) => {
    return {
      ...config,
      resolve: {
        ...config.resolve,
        alias: myProjectConfig.resolve.alias,
      },
    };
  },
  stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
  addons: ["@storybook/addon-links", "@storybook/addon-essentials"],
};

@shilman
Copy link
Member

shilman commented Mar 31, 2021

@jdevries3133 did this break in 6.2? We're definitely recommending the .storybook/main.js configuration, but I thought we were still supporting the .storybook/webpack.config.js configuration until 7.0. It's possible that we broke it as part of the webpack5 refactor, in which case that's a pretty serious bug. Please let me know!

@jdevries3133
Copy link

jdevries3133 commented Apr 1, 2021

@shilman The .storybook/webpack.config.js file isn't there. I didn't try adding it... it seems like extending your managed configuration was a more sensible pattern anyway.

I'm on version 6.2.1.

@stephiescastle
Copy link

stephiescastle commented Apr 1, 2021

@shilman Not sure if this is related, but previously I was able to resolve aliases in an image source. With the 6.2.1 update, this breaks, and I get <img src="[object Module]" />.

I configured my aliases in main.js:

webpackFinal: async (config, { configType }) => {
   config.resolve.alias['@'] = path.dirname(path.resolve(__dirname))
}
<img src="@/images/my-image.svg" />

Turns into:

<img src="[object Module]" />

The alias is working otherwise (able to import components using the same alias). And this was working in storybook as recently as v6.1.21

@shilman
Copy link
Member

shilman commented Apr 1, 2021

@stephiescastle do you happen to have a repro repo we can look at? we're also looking at an alias-related issue in #14423 with different symptoms

@stephiescastle
Copy link

@shilman thanks for the response, I'll set one up and get back to you.

@stephiescastle
Copy link

@shilman repro repo here:
https://github.com/stephiescastle/repro-storybook-alias

The main branch is storybook 6.2.1 with the broken image src alias.

Branch https://github.com/stephiescastle/repro-storybook-alias/tree/test/storybook-6.1.21 downgrades storybook to 6.1.21 and the image src alias works.

npm i
npm run storybook

@shamilovtim
Copy link

For anyone finding themselves here more recently, storybook no longer has a .storybook/webpack.config.js file. Instead, if you want to hook into the Webpack configuration to add your own file path alias or otherwise, you can do it as described in their documentation here

For example, I was able to bring all my project aliases into storybook quite easily like this:

// .storybook/main.js

const myProjectConfig = require("../webpack.config");

module.exports = {
  webpackFinal: (config) => {
    return {
      ...config,
      resolve: {
        ...config.resolve,
        alias: myProjectConfig.resolve.alias,
      },
    };
  },
  stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
  addons: ["@storybook/addon-links", "@storybook/addon-essentials"],
};

I think its still their own webpack config? It's just served from main.js. Not really much different from what you were already describing.

@shilman
Copy link
Member

shilman commented Apr 5, 2021

@stephiescastle thanks so much for the awesome repro. turns out it's not an alias issue but an issue with the default webpack file-loader settings! fix will be merged & released shortly.

@shilman
Copy link
Member

shilman commented Apr 5, 2021

Hurrah!! I just released https://github.com/storybookjs/storybook/releases/tag/v6.2.3 containing PR #14480 that references this issue. Upgrade today to the @latest NPM tag to try it out!

npx sb upgrade

@stephiescastle
Copy link

@shilman awesome! v6.2.3 fixes the issue for me :)

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

7 participants