Webpack Dev与Prod的样式差异

时间:2018-08-28 04:37:37

标签: css webpack sass mini-css-extract-plugin

简短摘要:

我注意到在本地测试时,webpack的dev / prod配置之间在样式上存在细微的差异。似乎与sass-loader有关,但它可能会扩展到其他范围之外吗?我不确定,因为很难找到该错误。

(底部代码,图像仅用于突出显示某些元素)

线索

开发人员缺少或覆盖的大多数样式都来自我的Sass文件。因此,我想象罪魁祸首埋在prod.config.js与dev.config.js上如何处理Sass文件的地方。具体来说,我注意到Sass中的变量(例如$ main-font)未在dev上解释,但在prod config上似乎还可以。我还注意到,在开发人员可能从一组类中应用了边界的情况下,发生了一些奇怪的替代,但是生产却没有。也许Minicssextract在为产品做一些不同的事情?

问题

在下图中,左侧是我的生产配置。如您所见,它将文本提取到CSS文件中,该文件在index.html中称为。它正在加载我的SCSS变量就好了。在右边,我不使用minicssextractloader,我所有的样式都放入标签中并注入。是否将字体系列切换到我的代码中未定义的任何地方?

enter image description here

装载程序

左边是dev,右边是Sass的产品。 enter image description here

以下是在Sass中定义此字体的方式: enter image description here

想法和测试:

  • 样式加载器:我尝试从scss测试中删除dev上的postcss,sass-loader和style-loader。似乎没有解决问题。
  • webpack是否有可能在开发/生产模式之间做一些时髦的事情?
  • 也许我对pros的css压缩使事情变得奇怪了?

Dev.config

const webpack = require('webpack');
const path = require('path');
const fs = require('fs');
require('babel-polyfill').default;

const PATHS = {
  app: path.join(__dirname, '../src'),
  build: path.join(__dirname, '../dist'),
};

module.exports = {
  devtool: 'cheap-module-eval-source-map',
  entry: ['webpack-hot-middleware/client', './src/index'],
  mode: 'development',

  output: {
    publicPath: '/dist/',
    filename: 'bundle.js',
  },

  resolve: {
    extensions: ['.jsx', '.js', '.json', '.scss', '.less'],
    modules: ['node_modules', PATHS.app],
  },

  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
      },
      {
        test: /\.css$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
            },
          },
          'postcss-loader',
        ],
      },
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              importLoaders: 2,
            },
          },
          'postcss-loader',
          'sass-loader',
        ],
      },
      {
        test: /\.less$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              importLoaders: 2,
            },
          },
          'postcss-loader',
          'less-loader',
          },
        ],
      },
      {
        test: /bootstrap-sass\/assets\/javascripts\//,
        use: [
          {
            loader: 'imports-loader',
            options: {
              jQuery: 'jquery',
            },
          },
        ],
      },
      {
        test: require.resolve('jquery'),
        use: [
          {
            loader: 'expose-loader',
            options: '$',
          },
          {
            loader: 'expose-loader',
            options: 'jQuery',
          },
        ],
      },
      {
        test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 50000,
              mimetype: 'application/font-woff',
            },
          },
        ],
      },
      {
        test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10000,
              mimetype: 'application/octet-stream',
            },
          },
        ],
      },
      {
        test: /\.otf(\?v=\d+\.\d+\.\d+)?$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10000,
              mimetype: 'application/font-otf',
            },
          },
        ],
      },
      {
        test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
        use: [
          {
            loader: 'file-loader',
          },
        ],
      },
      {
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10000,
              mimetype: 'image/svg+xml',
            },
          },
        ],
      },
      {
        test: /\.png$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[ext]',
            },
          },
        ],
      },
      {
        test: /\.jpg$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[ext]',
            },
          },
        ],
      },
      {
        test: /\.ico$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[ext]',
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"development"',
      },
      __DEVELOPMENT__: true,
    }),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.ProvidePlugin({
      jQuery: 'jquery',
    }),
  ],
};

Prod.config

const webpack = require('webpack');
const path = require('path');
const fs = require('fs');
require('babel-polyfill').default;

// const PurifyCSSPlugin = require('purifycss-webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const StatsPlugin = require('stats-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const cssnano = require('cssnano');

