webpack中的CSSO + ExtractTextPlugin不重构提取的页面

时间:2017-08-24 20:25:05

标签: webpack webpack-2 extract-text-plugin csso

我正在尝试为我的反应项目创建一个脚手架,并在此过程中学习webpack。我一直在尝试将我的css模块化在他们自己的组件文件夹中,并将它们解压缩到build文件夹中的一个styles.css文件中。

问题在于,在每个模块化.css文件中,我都有媒体查询,有时它们在相同宽度断点的特定规则方面重叠。这会在我提取的styles.css文件中产生一堆重复的@media all和(min-width:400px)-esque语句。

所以为了解决这个问题,我发现这个csso插件似乎在他们的在线工具中起到了作用。它将所有重复的@media语句合并(通过重组)到一个并将不同的规则放在那里。问题是,在我的项目中,只有当重复的@media语句来自同一个文件时才会这样做(这不应该发生)。如果它们来自不同的文件(这是我试图解决的问题),它们就不会合并。

现在,我不确定这些插件是如何在后台运行的,但我想csso-webpack-plugin正在解析所有文件,然后将结果添加到bundle中,然后提取到styles.css进行,而不是直接解析styles.css。谁能想到这个问题的解决方案?

我的生产配置如下:

const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const CssoWebpackPlugin = require('csso-webpack-plugin').default;

module.exports = {
  entry: {
    app: './src/index.js'
  },
  module:{
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: [
            'css-loader',
            'csso-loader'
          ]
        })
      }
    ]
  },
  plugins:[
    new CleanWebpackPlugin(['build']),
    new HtmlWebPackPlugin(),
    new ExtractTextPlugin('styles.css'),
    new webpack.optimize.UglifyJsPlugin({
      beautify: false,
      mangle: {
        screw_ie8: true,
        keep_fnames: true
      },
      compress: {
        screw_ie8: true
      },
      comments: false
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks(module){
        var context = module.context;
        return context && (context.indexOf('node_modules') > 0);
      }
    })
  ],
  output: {
    filename: '[name].bundle.min.js',
    path: path.resolve(__dirname, 'build')
  }
} 

我的index.css看起来像这样:

@media all and (max-width: 100px){
  .lorelei{
    font-size: 50px;
  }
}

我的App.css:

@media all and (max-width: 100px){
  .loboto{
    font-size: 30px;
  }
}


@media all and (max-width: 100px){
  .jonas{
    font-size: 30px;
  }
}

结果styles.css

@media all and (max-width:100px){.lorelei{font-size:50px}}@media all and (max-width:100px){.jonas,.loboto{font-size:30px}}

2 个答案:

答案 0 :(得分:1)

CssoWebpackPlugin 将处理已提取的捆绑包,不需要 csso-loader

对于重组,您应该将plugins部分中的 CssoWebpackPlugin 应用到您的网络包配置中,例如 - new CssoWebpackPlugin()

部分规则:

{
    test: /\.css$/,
    use: ExtractTextPlugin.extract({
    fallback: 'style-loader',
    use: 'css-loader'
}

部分插件:

plugins: [
    /* ... */
    new ExtractTextPlugin('styles.css'),
    new CssoWebpackPlugin(), // <==== it's very important!
    /* ... */
]

您的完整配置应如下所示:

const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const CssoWebpackPlugin = require('csso-webpack-plugin').default;

module.exports = {
  entry: {
    app: './src/index.js'
  },
  module:{
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: 'css-loader'
        })
      }
    ]
  },
  plugins:[
    new CleanWebpackPlugin(['build']),
    new HtmlWebPackPlugin(),
    new ExtractTextPlugin('styles.css'),
    new CssoWebpackPlugin(),
    new webpack.optimize.UglifyJsPlugin({
      beautify: false,
      mangle: {
        screw_ie8: true,
        keep_fnames: true
      },
      compress: {
        screw_ie8: true
      },
      comments: false
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks(module){
        var context = module.context;
        return context && (context.indexOf('node_modules') > 0);
      }
    })
  ],
  output: {
    filename: '[name].bundle.min.js',
    path: path.resolve(__dirname, 'build')
  }
}

之后,更改结果将合并良好:

@media all and (max-width:100px){.lorelei{font-size:50px}.jonas,.loboto{font-size:30px}}

答案 1 :(得分:0)

由于我的问题的解决方案不是所有情况下的安全解决方案,但无论如何这是我需要的东西,我尝试寻找不同的解决方案,并首先使用group-media-queries-plugin找到一个首先提取styles.css文件,然后使用csso缩小结果。我发现它是一个CLI插件,所以我最终通过npm脚本使用它和CSSO CLI。

我的npm脚本最终变得相当冗长,但它完成了工作:

  "scripts": { "build:prod": "webpack --env=prod --progress --profile --colors && group-css-media-queries ./build/styles.css ./build/styles.css && csso ./build/styles.css ./build/styles.min.css"}