Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shared bundle "missing" in 1.x #63

Closed
akx opened this issue Apr 15, 2020 · 12 comments
Closed

Shared bundle "missing" in 1.x #63

akx opened this issue Apr 15, 2020 · 12 comments
Assignees

Comments

@akx
Copy link

akx commented Apr 15, 2020

We're using a configuration like

optimization: {
    splitChunks: {
      automaticNameDelimiter: '.',
      cacheGroups: {
        shared: {
          name: 'shared',
          chunks: 'initial',
          minChunks: 2,
        },
      },
      name: true,
    },
    runtimeChunk: {
      name: 'shared',
    },
}

which has Webpack hoist shared modules and the Webpack runtime itself into a shared chunk.
In our HTML (Django templates really) we guarantee that the shared chunk appears first on every page, so everything works.

With WBT 0.x, this appeared in the chunks output e.g.

    "shared": [
      {
        "name": "6726b09177234a35303e/shared.js",
        "publicPath": "/static/webpack-bundles/6726b09177234a35303e/shared.js",
        "path": ".../static/webpack-bundles/6726b09177234a35303e/shared.js"
      }
    ],

but with WBT 1.0, it's no longer shown separately in chunks, but is included in each chunk's asset list separately, e.g.

    "dev-view": [
      "8b58fb0e109c3f0e01a9/shared.js",
      "8b58fb0e109c3f0e01a9/dev-view.js"
    ],
    "global": [
      "8b58fb0e109c3f0e01a9/shared.js",
      "8b58fb0e109c3f0e01a9/global.js"
    ],

It would be useful if shared did appear in the chunk list as its own entry.

@melck
Copy link
Contributor

melck commented Apr 18, 2020

We have change behavior for two reasons :

  • To avoid choosing order in HTML when Webpack already knows the correct order of loading.
  • To avoid handling environment specifics. Ex: When you have different settings by environment who do not produce same chunks.

With this new structure, only app chunks are shown and know loading order of assets.

I don't understand why do u need to know shared chunk in chunks section ?

If your answer make sense, we will better handle your case.

@akx
Copy link
Author

akx commented Apr 18, 2020

We have React components that are loaded into various Jinja2 templates using a template tag and the chunk's name (e.g. {{ react_component("dev-view") }}), which injects the JS tag required.
In addition, all views will have a tag to load the shared and global chunks.

If I'd just be able to know which physical file(s) made up the shared chunk (that is, if non-app chunks appeared in the output), that'd be enough, I could handle deduplicating shared/global in my code.

@melck
Copy link
Contributor

melck commented Apr 19, 2020

I think i'm missing something. If i understand well, you are using multiple template tag on same view and you want to avoid redondant loading of shared and global ?

If i understand well the case, i never used multiple app in same view. It will be better to keep old behavior and add a option for those who want to load app with deps directly.

@akx
Copy link
Author

akx commented Apr 21, 2020

I think i'm missing something. If i understand well, you are using multiple template tag on same view and you want to avoid redondant loading of shared and global ?

Yes, indeed. We have shared and global in head, and the script tags for each view are splatted into body in-place.

Right now I can't use WBT 1.x, because

  • I can't know the shared chunk's URL, since it's not listed at all
  • When rendering a particular entry point, I'd have to guess which assets I already have included in the page to filter them out (okay, granted, for this use case I just know it's the one whose name starts with shared., but still)

@mjtamlyn
Copy link

Just to mention this is a problem for me too. It's causing redundant duplicate loads of our "common" (split chunks) module. In practice it isn't the end of the world as nothing in the common chunks has side effects, but it does increase the overheads on most pages.

@fjsj
Copy link
Member

fjsj commented May 27, 2021

@akx @mjtamlyn are you using django-webpack-loader version 1.0.0?

The changes introduced by django-webpack-loader and webpack-bundle-tracker 1.x were made to accommodate the "basic" behavior of a single entrypoint per template, so the render_bundle is now used to render the entrypoint with all its chunks. How chunks are organized it's a Webpack matter.

Have you tried the dependOn option from Webpack 5? I think it enables you to separate your "shared" entrypoint: https://webpack.js.org/guides/code-splitting/#entry-dependencies

But for others reading this thread, note that's not the recommended config. Webpack docs say:

Although using multiple entry points per page is allowed in webpack, it should be avoided when possible in favor of an entry point with multiple imports

@akx
Copy link
Author

akx commented May 27, 2021

@fjsj No, we have an in-house solution to read and render the bundles – the gist of it (heh) is in this gist: https://gist.github.com/akx/9a6f2a6ce89c86819240119eea6a907e

@fjsj fjsj self-assigned this May 27, 2021
@fjsj fjsj assigned joaopslins and unassigned fjsj Jul 15, 2021
@joaopslins
Copy link
Contributor

joaopslins commented Aug 16, 2021

Hi @akx @mjtamlyn,

I'm unable to reproduce this. I'm finding the shared.js file in the assets list.
WBT version 1.2.0. webpack version: 4.46.0, and multiple entrypoints configuration.
This is my output by adding the provided optimization:

