Не корректная последовательность подключения файлов стилей после сборки

По наследству досталась вот такая cборка

'use strict';

const env = process.env.NODE_ENV;
const { src, path, globby, glob, fs } = require('./helper.js');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const WebpackAssetsManifest = require('webpack-assets-manifest');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const styles = path.resolve(__dirname, 'app/styles/global.scss');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const SpriteLoaderPlugin = require('svg-sprite-loader/plugin');
const svg = glob.sync('./app/images/icons/*.svg');

function generateHtmlPlugins(templateDir) {
  const templateFiles = fs.readdirSync(path.resolve(__dirname, templateDir));
  return templateFiles.map(item => {
    const parts = item.split('.');
    const name = parts[0];
    const extension = parts[1];
    return new HtmlWebpackPlugin({
      filename: `${name}.html`,
      template: path.resolve(__dirname, `${templateDir}/${name}.${extension}`),
      chunks: [`${name}`, "styles", 'headerTemplate', 'footerTemplate', 'modal', 'cartFooterTemplate', 'cartHeaderTemplate']
    });
  });
}

module.exports = async () => {
  let entry = {};
  const paths = await globby(src('./app/js/*.js'));
  const htmlPlugins = generateHtmlPlugins('app/pages/');

  paths.forEach(src => {
    entry[path.basename(src).replace(/\..*$/, '')] = src;
  });

  return {
    entry: {
      styles,
      svg,
      ...entry
    },
    output: {
      filename: '[name].bundle.js',
      path: path.resolve(__dirname, './build')
    },
    module: {
      rules: [
        {
          test: /\.js$/,
          exclude: /node_modules\/(?!(dom7|ssr-window|swiper)\/).*/,
          loader: 'babel-loader'
        },
        {
          enforce: 'pre',
          test: /\.(js|vue)$/,
          exclude: /node_modules/,
          loader: 'eslint-loader',
          options: {
            fix: true,
            quiet: true,
            formatter: require('eslint-formatter-pretty')
          }
        },
        {
          test: /\.vue$/,
          loader: 'vue-loader',
          options: {
            loaders: {
              scss: ['vue-style-loader', 'css-loader', 'postcss-loader']
            }
          }
        },
        {
          test: /\.(css|scss)$/,
          use: [
            {
              loader: MiniCssExtractPlugin.loader,
              options: {
                options: {
                  url: false
                }
              }
            },
            {
              loader: 'css-loader',
              options: {
                url: false,
                sourceMap: true
              }
            },
            {
              loader: 'postcss-loader',
              options: {
                sourceMap: true
              }
            },
            {
              loader: 'sass-loader',
              options: {
                sourceMap: true
              }
            },
            {
              loader: 'sass-resources-loader',
              options: {
                resources: [
                  path.resolve(__dirname, 'app/styles/helpers/variables.scss'),
                  path.resolve(__dirname, 'app/styles/helpers/mixins.scss')
                ]
              }
            }
          ]
        },
        {
          test: /\.(png|jpe?g|gif|woff|woff2?)$/,
          exclude: path.resolve(__dirname, 'app/images/icons'),
          use: [
            {
              loader: 'file-loader',
              options: {
                esModule: false,
                name: '[name].[ext]'
              }
            }
          ]
        },
        {
          test: /\.svg$/,
          use: [
            {
              loader: 'svg-sprite-loader',
              options: {
                extract: true,
                publicPath: 'images/',
                spriteFilename: 'sprite.svg'
              }
            },
            {
              loader: 'svgo-loader',
              options: {
                plugins: [
                  { removeTitle: true }
                  // {
                  //   removeAttrs: {
                  //     attrs: "(fill|stroke)"
                  //   }
                  // }
                ]
              }
            }
          ]
        }
      ]
    },
    devServer: {
      writeToDisk: true,
      historyApiFallback: true,
      noInfo: false,
      overlay: true,
      port: 9000
    },

    /**
     * @doc https://github.com/webpack/webpack/tree/master/examples/common-chunk-and-vendor-chunk
     */
    optimization: {
      runtimeChunk: 'single',
      splitChunks: {
        chunks: 'all',
        maxInitialRequests: Infinity,
        minSize: 0,
        cacheGroups: {
          // Собираем все зависимости в один чанк - vendor.bundle.js
          vendor: {
            test: /node_modules/,
            chunks: 'initial',
            name: 'vendor',
            enforce: true
          }
        }
      }
    },
    performance: {
      hints: false
    },
    /**
     * @doc https://webpack.js.org/configuration/resolve/#resolvealias
     */
    resolve: {
      alias: {
        vue$:
          env === 'development' ? 'vue/dist/vue.esm.js' : 'vue/dist/vue.min.js',
        '@': path.resolve(__dirname, 'app/js'),
        '@components': path.resolve(__dirname, 'app/js/vue/components'),
        '@helpers': path.resolve(__dirname, 'app/js/helpers'),
        '@images': path.resolve(__dirname, 'app/images'),
        '@vue': path.resolve(__dirname, 'app/js/vue')
      }
    },
    plugins: [
      /**
       * отвечает за клонирование любых других правил, которые вы определили,
       * чтобы применить их к соответствующим языковым блокам в файлах .vue.
       */
      new VueLoaderPlugin(),
      /**
       * @doc https://habr.com/ru/post/423693/
       * @doc https://www.npmjs.com/package/webpack-assets-manifest
       */
      new WebpackAssetsManifest({
        entrypoints: true,
        transform: assets => assets.entrypoints
      }),
      new MiniCssExtractPlugin({
        filename: '[name].css?id=[contenthash]',
        chunkFilename: '[name].css?id=[contenthash]'
      }),
      new CopyWebpackPlugin({
        patterns: [
          {
            from: 'app/images',
            globOptions: {
              ignore: path.resolve(__dirname, 'app/images/icons')
            },
            to: 'images'
          },
          {
            from: 'app/fonts',
            to: 'fonts'
          }
        ]
      }),
      new SpriteLoaderPlugin({ plainSprite: true })
    ].concat(htmlPlugins),
    devtool: env === 'development' ? '#eval-source-map' : ''
  };
};

