0

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

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

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

现在,我不确定这些插件如何在后台工作,但我想 csso-webpack-plugin 正在解析所有文件,然后将结果添加到包中,然后提取到 styles.css,而不是解析样式.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}}
4

2 回答 2

1

CssoWebpackPlugin将处理已经提取的包,根本不需要 csso-loader

对于重组,您应该将CssoWebpackPlugin inside pluginssection 应用到您的 webpack 配置中,例如 — 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}}
于 2017-08-25T13:41:49.413 回答
0

由于我的问题的解决方案并不是对所有情况都是安全的解决方案,但无论如何我都需要它,我尝试寻找不同的解决方案,并首先在提取的样式上使用 group-media-queries-plugin 找到了一个解决方案。首先使用 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"}
于 2017-08-25T18:31:31.100 回答