django-webpack-loader icon indicating copy to clipboard operation
django-webpack-loader copied to clipboard

Exception in Loader.filter_chunks due to wrong webpack-stats.json data format

Open fabiocapsouza opened this issue 3 years ago • 1 comments

I'm updating a project to Django 4 and after updating both django-webpack-loader and webpack-bundle-tracker to 1.6.0 (migrating from v0.6.0), the render_bundle tag is failing with a TypeError exception when loading CSS files.

https://github.com/django-webpack/django-webpack-loader/blob/b9ac29763d02b7c9a56729d7a9c77ec84b78e492/webpack_loader/loader.py#L54-L63

In filter_chunks, chunk is expected to be a string but in my case it is a dict, so it raises TypeError when performing regex.match(chunk). In my case, chunks is:

>>> chunks
[{'name': 'main.js', 'path': '/home/fabio/neuralmind/eliot/eliot/case_analysis/static/case_analysis/dist/main.js'}]

The webpack-stats.json content is:

{
  "status": "done",
  "chunks": {
    "main": [
      {
        "name": "main.js",
        "path": "/home/fabio/neuralmind/eliot/eliot/case_analysis/static/case_analysis/dist/main.js"
      }
    ]
  }
}

My configs are:

webpack version: 4.46.0

Django template tag:

{% render_bundle 'main' 'css' %}

webpack.config.js:

const path = require('path');
const BundleTracker = require('webpack-bundle-tracker');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  mode: 'production',
  entry: path.resolve(__dirname, './js-src/index'),

  output: {
    path: path.resolve(
      __dirname,
      './eliot/case_analysis/static/case_analysis/dist'
    ),
    filename: 'main.js',
  },

  plugins: [
    new CleanWebpackPlugin(), //clean dist folder before building new files
    new BundleTracker({
      path: path.resolve(path.join(__dirname, './eliot')),
      filename: 'webpack-stats.json',
    }),
  ],
  resolve: {
    alias: {
      nm: path.resolve(__dirname, 'node_modules'),
    },
    modules: [
      path.resolve(__dirname, 'js-src'),
      path.resolve(__dirname, 'node_modules'),
    ],
  },
  resolveLoader: {
    modules: [path.resolve(__dirname, 'node_modules')],
  },

  module: {
    rules: [
      {
        test: /\.jsx?$/,
        loader: 'babel-loader',
        options: {
          presets: [
            path.resolve(__dirname, 'node_modules', '@babel/preset-react'),
          ],
        },

        exclude: /node_modules/,
      },
    ],
  },
};

settings.py:

WEBPACK_LOADER = {
    'DEFAULT': {
        'BUNDLE_DIR_NAME': 'dist/',
        'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
    }
}

I searched through READMEs and issues in both repositories but could not solve this issue, so any help will be appreciated.

Thanks in advance

fabiocapsouza avatar Jul 11 '22 18:07 fabiocapsouza

I'm having the same issue although I'm upgrading to Django 3.2 from 3.1. I bumped the version from 0.7.0 to 1.6.0 and I'm getting the same error. Hopefully, we'll have something soon so we can upgrade. Thanks!

ronilrufo-domain avatar Aug 23 '22 13:08 ronilrufo-domain

+1 to this issue. It seems to be related to the fact that the new version of webpack-bundle-tracker puts both the CSS and JS in the same array under one dictionary heading, as opposed to before where it was only one per. Hopefully it gets fixed soon, I'm moving to 1.5.0 for the time being and hoping for the best!

EDIT: No luck on that, went all the way back to 1.1.0, still nothing. I am now attempting to include the filetype in the chunk name so that there is only one thing per chunk name.

Starmism avatar Sep 23 '22 11:09 Starmism

Hi folks, sorry to hear about this issue.

I've tried to reproduce this behavior on my end, unfortunately I wasn't able to come across this issue on my attempts. I've used both django-webpack-loader==1.6.0 and [email protected].

One thing I've noticed in the provided webpack-stats.json file

{
  "status": "done",
  "chunks": {
    "main": [
      {
        "name": "main.js",
        "path": "/home/fabio/neuralmind/eliot/eliot/case_analysis/static/case_analysis/dist/main.js"
      }
    ]
  }
}

is that the outer JSON only contains chunks and status as its keys, when the expected format for the stats file outputted by [email protected] should be similar to

{
  "status": "done",
  "assets": {
    "i-1561b91d7b75f3ca28145ff2b1a79802.png": {
      "name": "i-1561b91d7b75f3ca28145ff2b1a79802.png",
      "path": "/app/frontend/bundles/i-1561b91d7b75f3ca28145ff2b1a79802.png"
    },
    "i-4c677b78d12c96ea7adde99ce24d8172.png": {
      "name": "i-4c677b78d12c96ea7adde99ce24d8172.png",
      "path": "/app/frontend/bundles/i-4c677b78d12c96ea7adde99ce24d8172.png"
    },
    "main.js": {
      "name": "main.js",
      "path": "/app/frontend/bundles/main.js"
    },
    "vendors~main.js": {
      "name": "vendors~main.js",
      "path": "/app/frontend/bundles/vendors~main.js"
    }
  },
  "chunks": {
    "main": [
      "vendors~main.js",
      "main.js"
    ]
  }
}

with the outer JSON containing chunks, status and also assets. One thing to notice is that assets on the file I've obtained is similar to chunks on the provided file. If I recall correctly, that used to be the case in a previous version of webpack-bundle-tracker, but was changed in favor of the new approach in a version prior to 1.6.0.

I've also did some investigations on webpack-bundle-tracker to try pinpointing a section of the code that could be producing an incorrect stats file, but also couldn't identify it (for completeness, here is the section that produces the output content https://github.com/django-webpack/webpack-bundle-tracker/blob/master/lib/index.js#L146-L178).

I'll continue to investigate that behavior. In the meantime, could you double-check if both versions are running on 1.6.0 and, if possible, ensure that the stats file is being generated with the latest version(i.e.: delete any old stats file and ensure it's a new one being produced).

rvlb avatar Sep 30 '22 20:09 rvlb

It looks like this change https://github.com/django-webpack/django-webpack-loader/blame/master/webpack_loader/loader.py#L58 turned chunk["name"] into chunk so that it was passing a dict into regex.match(). This error is affecting me with django-webpack-loader==1.6.0 and [email protected].

When I switched to use 1.6.0 for both libraries, it started working correctly.

Jdsleppy avatar Oct 06 '22 19:10 Jdsleppy

Thanks for reporting back @Jdsleppy Since version 1.0.0, both projects must always match versions in order to work correctly. Therefore, if one uses django-webpack-loader==1.6.0, they must use [email protected]. Even if something changes in only one side, we'll make a new release on the other.

I'll close this issue for now. If anyone is still facing the issue after correcting the versions, please let me know by commenting here and mentioning me. (cc @Starmism @ronilrufo-domain @fabiocapsouza)

fjsj avatar Oct 06 '22 20:10 fjsj