webpack-contrib/mini-css-extract-plugin

CSS file is not emitted on incremental rebuild in watch mode

pshurygin opened this issue ยท 16 comments

Using mini-css-extract-plugin 0.2.0 with webpack 4.1.0 with this config and -watch option:

module: {
	rules: [
		{
			test: /\.css$/,
			use: [
				MiniCssExtractPlugin.loader,
				{ loader: 'css-loader', options: { url: false, sourceMap: true } }
			]
		},
		{
			test: /\.scss$/,
			use: [
				MiniCssExtractPlugin.loader,
				{ loader: 'css-loader', options: { url: false, sourceMap: true } },
				{ loader: 'sass-loader', options: { sourceMap: true } }
			]
		}
	]
}

Initial build works fine and outputs css bundle as expected. Whenever i change my scss file, an incremental rebuild is triggered and this changed scss file is clearly shown in the console output, but somehow the emitted css bundle is not changed from the initial build. If i rerun the build from scratch, the changes are correctly propagated to filesystem. Here is an output after incremental rebuild.

>  0% compiling
>  10% building modules 4/4 modules 0 active
>  10% building modules 5/6 modules 1 active ...s\solo-showcase-columns-widget.scss 0
>  10% building modules 7/7 modules 0 active
>  10% building modules 11/11 modules 0 active
>  10% building modules 12/13 modules 1 active ...ures\content-bank\content-bank.scss 0
>  10% building modules 18/18 modules 0 active
>  10% building modules 19/20 modules 1 active ...nd\vendor\custom\sortable\sortable.js
>  11% building modules 27/28 modules 1 active ...nd\vendor\custom\sortable\sortable.js
>  11% building modules 32/33 modules 1 active ...nd\vendor\custom\sortable\sortable.js
>  11% building modules 33/34 modules 1 active ...nd\vendor\custom\sortable\sortable.js
>  11% building modules 44/46 modules 2 active ...tend\features\balance\invoices.scss 0
>  11% building modules 45/47 modules 2 active ...\features\balance\transactions.scss 0
>  12% building modules 46/47 modules 1 active ...nd\vendor\custom\sortable\sortable.js
>  12% building modules 48/49 modules 1 active ...nd\vendor\custom\sortable\sortable.js
>  12% building modules 49/50 modules 1 active ...nd\vendor\custom\sortable\sortable.js
>  12% building modules 49/51 modules 2 active ...works\wizard\step-goal\goal-step.scss
>  12% building modules 61/63 modules 2 active ...works\wizard\step-goal\goal-step.scss
>  12% building modules 67/69 modules 2 active ...works\wizard\step-goal\goal-step.scss
>  13% building modules 79/82 modules 3 active ...wizard\step-budget\budget-step.scss 0
>  13% building modules 82/85 modules 3 active ...udience-popup\persist-audience.scss 0
>  13% building modules 84/86 modules 2 active ...works\wizard\step-goal\goal-step.scss
>  14% building modules 96/99 modules 3 active ...nents\file-input\sm-file-input.scss 0
>  14% building modules 97/99 modules 2 active ...works\wizard\step-goal\goal-step.scss
>  14% building modules 109/111 modules 2 active ...works\wizard\step-goal\goal-step.scss
>  14% building modules 111/114 modules 3 active ...d\vendor\custom\introjs\introjs.css 0
>  14% building modules 112/114 modules 2 active ...works\wizard\step-goal\goal-step.scss
>  14% building modules 113/114 modules 1 active ...works\wizard\step-goal\goal-step.scss
>  70% finish module graph FlagDependencyExportsPlugin
>  70% sealing WarnCaseSensitiveModulesPlugin
>  72% after dependencies optimization
>  75% basic chunk optimization RemoveParentModulesPlugin
>  76% advanced chunk optimization SplitChunksPlugin
>  75% basic chunk optimization RemoveParentModulesPlugin
>  84% module id optimization
>  86% after chunk id optimization
>  88% hashing
>  90% additional chunk assets processing
>  95% emitting unnamed compat plugin
> Hash: bf05be2f878f02734bcc
> Version: webpack 4.1.0
> Time: 478ms
> Built at: 2018-3-7 18:16:56
>      Asset     Size  Chunks             Chunk Names
>    en.json  150 KiB          [emitted]  
>    es.json  157 KiB          [emitted]  
>    ru.json  156 KiB          [emitted]  
> pt-BR.json  158 KiB          [emitted]  
>  + 38 hidden assets
> Entrypoint solomoto [big] = runtime.js vendor.css vendor.js solomoto.css solomoto.js
> Entrypoint showcase [big] = runtime.js vendor.css vendor.js showcase.css showcase.js
> Entrypoint showcase-wysiwyg = runtime.js showcase-wysiwyg.css showcase-wysiwyg.js
> Entrypoint registration [big] = runtime.js vendor.css vendor.js registration.css registration.js
> Entrypoint admin-panel [big] = runtime.js vendor.css vendor.js vendor-admin.js admin-panel.css admin-panel.js
> Entrypoint content-panel [big] = runtime.js vendor.css vendor.js vendor-admin.js content-panel.css content-panel.js
> [./Frontend/features/media/social-networks/wizard/step-goal/goal-step.scss] 39 bytes {solomoto} [built]
> [./Frontend/vendor/custom/sortable/sortable.js] 36 KiB {vendor} [built]
>     + 1378 hidden modules
> Child mini-css-extract-plugin node_modules/css-loader/index.js??ref--7-1!node_modules/sass-loader/lib/loader.js??ref--7-2!Frontend/features/media/social-networks/wizard/step-goal/goal-step.scss:
>     Entrypoint mini-css-extract-plugin = *
>     [./node_modules/css-loader/index.js??ref--7-1!./node_modules/sass-loader/lib/loader.js??ref--7-2!./Frontend/features/media/social-networks/wizard/step-goal/goal-step.scss] ./node_modules/css-loader??ref--7-1!./node_modules/sass-loader/lib/loader.js??ref--7-2!./Frontend/features/media/social-networks/wizard/step-goal/goal-step.scss 23.9 KiB {mini-css-extract-plugin} [built]
>         + 1 hidden module
krtr commented

