Не корректная последовательность подключения файлов стилей после сборки
По наследству досталась вот такая 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.
Понимаю, что можно просто задать стилям большую специфичность и привести отображение к нужному виду, но хотелось бы разобраться, из-за чего меняется последовательность подключения при такой сборке и можно ли на это как-то повлиять.