const PATHS = {
  app: path.join(__dirname, '../src'),
  build: path.join(__dirname, '../dist'),
};

const pathsToClean = [
  '../dist/*.{js,css,eot,woff,woff2,svg,ttf,jpg,map}',
  '../dist/index.html',
];

const cleanOptions = {
  root: PATHS.build,
  exclude: [
    'sitemap.xml',
  ],
  dry: false,
};

module.exports = {
  // devtool: 'source-map',
  entry: ['./src/index'],
  mode: 'production',

  output: {
    publicPath: '/dist/',
    chunkFilename: '[name].[chunkhash:4].js',
    filename: '[name].[chunkhash:4].js',
  },

  resolve: {
    extensions: ['.jsx', '.js', '.json', '.scss', '.less'],
    modules: ['node_modules', PATHS.app],
  },

  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
      },
      {
        test: /\.css$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
            },
          },
          'postcss-loader',
        ],
      },
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
          },
          {
            loader: 'css-loader',
            options: {
              importLoaders: 2,
            },
          },
          'postcss-loader',
          'sass-loader',
        ],
      },
      {
        test: /\.less$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
          },
          {
            loader: 'css-loader',
            options: {
              importLoaders: 2,
            },
          },
          'postcss-loader',
          'less-loader',
          },
        ],
      },
      {
        test: /bootstrap-sass\/assets\/javascripts\//,
        use: [
          {
            loader: 'imports-loader',
            options: {
              jQuery: 'jquery',
            },
          },
        ],
      },
      {
        test: require.resolve('jquery'),
        use: [
          {
            loader: 'expose-loader',
            options: '$',
          },
          {
            loader: 'expose-loader',
            options: 'jQuery',
          },
        ],
      },
      {
        test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
        // test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 50000,
              mimetype: 'application/font-woff',
            },
          },
        ],
      },
      {
        test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10000,
              mimetype: 'application/octet-stream',
            },
          },
        ],
      },
      {
        test: /\.otf(\?v=\d+\.\d+\.\d+)?$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10000,
              mimetype: 'application/font-otf',
            },
          },
        ],
      },
      {
        test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
        use: [
          {
            loader: 'file-loader',
          },
        ],
      },
      {
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10000,
              mimetype: 'image/svg+xml',
            },
          },
        ],
      },
      {
        test: /\.png$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[ext]',
            },
          },
        ],
      },
      {
        test: /\.jpg$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[ext]',
            },
          },
        ],
      },
      {
        test: /\.ico$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[ext]',
            },
          },
        ],
      },
    ],
  },

  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"',
      },
      __DEVELOPMENT__: false,
    }),
    new CleanWebpackPlugin(pathsToClean, cleanOptions),
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash:4].css',
    }),
    new OptimizeCSSAssetsPlugin({
      cssProcessor: cssnano,
      cssProcessorOptions: {
        options: {
          discardComments: {
            removeAll: true,
          },
          // Run cssnano in safe mode to avoid
          // potentially unsafe transformations.
          safe: true,
        },
      },
      canPrint: false,
    }),
    new StatsPlugin('stats.json', {
      chunkModules: true,
      exclude: [/node_modules[\\/]react/],
    }),
    // new PurifyCSSPlugin({
    //   paths: glob.sync(PATHS.app),
    // }),
  ],

  optimization: {
    minimizer: [
      new UglifyJsPlugin({
        sourceMap: true,
      }),
    ],
    splitChunks: {
      cacheGroups: {
        commons: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendor',
          chunks: 'initial',
        },
      },
    },
    runtimeChunk: {
      name: 'manifest',
    },
  },
};

一些Sass似乎有麻烦吗?

/** 03. Typography **/

$font-source: 'Source Sans Pro', 'Helvetica', 'Arial', sans-serif; 


body {
  font-size: 1em;
  line-height: 1.85em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-family: $font-source;
  color: $color-secondary;
  font-weight: 400;
}

1 个答案:

答案 0 :(得分:0)

在调查我遇到类似问题的原因时发现了这个旧问题。

就我而言,sass 文件中有 iffy css(设置为百分比而不是小数的不透明度值)

Dev 解决了这个问题,但 prod 没有。我仍然不确定为什么除了“prod 更严格”之外 - 但纠正 css 语法使它在 prod 上工作(当然)