{
  "status": "done",
  "assets": {
    "shared.js": {
      "name": "shared.js",
      "path": "/home/jota/PycharmProjects/django-webpack-loader/tests/assets/django_webpack_loader_bundles/shared.js",
      "publicPath": "http://mywebsite.com/dist/shared.js"
    },
    "main.css": {
      "name": "main.css",
      "path": "/home/jota/PycharmProjects/django-webpack-loader/tests/assets/django_webpack_loader_bundles/main.css",
      "publicPath": "http://mywebsite.com/dist/main.css"
    },
    "main.js": {
      "name": "main.js",
      "path": "/home/jota/PycharmProjects/django-webpack-loader/tests/assets/django_webpack_loader_bundles/main.js",
      "publicPath": "http://mywebsite.com/dist/main.js"
    },
    "main2.js": {
      "name": "main2.js",
      "path": "/home/jota/PycharmProjects/django-webpack-loader/tests/assets/django_webpack_loader_bundles/main2.js",
      "publicPath": "http://mywebsite.com/dist/main2.js"
    }
  },
  "chunks": {
    "main": [
      "shared.js",
      "main.css",
      "main.js"
    ],
    "main2": [
      "shared.js",
      "main2.js"
    ]
  },
  "publicPath": "http://mywebsite.com/dist/"
}
    entry: { main: './assets/js/index', main2: './assets/js/index2' },
    plugins: [
        new MiniCssExtractPlugin(),
        new BundleTracker({
            path: __dirname,
            filename: './webpack-stats.json',
            publicPath: 'http://mywebsite.com/dist/'
        }),
    ],

Am I missing something? If so, would you mind to us a more complete, reproducible example, or providing more info so we are able to reproduce and understand the issue?

@melck
Copy link
Contributor

melck commented Aug 22, 2021

I'm aggre with @joaopslins, it works. I think this a concern for django-webpack-loader.

Their example i think ...

Pre 1.2 you have to declare in django code each dependencies ex:

{% extends 'layout.html' %}
{% load staticfiles %}
{% load render_bundle from webpack_loader %}

{% block cssheader %}
  {% render_bundle 'shared' 'css' %}
  {% render_bundle 'main' 'css' %}
  {% render_bundle 'main2' 'css' %}
{% endblock %}

{% block container %}
  <div class="row">
    <div id="main"></div>
  </div>
  <div class="row">
    <div id="main2"></div>
  </div>
  {% render_bundle 'shared' 'js' %}
  {% render_bundle 'main' 'js' %}
  {% render_bundle 'main2' 'js' %}
{% endblock %}

With >1.2 you only need to declare your chunk but tag for shared will be generated twice :

{% extends 'layout.html' %}
{% load staticfiles %}
{% load render_bundle from webpack_loader %}

{% block cssheader %}
  {% render_bundle 'main' 'css' %}
  {% render_bundle 'main2' 'css' %}
{% endblock %}

{% block container %}
  <div class="row">
    <div id="main"></div>
  </div>
  <div class="row">
    <div id="main2"></div>
  </div>
  {% render_bundle 'main' 'js' %}
  {% render_bundle 'main2' 'js' %}
{% endblock %}

I think we could create and fix this issue in django-webpack-loader by checkin assets already loaded in page for a template. I have made a test case in draft PR. I would try to fix it week end.

@fjsj
Copy link
Member

fjsj commented Aug 23, 2021

@melck have you tried dependOn + optimization.runtimeChunk: 'single' to create your own shared entrypoint? https://webpack.js.org/guides/code-splitting/#prevent-duplication

@melck
Copy link
Contributor

melck commented Aug 24, 2021

@fjsj No i haven't yet upgraded to webpack 5 and for my use cases, i never load more than 1 entrypoint per html page.

For me this use case shouldn't be fix, because it doesn't respect usage of webpack entrypoints. After saying that, its allowed by webpack and working, so we could at least try to warn when declaring multiple time same script in django but i don't know it it's possible. So I may close my PR without fix after trying a couple of hours.

pacahon added a commit to cscenter/site-frontend that referenced this issue Aug 25, 2021
1.x implementation of the django-webpack-loader does not support shared
bundles django-webpack/webpack-bundle-tracker#63

This reverts commit bdd4f2314ac302eeeacd2ae79a1e082e862e7c1a.
@fjsj
Copy link
Member

fjsj commented Sep 2, 2021

Closing this, as django-webpack-loader and webpack-bundle-tracker are entrypoint-based (not chunk-based) since 1.0.0 and webpack 4.

If needed, for multiple entrypoints in a single template (not recommended), chunking should be controlled by the webpack config dependOn: https://webpack.js.org/guides/code-splitting/#entry-dependencies

For the issue of multiple entrypoints in a single template generating duplicate common chunks (comments from @akx
and @mjtamlyn above), check this new open issue: django-webpack/django-webpack-loader#289

LMK if you think I understood something wrong.

@fjsj fjsj closed this as completed Sep 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants