storybookjs / storybook

Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation
https://storybook.js.org
MIT License
84.53k stars 9.3k forks source link

Error importing styles.scss to storybook #5684

Closed codestitch closed 5 years ago

codestitch commented 5 years ago

The bug I followed this tutorial in starting storybook. Though the tutorial is using less, I decided to use scss.

When I import my styles.scss into the config.js in .storybook with this configuration in webpack.config.js

const path = require("path");

module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        loaders: ["style-loader", "css-loader", "sass-loader"],
        include: path.resolve(__dirname, "../")
      }
    ]
  }
};

as per https://storybook.js.org/configurations/custom-webpack-config/, it gives me an error.

If I try to change the webpack.config.js to this solution: it doesn't do anything.

Reproduce Steps to reproduce the behavior:

  1. Go to https://www.learnstorybook.com/angular/en/get-started/ and use sass styling.
  2. Continue through https://www.learnstorybook.com/angular/en/simple-component/
  3. Upon setting config.js instead of styles.less use styles.scss
  4. Upon setting webpack.config.js use this config instead:
const path = require("path");

module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        loaders: ["style-loader", "css-loader", "sass-loader"],
        include: path.resolve(__dirname, "../")
      }
    ]
  }
};

from official tutorial.

And then install node-sass.

Then run npm run storybook.

Expected behavior I should be able to see styles from whatever is in styles.scss

Screenshots error1

Code snippets package.json

"dependencies": {
    "@angular/animations": "~7.2.0",
    "@angular/common": "~7.2.0",
    "@angular/compiler": "~7.2.0",
    "@angular/core": "~7.2.0",
    "@angular/forms": "~7.2.0",
    "@angular/platform-browser": "~7.2.0",
    "@angular/platform-browser-dynamic": "~7.2.0",
    "@angular/router": "~7.2.0",
    "core-js": "^2.5.4",
    "node-sass": "^4.11.0",
    "rxjs": "~6.3.3",
    "tslib": "^1.9.0",
    "zone.js": "~0.8.26"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.13.0",
    "@angular/cli": "~7.3.2",
    "@angular/compiler-cli": "~7.2.0",
    "@angular/language-service": "~7.2.0",
    "@types/node": "~8.9.4",
    "@types/jasmine": "~2.8.8",
    "@types/jasminewd2": "~2.0.3",
    "codelyzer": "~4.5.0",
    "jasmine-core": "~2.99.1",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~3.1.1",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "~2.0.1",
    "karma-jasmine": "~1.1.2",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.4.0",
    "ts-node": "~7.0.0",
    "tslint": "~5.11.0",
    "typescript": "~3.2.2",
    "@babel/core": "^7.3.3",
    "babel-loader": "^8.0.5",
    "@storybook/angular": "^4.1.12",
    "@storybook/addon-notes": "^4.1.12",
    "@storybook/addon-actions": "^4.1.12",
    "@storybook/addon-links": "^4.1.12",
    "@storybook/addons": "^4.1.12"
  }

config.js

import { configure } from '@storybook/angular';

import '../src/styles.scss';

// automatically import all files ending in *.stories.ts
const req = require.context('../src/stories', true, /.stories.ts$/);
function loadStories() {
  req.keys().forEach(filename => req(filename));
}

configure(loadStories, module);

webpack.config.js

const path = require("path");

module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        loaders: ["style-loader", "css-loader", "sass-loader"],
        include: path.resolve(__dirname, "../")
      }
    ]
  }
};

System:

Source Code HERE.

tourniquet commented 5 years ago
const path = require("path");

module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [
          {
            loader: "style-loader"
          },
          {
            loader: "css-loader"
          },
          {
            loader: "sass-loader",
            options: {
              javascriptEnabled: true
            }
          }
        ],
        include: path.resolve(__dirname, "../")
      }
    ]
  }
};

Try this solution, it worked for me, the only difference is I used this configuration for LESS.

shilman commented 5 years ago

cc @tmeasday

tmeasday commented 5 years ago

@codestitch -- what is the content of button.component.scss? Can you upload your code somewhere?

codestitch commented 5 years ago

Hi, @tourniquet, less is fine. As I stated in my problem less has no problem. only when I call .scss files from config.js. And it didn't work.

codestitch commented 5 years ago

Hi, @tmeasday. There's no style for button.component.scss... I am making my styles in the global such as styles.scss outside of app folder. That's why I'm trying to import styles.scss in config.js coz importing styles.less works in config.js. Or there could be another way of importing styles.scss other than in config.js.

tmeasday commented 5 years ago

Hi @codestitch - but the error above looks like you are importing that file - and it looks like a JS file?

codestitch commented 5 years ago

yes @tmeasday ... it's saying that there is an error in button.component.scss file, but there are not styling in that file... that's what perplexed me. When I use this sass-loader in webpack.config.js, i'm having that error.

module.exports = {
    module: {
      rules: [{
        test: /\.scss$/,
        loaders: ["style-loader", "css-loader", "sass-loader"],
        include: path.resolve(__dirname, "../")
      }]
    }
  };

but if i'm using a less loader in webpack.config.js, it's just ok.

the only place i'm importing styling is in config.js

tmeasday commented 5 years ago

@codestitch as a guess I'd say that by adding the above rule, your webpack config is now treating .scss files as SASS files rather than default (which is to load them with file-loader which I think just dumps their contents into a string). So if you have import ./button.component.scss which contains JS it'd explain that error.

codestitch commented 5 years ago

this is the structure of my button.component capture

The button.component.scss files doesn't contain anything.. this is the project.

tmeasday commented 5 years ago

Oh, you know what, this could be a problem with file loader, maybe. I don't think you need to do this any more with SB5 but previously I think I had a similar issue with svgs that I avoided with:

 // in .storybook/webpack.config.js
 const fileLoader = storybookBaseConfig.module.rules.find(
   r => r.loader && r.loader.match('file-loader')
 );
 fileLoader.exclude = /\.svg/;

Try that with /\.scss/ and see if it helps?

codestitch commented 5 years ago

I tried it but gave me an error.

capture

codestitch commented 5 years ago

is there a way of adding a global style in all the stories?

tmeasday commented 5 years ago

Sorry, storybookBaseConfig was the first argument to the function exported by webpack.config.js in SB4.

tmeasday commented 5 years ago

is there a way of adding a global style in all the stories?

You can do it like this: https://storybook.js.org/docs/configurations/add-custom-head-tags/

codestitch commented 5 years ago

is there a way of adding a global style in all the stories?

You can do it like this: https://storybook.js.org/docs/configurations/add-custom-head-tags/

Thanks, @tmeasday. But how do I include my own styles from the project, like styles.css inside /stories folder?

tourniquet commented 5 years ago

At the top of my .storybook/config.js I added:

  import "antd/dist/antd.less"

I think you can import your styles in the same way. PS: The only way this works is to add at the very top of the file, in the first line

codestitch commented 5 years ago

My bad. I looked at the iframe and the style are already there. Sorry for wasting your time @tmeasday .

So, this code import '!style-loader!css-loader!../stories/styles.scss'; works in config.js instead of import "../stories/styles.scss"; or require('../stories/styles.scss');!

but the webpack.config.js example in the documentation really doesn't work.

Thanks a lot.

codestitch commented 5 years ago

Another question though, @tmeasday. I'm using NX and has multiples apps and each app is using different UI library. App1 is using bootstrap and clarity and app2 is using clarity and app3 is using angular material. Now, What I notice is that SB looks at the 1st app's styles in angular.json w/c is App1 so it has two styles bootstrap and clarity.

Is there a way to control where SB will look to get what style, say i only want SB to have base style of clarity? coz' SB just automatically loads the styles used in App1.

Thanks.

tmeasday commented 5 years ago

Hey @codestitch you probably just need to carefully consider the import chain -- if your storybook imports a story, which itself imports a component which imports a style file, that style file will end up in the storyboook.

