Skip to content
This repository has been archived by the owner on Feb 1, 2020. It is now read-only.

Contenthash with MiniCssExtractPlugin does not change even if content has changed #65

Open
arneee opened this issue Jan 2, 2019 · 2 comments

Comments

@arneee
Copy link

arneee commented Jan 2, 2019

I'm using the contenthash in the filenames to allow long term caching:
https://webpack.js.org/guides/caching/

Unfortunately if the content is changed by the PurgeCss plugin only, for example since I have removed a usage of an class or I'm using a class which hasn't been used before, the contenthash does not change. This leads to old files being served to the users and therefore a breaking app.

The content hash changes as soon as I do an actual modification of the CSS files. My guess would be that the contenthash is calculated to early?

webpack config:

const path = require('path');
const glob = require('glob-all')
const ManifestPlugin = require('webpack-manifest-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CleanWebpackPlugin = require('clean-webpack-plugin'); //installed via npm
const PurgecssPlugin = require('purgecss-webpack-plugin');
const webpack = require('webpack');

// the path(s) that should be cleaned
let pathsToClean = [
    'dist'
];

// the clean options to use
let cleanOptions = {
    root:     '..................../public',
    verbose:  true,
    dry:      false
};

function collectWhitelistPatterns() {
    return [/^pcr-/];
}

module.exports = {

    plugins: [
        new CleanWebpackPlugin(pathsToClean, cleanOptions),
        new ManifestPlugin(),
        new PurgecssPlugin({
            paths: glob.sync(['./src-js/**/*', './templates/**/*'],  { nodir: true }),
            whitelistPatterns: collectWhitelistPatterns,
        }),
        new MiniCssExtractPlugin({
            filename: "[name]-[contenthash].css",
            chunkFilename: "[id]-[contenthash].css"
        }),
        new webpack.ProvidePlugin({
            $: 'jquery',
            jQuery: 'jquery'
        })
    ],

    entry: {
        one: './src-js/index-one.js',
        two: './src-js/index-two.js',
        three: './src-js/index-three.js',
    },

    output: {
        path: path.resolve(__dirname, 'public/dist'),
        filename: dev?'[name]-min.js':'[name]-[contenthash]-min.js',
        publicPath: "/dist/"
    },

    module: {
        rules: [
            {
                test: /\.m?js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        "presets": [
                            [
                                "@babel/preset-env",
                                {
                                    "useBuiltIns": "entry",
                                    "targets": "> 0.25%, not dead",
                                }
                            ]
                        ],
                        "plugins": ["transform-remove-console"]
                    }
                }
            },
            {
                test: /\.(sa|sc|c)ss$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'sass-loader',
                ],
            },
            {
                test: /\.(png|svg|jpg|gif)$/,
                use: [
                    'file-loader'
                ]
            }
        ]
    },
    externals: {
        jquery: 'jQuery'
    },
};
@iancwoodward
Copy link

Simply adding a comment to a stylesheet seems to be kicking off the re-hashing process. I'm just adding a comment like: /* cache increment = 1000 */

Not the best solution since it would be preferable not to have to think about it.

@SkaterDad
Copy link

SkaterDad commented Feb 17, 2019

@arneee I just ran into this same problem today. Had to purge my Cloudflare cache to get an update to download after nearly an hour of troubleshooting. Putting immutable on your cache-control headers is fun when the hashes aren't working correctly...

My solution was to stop using this Webpack plugin, and move PurgeCSS to my postcss.config.js file instead (via @fullhuman/postcss-purgecss.

// postcss.config.js
/* eslint-env node */
const DEV = process.env.NODE_ENV !== 'production'

class TailwindExtractor {
  static extract(content) {
    return content.match(/[A-z0-9-:\/]+/g) || []
  }
}

module.exports = {
  plugins: [
    require('tailwindcss')('./tailwind.js'),
    DEV
      ? false
      : require('@fullhuman/postcss-purgecss')({
          content: ['./src/**/*.{js,ejs,html}'],
          extractors: [
            {
              extractor: TailwindExtractor,
              // Specify the file extensions to include when scanning for
              // class names.
              extensions: ['html', 'js', 'ejs', 'vue'],
            },
          ],
        }),
    require('autoprefixer'),
  ].filter(Boolean),
}

Webpack module config:

      {
        test: /\.css$/,
        use: [
          { loader: 'style-loader' },
          {
            loader: 'css-loader',
            options: { importLoaders: 1 },
          },
          { loader: 'postcss-loader' },
        ],
      },

Hope this helps someone!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants