Webpack, images disappear after browser refresh, using webpack-dev-server

Viewed 273

I've got a problem with my Webpack config. After tag had been written, the image appears, but devServer remove all the pictures after styles applications right after page reload. And it wouldn't back until path was added again in tag. See this screenshot video to have a better image of what is happening.

webpack.config.js:

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

let mode = 'development'
let target = 'web'
if (process.env.NODE_ENV === 'production') {
  mode = 'production'
  target = 'browserslist'
}

const plugins = [
  new HtmlWebpackPlugin({
    template: './index.html',
  }),
  new MiniCssExtractPlugin({
    filename: '[name].[contenthash].css',
  }),
]

module.exports = {
  mode,
  plugins,
  target,
  context: path.resolve(__dirname, 'src'),
  entry: {
    main: './main.js',
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    assetModuleFilename: 'assets/[hash][ext][query]',
    clean: true,
  },
  optimization: {
    splitChunks: {
      chunks: 'all',
    },
  },
  devServer: {
    static: {
      directory: path.join(__dirname, 'src'),
    },
    compress: true,
    open: true,
    hot: true,
    port: 3001,
  },
  resolve: {
    extensions: ['.js', '.ts', '.jsx', '.tsx'],
  },
  module: {
    rules: [
      {
        test: /\.(html)$/,
        use: ['html-loader'],
      },
      {
        test: /\.(s[ac]|c)ss$/i,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
      },
      {
        test: /\.(png|jpe?g|gif|svg|webp|ico)$/i,
        type: mode === 'production' ? 'asset' : 'asset/resource',
      },
      {
        test: /\.(woff2?|eot|ttf|otf)$/i,
        type: 'asset/resource',
      },
      {
        test: /\.(js|jsx)?$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            cacheDirectory: true,
          },
        },
      },
      {
        test: /\.(ts|tsx)?$/,
        exclude: /node_modules/,
        use: {
          loader: 'ts-loader',
        },
      },
    ],
  },
}
2 Answers

I had a similar issue - I noticed that changing output.clean = false in the webpack.dev.js file resolve the issue when output.path was null.

The answer selected above worked for me as well.

New answer

As @Bryce said in his answer having clean:false inside output entry of webpack.config.js solves the issue (no need for the path to be null though). But it rises another one, a dist folder crowded with hashed CSS and JavaScript files. What I did is to set it only for development mode, like so:

output: {
  // ...
  clean: process.env.NODE_ENV === "production" ,
},

And added an environment variable only for build in my package.json, like so:

"scripts": {
    "start": "webpack serve --open",
    "build": "NODE_ENV=production webpack"
}

Old answer

I have the same issue. I realised that images that are imported in JavaScript files with import works fine. The problem is coming from images in HTML files, processed with html-loader. I searched a lot, didn't find why this is happening, but here a way to avoid the issue:

Every time you add a new image, stop your development server, run npm run build to build your project, and then run npm start. And after that it would work fine.

Regarding CSS changes, the problem is solved for me after upgrading my webpack-dev-server version from v3.11.2 to v4.9.1. Though when I change a TypeScript file (I'm compiling TypeScript to JavaScript), the problem remains, and the above solution is still valid.

If yo do that version migration, depending on your previous version, there may be some changes to be made to devServer entry. See the doc if you have errors.

Related