Зависимости

"devDependencies": {
    "@babel/core": "^7.10.4",
    "@babel/plugin-proposal-class-properties": "^7.10.4",
    "@babel/plugin-transform-runtime": "^7.10.4",
    "@babel/preset-env": "^7.10.4",
    "acorn": "^6.4.1",
    "acorn-dynamic-import": "^4.0.0",
    "autoprefixer": "^9.8.6",
    "babel-eslint": "^10.1.0",
    "babel-loader": "^8.1.0",
    "babel-plugin-component": "^1.1.1",
    "copy-webpack-plugin": "^6.1.0",
    "cross-env": "^5.2.1",
    "css-loader": "^1.0.0",
    "element-ui": "^2.13.2",
    "eslint": "^5.16.0",
    "eslint-config-prettier": "^4.3.0",
    "eslint-formatter-pretty": "^2.1.1",
    "eslint-loader": "^2.2.1",
    "eslint-plugin-prettier": "^3.1.4",
    "eslint-plugin-vue": "^4.7.1",
    "file-loader": "^6.1.0",
    "fs": "0.0.1-security",
    "html-webpack-plugin": "^4.4.1",
    "husky": "^4.2.5",
    "lint-staged": "^10.2.11",
    "lodash": "^4.17.19",
    "mini-css-extract-plugin": "^0.9.0",
    "node-sass": "^4.14.1",
    "optimize-css-assets-webpack-plugin": "^5.0.3",
    "path": "^0.12.7",
    "postcss-loader": "^4.0.2",
    "prettier": "^1.19.1",
    "prettier-eslint": "^9.0.2",
    "sass-loader": "^8.0.2",
    "sass-resources-loader": "^2.0.3",
    "stylelint": "^13.6.1",
    "stylelint-config-sass-guidelines": "^6.2.0",
    "stylelint-order": "^3.1.1",
    "stylelint-scss": "^3.18.0",
    "svg-sprite-loader": "^5.0.0",
    "svgo-loader": "^2.2.1",
    "vinyl-fs": "^3.0.3",
    "vue-eslint-parser": "^6.0.5",
    "vue-loader": "^15.9.3",
    "vue-modal-dialogs": "^3.0.0",
    "vue-template-compiler": "^2.6.11",
    "webpack": "^4.43.0",
    "webpack-assets-manifest": "^3.1.1",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0"
}

На тестовом сервере через pm2 запускается dev-server для автоматической сборки, вот с такими параметрами

webpack-dev-server.js --mode production --public test.dev.ru:80 --host 127.0.0.1 --port 3037 --publicPath '/build/'

В таком случае последовательность подключения стилей корректная, первым идет файл /build/vendor.css за ним /build/styles.css.

Если же запускаю сборку руками

"build": "rm -rf build && webpack --mode=production --progress"

то последовательность этих двух файлов меняется и дефолтные стили из vendor.css начинают перебивать нужные из styles.css.
Понимаю, что можно просто задать стилям большую специфичность и привести отображение к нужному виду, но хотелось бы разобраться, из-за чего меняется последовательность подключения при такой сборке и можно ли на это как-то повлиять.


Ответы (0 шт):