为什么 ExtractTextPlugin 通过插件创建一个空的 css 文件?为什么 sass 加载程序在使用 Webpack 导入时提供空对象?

Why does ExtractTextPlugin create an empty css file via the plugin? Why is the sass loader providing empty objects when imported with Webpack?

我已将 webpack 配置为使用 ExtractTextPlugin 从 sass 生成单个 css 文件,并允许它通过 webpack 加载程序导入在 reactjs 应用程序中可用。

通过 react 组件中的 import 语句检测到 sass 文件的使用,并且正在生成输出文件,但是生成的 main.css 文件是空的,导入正在返回一个空样式对象,有谁知道我做错了什么?

结构

client
  - app
    - components
      - navbar
        Navbar.js
        navbar.scss
  - public
    - styles
      main.scss
    bundle.js
    index.html

Webpack 配置

const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

const BUILD_DIR = path.resolve(__dirname, 'public');
const APP_DIR = path.resolve(__dirname, 'app');

const config = {
   entry: APP_DIR + '/index.js',
   output: {
     path: BUILD_DIR,
     filename: 'bundle.js'
  },
  externals: {
    'cheerio': 'window',
    'react/lib/ExecutionEnvironment': true,
    'react/lib/ReactContext': true,
  },
  module : {
    loaders : [
      {
        test : /\.jsx?/,
        include : APP_DIR,
        loader : 'babel'
      },
      {
        test: /\.scss$/,
        include : APP_DIR,
        loader: ExtractTextPlugin.extract('css!sass')
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'My App'
    }),
    new ExtractTextPlugin('styles/main.css', {
      allChunks: true
    })
  ]
};

module.exports = config;

navbar.scss

.navbar {
  display: flex;

  .navbarBrand {

  }
}

Navbar.js

import React, { Component, PropTypes } from 'react'
import classnames from 'classnames'
import Login from '../login/Login'
import Logout from '../logout/Logout'
import styles from './navbar.scss';


export default class Navbar extends Component {

  render() {
    const { isAuthenticated, errors, onLogin, onLogout } = this.props;

    console.log(styles);
    const navBarStyles = classnames(styles.navbar);
    const navBarBrandStyles = classnames(styles.navbarBrand);

    return (
        <nav className={navBarStyles}>
          <div className='container-fluid'>
            <a className={navBarBrandStyles} href="#">User Management App</a>
            <div className='navbar-form'>

              {!isAuthenticated &&
                <Login
                    errors={errors}
                    onLoginClick={ (creds) => onLogin(creds) }
                />
              }

              {isAuthenticated &&
                <Logout onLogoutClick={() => onLogout()} />
              }

            </div>
          </div>
        </nav>
    )
  }
}

Navbar.propTypes = {
  isAuthenticated: PropTypes.bool.isRequired,
  errors: PropTypes.arrayOf(PropTypes.string),
  onLogin: PropTypes.func.isRequired,
  onLogout: PropTypes.func.isRequired
};

症状

加载程序和导入程序(不再是问题,请参阅下面的答案)

  1. console.log(样式)=对象{}

  2. styles.navbar = 未定义

插件

  1. public/styles/main.css 为空 (不再是问题,请参考下面的答案)

问题

  1. 为什么在 Narbar.js 中导入样式时样式为空对象?我配置错了什么? (我找到了解决方案并在下面的答案部分提供了答案)
  2. 为什么 public/style/main.css 是空的? (我找到了解决方案并在下面的答案部分提供了答案)
  1. 至于空文件,这是我在我的一个项目中使用这个插件的方式: ( Webpack@2.2, ExtractTextPlugin v2 )

插件实例化

const extractSCSS = new ExtractTextPlugin({
    filename: "[name].scss",
    allChunks: true
});

装载机

{
    test: /\.(css|scss)$/,
    loader: extractSCSS.extract({
        loader: [
            {
                loader: "css-loader",
                options: { modules: true }
            },
            {
                loader: "sass"
            }
        ],
        defaultLoader: "style-loader"
    })
}

插件

plugins: [extractSCSS],

你可以在这个 project

中查看我从中采样的完整 Webpack 配置

sass-loader 固定。

关键是为 css-loader 添加 modules=true,然后您可以从 scss 文件导入样式。

{
            test: /\.scss$/,
            loader: extractCSS.extract('style', 'css?modules=true!sass?sourceMap=true')
          }

public/style/main.css 固定。

老实说,我不确定有什么区别,但 public/styles/main.css 文件现在已填充。

我所做的唯一更改是 webpack 配置。

const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

const BUILD_DIR = path.resolve(__dirname, 'public');
const APP_DIR = path.resolve(__dirname, 'app');

let generateHtml = new HtmlWebpackPlugin({ title: 'My App' });
let extractCSS = new ExtractTextPlugin('styles/[name].css', { allChunks: true });

const config = {
  entry: APP_DIR + '/index.js',
  output: {
    path: BUILD_DIR,
    filename: 'bundle.js'
  },
  externals: {
    'cheerio': 'window',
    'react/lib/ExecutionEnvironment': true,
    'react/lib/ReactContext': true,
  },
  module : {
    loaders : [
      {
        test : /\.jsx?/,
        include : APP_DIR,
        loader : 'babel'
      },
      {
        test: /\.scss$/,
        loader: extractCSS.extract('style', 'css?modules=true!sass?sourceMap=true')
      }
    ]
  },
  plugins: [
    generateHtml,
    extractCSS
  ]
};

module.exports = config;