Различия стилей в Webpack Dev и Prod - PullRequest
0 голосов
/ 28 августа 2018

Краткое резюме:

Я заметил, что есть небольшие несоответствия стилей между моими конфигурациями dev / prod в веб-пакете при локальном тестировании. Похоже, это связано с загрузчиком sass, но может ли он выйти за пределы этого? Я не могу быть уверен, потому что это очень трудно отследить ошибку.

(код внизу, изображения только для выделения определенных элементов)

Подсказка

Большинство стилей, которые отсутствуют в dev или перезаписаны, взяты из моего файла Sass. Поэтому я предполагаю, что виновник где-то скрыт в том, как я обрабатываю файлы Sass в prod.config.js по сравнению с dev.config.js. В частности, я заметил, что переменные в Sass, такие как $ main-font, не интерпретируются в dev, но выглядят нормально в конфигурации prod. Я также заметил несколько странных переопределений, когда dev может применить границу из набора классов, а производство - нет. Возможно, Minicssextract делает что-то другое для prod?

Проблема

На рисунке ниже слева - моя производственная конфигурация. Как вы можете видеть, он извлекает текст в файл CSS, который называется index.html. Он загружает мои переменные SCSS просто отлично. Справа я не использую minicssextractloader, и все мои стили помещаются в теги и внедряются. Он переключает семейство шрифтов на то, что я нигде не определил в своем коде?

enter image description here

Погрузчик

Слева - dev, справа - sass. enter image description here

Вот как этот шрифт определяется в Sass: enter image description here

Идеи и тесты:

  • Style-loader: я попытался удалить postcss, sass-loader и style-loader в dev из теста scss. Похоже, не решить проблему.
  • Есть ли шанс, что веб-пакет делает что-то необычное между режимами разработки / производства?
  • Возможно, мое сжатие CSS на Prod делает вещи странными?

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;
}
...