same happens with webpack-serve

Also I can confirm that it doesn't work for incremental builds.

acoll commented

I dug into this a little bit over the weekend so hopefully this is helpful in someway.

I noticed the same issue mentioned above but if I pass along a hash here then I can get it to re-emit the css file. However, the new output isn't the correct updated output, just the same file but rewritten(updated timestamp). I tried to trace through webpack to get an idea of whats supposed to be happening and somewhere around here it ends up replacing the new module with the cached version. I am pretty new to the inner workings of webpack so I'm not sure if that is intended.

Anyways, still digging...

Hopefully @sokra got an idea.

Playing with hashes doesn't help either. This issue makes watch mode development completely impossible...

Same problem here. Get's really annoying as I have to restart the whole webpack process every single time I change a single line in CSS. Can't imagine being the only one having this problem as I'm using a pretty standard webpack config.

Please don't post here unless you have something new to share. Otherwise other people following this issue will get email spam for no real and useful reason.

It would be good to give a thumbs up for other commenters if you face a similar situation etc.

:-)

@manuelbieh looking on this now ๐Ÿ˜ƒ@piehei yeah ๐Ÿ‘

As dirty hack for now disabling cache in config will trick the plugin to alter the extracted css file

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
  // disabling cache in watch mode 
  cache: false,
  plugins: [
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: "[name].css",
      chunkFilename: "[id].css"
    })
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader"
        ]
      }
    ]
  }
}

@manuelbieh As an alternative workaround, I'm using style-loader for the time being. See webpack.config.js below. Css does not get extracted into a separate external file, but does get referenced in the html file like <link type="text/css" rel="stylesheet" href="blob:file:///253efbed-2c8a-4d59-ae25-1833e8f8bfbb">

Not sure if it makes a difference, but I'm targeting Electron...

