使用 Vue Storybook 时无法编译 sass

Can't compile sass while using Vue Storybook

我正在尝试在 vue 上创建故事书。我的组件使用 sass 编写。所以,我在 .storybook/main.js:

中做了这个
webpackFinal: (config) => {
        config.module.rules.push({
            test: /\.s[ac]ss$/i,
            use: [
                // Creates `style` nodes from JS strings
                'style-loader',
                // Translates CSS into CommonJS
                'css-loader',
                // Compiles Sass to CSS
                'sass-loader',
            ],
        })

        return config
}

样式如下所示:

<style lang="sass" scoped>
button
    background-color: red
</style>

所以我在尝试编译时遇到了这个错误:

SassError: Invalid CSS after "": expected 1 selector or at-rule, was "button"
        on line 1 of C:\Code\testproj\src\components\UI\TestComponent.vue

如果我将样式更改为:

<style lang="sass" scoped>
button {
    background-color: red
}
</style>

一切正常,但这不是 sass 语法。

问题是在你的 webpack 配置中,你告诉 webpack 只有当你的文件的扩展名是 test: /.s[ac] 时才使用 sass-loader ss$/i 即.sass 或.scss。但是,您的文件的扩展名是 .vue,因为您在组件的 vue 文件中使用 sass。

使用该配置,尝试将您的 sass 样式放入 .sass 文件并检查是否有效

我遇到了完全相同的问题,但我能够解决它。问题来自 webpack 配置。如果您使用 SASS,您 .storybook 文件夹中的 webpack.config.js 文件应该如下所示:

module.exports = ({ config }) => {
  config.module.rules.push({
    test: /\.sass$/,
    use: [
      require.resolve("vue-style-loader"),
      require.resolve("css-loader"),
      {
        loader: require.resolve("sass-loader"),
        options: {
          sassOptions: {
            indentedSyntax: true
          }
        }
      }
    ],
  });

  return config;
};

如果你使用的是 SCSS,那么它应该是这样的:

module.exports = ({ config }) => {
  config.module.rules.push({
    test: /\.scss$/,
    use: [
      require.resolve("vue-style-loader"),
      require.resolve("css-loader"),
      require.resolve("sass-loader"),
    ],
  });

  return config;
};

我在阅读 Vue Loader Docs

时弄明白了这一点

对于使用 Storybook 6.4.9+ 的 React 17+ 的任何人,我遇到了类似的问题,其中 Storybook/webpack 构建不包括我的 SCSS 文件。 .storybook/main.js 中的这个配置对我有用:

module.exports = {
    "stories": [
        "../src/**/*.stories.mdx",
        "../src/**/*.stories.@(js|jsx|ts|tsx)"
    ],
    "addons": [
        "@storybook/addon-links",
        "@storybook/addon-essentials"
    ],
    "framework": "@storybook/react",
    webpackFinal: async (config) => {

        // add SCSS support for CSS Modules
        config.module.rules.push({
            test: /\.scss$/,
            use: [
                require.resolve("style-loader"),
                require.resolve("css-loader"),
                require.resolve("sass-loader"),
            ],
        });

        return config;
    }
}

我花了很多时间来寻找更好的解决方案。它可能是 main.js Storybook 6.4.9 的配置文件:

const path = require('path');

module.exports = {
  "stories": [
    "../src/**/*.stories.@(js|jsx|ts|tsx|mdx)"
  ],
  "addons": [
    "@storybook/addon-essentials",
    "@storybook/addon-actions",
    "@storybook/addon-controls",
    "@storybook/addon-links",
    {
      name: '@storybook/preset-scss',
      options: {
        sassLoaderOptions: {
          implementation: require('node-sass'), // ATTENTION: We need to use "node-sass" instead "sass/dart-sass"
          sassOptions: {
            indentedSyntax: true
          },
        },
      }
    },
    "@storybook/addon-postcss",
  ],
  "framework": "@storybook/vue",
  features: {
    babelModeV7: true,
  },
  webpackFinal: async (config, { configType }) => {
    // `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION'
    // You can change the configuration based on that.
    // 'PRODUCTION' is used when building the static version of storybook.
    
    // ATTENTION: Need to preload "global.sass" style for all elements;
    config.module.rules.map(rule => {
      if (rule.test instanceof RegExp && rule.test.toString() === '/\.s[ca]ss$/') {
        rule.use.push({
          loader: require.resolve('sass-resources-loader'),
          options: {
            resources: [
              path.resolve(__dirname, '../src/styles/global.sass')
            ]
          }
        })
      }
      return rule
    })
    
    // ATTENTION: Need to compile "Pug" templates.
    config.module.rules.push(
      {
        test: /\.pug$/,
        oneOf: [
          // this applies to `<template lang="pug">` in Vue components
          {
            resourceQuery: /^\?vue/,
            use: ['pug-plain-loader']
          },
          // this applies to pug imports inside JavaScript
          {
            use: ['raw-loader', 'pug-plain-loader']
          }
        ]
      }
    );
    
    // Return the altered config
    return config;
  },
}