If the component imports a library which imports a ... etc etc -- so you just need to figure out how the bootstrap files are getting imported.

tmeasday commented 5 years ago

I guess I am going to close this as the issue has been resolved?

albertjke commented 5 years ago

I tried it but gave me an error.

capture

Hey @codestitch, sorry to bother you - I'm having the same issue, but it's not super clear to me how you ended up resolving it. Did you find a way to resolve this error?

codestitch commented 5 years ago

Sure @albertjke. You can check my repo at https://github.com/codestitch/sbnx.

it's using version 5.0.6 though. What I did there is I added this line:

import '!style-loader!css-loader!../stories/stories.scss';

to config.js file.

PS. When running npm run storybook you will encounter an error as I purposely do that for some issue. you can remove the ListComponent in the story to view the working one.

magisters-cc commented 5 years ago

@codestitch little fix for scss (sass-loader):

import '!style-loader!css-loader!sass-loader!../styles/main.scss'; 

to config.js file. Work for me with HMR.

shiftgeist commented 5 years ago

@magisters-org

import '!style-loader!css-loader!sass-loader!../styles/main.scss';

This works but it outputs:

DeprecationWarning: Extend-mode configuration is deprecated, please use full-control mode instead.

See https://storybook.js.org/docs/configurations/custom-webpack-config/#full-control-mode

Here is another solution I found, because I got Invalid CSS after "": expected 1 selector or at-rule: https://github.com/storybookjs/storybook/issues/6467#issuecomment-481425563 (fix for the full-control example here)

shilman commented 5 years ago

@shiftgeist here's more about the deprecation https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#Deprecate-webpack-extend-mode

jaydeep987 commented 4 years ago

@codestitch little fix for scss (sass-loader):

import '!style-loader!css-loader!sass-loader!../styles/main.scss'; 

to config.js file. Work for me with HMR.

this works fine for local scss files, but not working for importing scss files from node_modules. any idea ?

popthestack commented 4 years ago

@jaydeep987

this works fine for local scss files, but not working for importing scss files from node_modules. any idea ?

I'm having this same issue. Have you found any workarounds?

AlexanderMelox commented 4 years ago

Same here :(

B3Kay commented 4 years ago

I got this problem to with typescript project.

popthestack commented 4 years ago

I solved this by removing the !style-loader!css-loader!sass-loader! from the scss import in my preview.js. This allowed the scss to be imported with the defined webpack loaders.

caseytrombley commented 4 years ago

My bad. I looked at the iframe and the style are already there. Sorry for wasting your time @tmeasday .

So, this code import '!style-loader!css-loader!../stories/styles.scss'; works in config.js instead of import "../stories/styles.scss"; or require('../stories/styles.scss');!

but the webpack.config.js example in the documentation really doesn't work.

Thanks a lot.

This doesn't work: ERR! import '!style-loader!css-loader!../styles/core.scss'; ERR! ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ERR! ERR! SyntaxError: Unexpected string

nirus commented 4 years ago

I had a difficult time using custom config. Logged the https://github.com/storybookjs/storybook/issues/11052

Solved it!

As a work around i mutated the config object to inject common scss. For more explaination & implementation checkout the blog i wrote on this topic.

tobystokes commented 3 years ago

To universally @import Sass styles, including from node_modules, something like this in your webpackFinal in main.js:

config.module.rules.push(
  {
    test: /\.scss$/,
    use: [
      {
            loader: "sass-loader",
            options: {
              implementation: require("sass"),
              prependData: '@import "./css/lib";', // add our scss variables etc any components
              sassOptions: {
                includePaths: ["./node_modules"] // resolve paths
              }
        }
  }
);

(n.b. exact sass-loader options vary, this is sass-loader@8, webpack@5)

AlexHoisan commented 3 years ago

@tobystokes I lost a lot of time trying to figure this out, and after a lot of trial and error, I came accross your answer here. Nice one. It saved me a lot of headache.

angelod1as commented 1 year ago

@nirus, whenever you have a solution, post it on the thread; otherwise, people like me need to necro it and say: your link is not working.