webpack.config.js

[...stuff deleted...]
'rules': [
    {
        test: /\.scss$/,
        use: [
            // {
            //     loader: MiniCssExtractPlugin.loader,
            // },
            {
                loader: 'style-loader',
                options: {
                    sourceMap: true,
                },
            },
            {
                loader: 'css-loader',
                options: {
                    sourceMap: true,
                },
            },
            {
                loader: 'postcss-loader',
                options: {
                    sourceMap: true,
                    plugins: (loader) => [
                        require('precss')(),
                        require('autoprefixer')()
                    ]
                }
            },
            {
                loader: "sass-loader",
                options: {
                    sourceMap: true,
                    includePaths: [
                        path.resolve(__dirname, '../src/app/assets/sass'),
                        path.resolve(__dirname, '../node_modules/bootstrap/scss'),
                    ]
                }
            }
        ]
    }
],
'plugins': [
    new HtmlWebpackPlugin({ template: 'src/index.html' }),
]
[... stuff deleted...]

Will use ExtractTextWebpackPlugin until this is fixed. Not really happy about that but at least it seems to work for me for the time being. Thanks for your help! ๐Ÿ™‚

If someone addresses this issue, it would be nice if there would be a hook that is called when the CSS changes. That way you can send a message to the browser that it needs to reload the CSS. See also webpack-contrib/extract-text-webpack-plugin#577

Looks like it is fixed with webpack 4.4.1 + mini-css-extract-plugin 0.4.0. Thanks!

This is not the same issue but I'm having the problem with webpack v4.6.0, mini-css-extract-plugin v0.4.0, and hard-source-webpack-plugin v0.6.4, that if CSS is unchanged between builds then no CSS file is generated. To be clear these are subsequent builds not rebuilds using compiler.watch or Webpack Dev Server.

I put together an example repo here. If you run the webpack task twice, i.e. yarn start then stop the process then yarn start you will see the extracted CSS file is not generated on the 2nd try.

https://github.com/dtothefp/hard-cache-mini-css-webpack-4

And there is already an issue thread started 29 days ago that doesn't seem to have generated much response

mzgoddard/hard-source-webpack-plugin#301

Problem reappeared with:

"webpack": "4.26.1",
"webpack-cli": "3.1.2",
"mini-css-extract-plugin": "0.4.5"

When changing CSS files all files are generated. It happens only if I change JS files and at first with the second "watched change". Then only JS files are generated.

Webpack output then is:

Hash: a9be440b8c0da1ac733f
Version: webpack 4.26.1
Time: 62ms
Built at: 11/30/2018 9:25:37 PM
             Asset     Size  Chunks             Chunk Names
    myentry_dfc3e2.js  232 KiB    myentry  [emitted]  myentry
myentry_dfc3e2.js.map  240 KiB    myentry  [emitted]  myentry
[ !!! HERE THE CSS FILES ARE MISSING !!! ]
 + 2 hidden assets
Entrypoint myentry = myentry_9b74a3.css myentry_dfc3e2.js myentry_9b74a3.css.map myentry_dfc3e2.js.map
[./frontend-src/js/MyChangedFile.js] 4.3 KiB {myentry} [built]
    + 31 hidden modules

Simplified webpack.config.js:

const SOURCE_DIR = './frontend-src';
const DIST_DIR = './frontend-dist';
const ENTRY_BASE_NAME = '[name]_[contenthash:6]';

module.exports = {
  entry: {
    "myentry": `${SOURCE_DIR}/js/index.js`,
  },
  output: {
    filename: `${ENTRY_BASE_NAME}.js`,
    path: path.resolve(__dirname, DIST_DIR),
    publicPath: '../static/'
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader
          },

          {
            loader: "css-loader",
            options: {
              sourceMap: true,
              modules: true,
              localIdentName: "[local]"
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: `${ENTRY_BASE_NAME}.css`
    })
  ],
  mode: 'development'
};

Any other information I should give?

BTW: cache: false still is usefull as a workaround here.