I'm getting this problem of duplicated css files under dist/css
My webpack configuration is as follows:
webpack.base.config.js
/* eslint quote-props: ['off'] */
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const isProduction = process.env.NODE_ENV === 'production';
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
const createLintingRule = () => ({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
})
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/entry.client.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'@': resolve('src'),
'$': resolve('node_modules'),
'i18n': resolve('i18n'),
'@fortawesome/fontawesome-free-solid$': '@fortawesome/fontawesome-free-solid/shakable.es.js',
'@fortawesome/fontawesome-free-regular$': '@fortawesome/fontawesome-free-regular/shakable.es.js',
'@fortawesome/fontawesome-free-brand$': '@fortawesome/fontawesome-free-brand/shakable.es.js',
}
},
module: {
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.s?[ac]ss$/,
use: [
!isProduction ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader',
],
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('i18n'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /^(?!.*-inline).*\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /.*(?:\.(gif|png|jpe?g)|(-inline\.svg))$/i,
use: [
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: true,
quality: 65
},
// optipng.enabled: false will disable optipng
optipng: {
enabled: false,
},
pngquant: {
quality: '65-90',
speed: 4
},
gifsicle: {
interlaced: false,
},
},
}
]
},
{
test: /-inline\.svg$/,
loader: 'svg-inline-loader',
options: {
removeSVGTagAttrs: false,
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
{
test: /\.(graphql|gql)$/,
exclude: /node_modules/,
loader: 'graphql-tag/loader',
}
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}
And webpack.prod.config.js
const webpackConfig = merge(baseWebpackConfig, {
mode: 'production',
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: "vendor",
chunks: "all"
},
},
},
concatenateModules: true,
minimizer: [
new UglifyJsPlugin({
uglifyOptions: {
compress: {
dead_code: true,
drop_console: true,
},
output: {
comments: false,
},
ecma: 6,
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
new OptimizeCSSAssetsPlugin({}),
],
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new CleanPlugin([dist], {
root: path.resolve(__dirname, '..'),
}),
new VueLoaderPlugin(),
new Dotenv({
path: path.resolve('.env')
}),
new MiniCssExtractPlugin({
filename: utils.assetsPath('css/[name].[hash].css'),
chunkFilename: utils.assetsPath('css/[id].[hash].css')
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: process.env.NODE_ENV === 'testing'
? 'index.html'
: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode(a, b) {
return (a.names[0] < b.names[0]) ? 1 : -1;
},
}),
// Generates manifest to configure pwa options
new WebpackPwaManifest({
name: 'My Company',
short_name: 'MyCompany',
description: 'Vue + Vuetify progressive app with Loopback server',
theme_color: "#004d40",
start_url: "./",
background_color: "#fafafa",
icons: [
{
"src": path.resolve('src/assets/logo.png'),
"sizes": "200x200",
"type": "image/png"
},
{
"src": path.resolve('src/assets/logo-512px.png'),
"sizes": "512x512",
"type": "image/png"
},
]
}),
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// copy custom static assets
new WorkboxPlugin.GenerateSW({
swDest: path.join(config.build.assetsRoot, 'sw.js'),
clientsClaim: true,
skipWaiting: true,
exclude: [/\.html$/],
}),
new HtmlCriticalPlugin({
base: path.resolve(__dirname, '../dist'),
src: 'index.html',
dest: 'index.html',
inline: true,
minify: true,
extract: true,
width: 375,
height: 565,
penthouse: {
blockJSRequests: false,
}
})
]
})
// This option is enabled by default, if nginx or another server already implement
// gzip you can disable it in config/index.js
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
if (config.build.productionBrotli) {
const BrotliWebpackPlugin = require('brotli-webpack-plugin');
webpackConfig.plugins.push(
new BrotliWebpackPlugin({
asset: '[path].br[query]',
test: new RegExp(
'\\.(' +
config.build.productionBrotliExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig
I checked the contents of both files and one is compressed by OptimizeCSSAssetsPlugin and the other is not.
I also want to ask why this css chunks doesn't have the brotli and gziped version.
Thanks