Skip to content

Conversation

@alihazemfarouk
Copy link

@alihazemfarouk alihazemfarouk commented Nov 18, 2018

render_entrypoint tag renders all chunks related to an entrypoint. This allows us to make use of Webpack 4 code splitting functionality.

The corresponding PR for webpack-bundle-tracker (necessary for this feature to work) can be found here

@alihazemfarouk alihazemfarouk changed the title WIP: render_entrypoint tag render_entrypoint tag Nov 21, 2018
@owais
Copy link
Collaborator

owais commented Nov 23, 2018

@alihazemfarouk Thanks for the PR. I'll review in detail but I haven't used webpack 4 yet so I'll likely have some questions. For starters, what is the difference between render_bundle and render_entrypoint ? From webpack's perspective, we used to define entrypoints in v2 and still define entrypoints in v4 so why the extra function in webpack-loader?

@alihazemfarouk
Copy link
Author

alihazemfarouk commented Nov 23, 2018

@owais Webpack 4 introduced a feature called "Code Splitting", where essentially for every entry it traces its dependencies and optimizes the bundles it outputs for maximum efficiency (least amount of code to be shipped). The problem with render_bundle is that what it does is just that, it renders a bundle, so we're unable to efficiently use the new Code Splitting webpack feature because we wouldn't know the names of the bundles webpack is going to produce, for example if react is used in entry 'a' webpack would most likely (depending on the configuration of course) generate a "node_vendors~a.bundle.js" file containg react (and other depencies used by entry a), but then if react is used in entry 'b', webpack optimizations would likely to output 1 bundle for those common dependencies for both entry a and b and the file name will look something like this "node_vendors~a~b.bundle.js"
What render_entrypoint does is that reads the output of how webpack optimized and then produced the bundles for each entry, and renders all the bundles required by that entry. For a clearer explanation on webpack 4 code splitting please check out this medium article

@persocon
Copy link

persocon commented Dec 3, 2018

👍

@greggb
Copy link

greggb commented Dec 12, 2018

@owais Really appreciate you keeping this project alive. Is there anything you need to help move some of these PRs along? Webpack has changed dramatically over the last year and this PR would be a huge help for those of us making use of code splitting.

@alihazemfarouk
Copy link
Author

@owais Anything I can help with to move things along for this PR?

@alihazemfarouk
Copy link
Author

alihazemfarouk commented Jan 9, 2019

Ok so to be able to use this feature, I published this PR on pypi and npm, under the names of 'django-webpack4-loader' and 'webpack4-bundle-tracker'.
You can find the documentation for the new feature in the readme on my github fork, if anyone would like to use it.

@owais If at any point you review this PR and would like me to do some modifications before merging, if you think the PR is fine and ready to merge and you would like to merge it, inform me and I will delete the 2 packages I published in order not to be redundant.

@owais
Copy link
Collaborator

owais commented Jan 9, 2019

@alihazemfarouk Thanks for helping out. I've been really busy with work. Will try to reserve some time to review it next week. Sorry for the delay. Using forked packages sounds good till this is merged.

@persocon
Copy link

@owais any news on this? 🙏

@dmytrokyrychuk
Copy link

@viperfx
Copy link

viperfx commented Feb 1, 2019

@alihazemfarouk thanks for your work on this. I have been waiting for this feature for ages.

Is your fork being used in your production apps? Have you been able to update the tests to verify the split functionality?

You should honestly put up some gittip or bounty, because I will happily pay for further improvements.

@viperfx
Copy link

viperfx commented Feb 2, 2019

@alihazemfarouk are you aware of how a react router integration could work? e.g. splitting based on routes defined in a react router.

export const createRoutes = (store) => ({ path : '/', component : CoreLayout, childRoutes : [ Login, SignUp ] }) export default createRoutes 
@alihazemfarouk
Copy link
Author

alihazemfarouk commented Feb 2, 2019

@alihazemfarouk thanks for your work on this. I have been waiting for this feature for ages.

Is your fork being used in your production apps? Have you been able to update the tests to verify the split functionality?

You should honestly put up some gittip or bounty, because I will happily pay for further improvements.

Thanks a lot for your nice words. Yes I have been using my fork in production. There are tests that I'd written here too that verify that the package handles loading an entrypoint correctly with all its chunks. You can find the necessary instructions in the readme on my github fork, especially look for the parts where EXCLUDE_RUNTIME, BASE_ENTRYPOINT and the usage of render_entrpoint are explained

@alihazemfarouk
Copy link
Author

@alihazemfarouk are you aware of how a react router integration could work? e.g. splitting based on routes defined in a react router.

export const createRoutes = (store) => ({ path : '/', component : CoreLayout, childRoutes : [ Login, SignUp ] }) export default createRoutes 

Well the whole idea behind this feature is Webpack code splitting when manually specifying certain entrypoints. Ex:

module.exports = { ..., entry: { index: "./myapp/static/src/pages/index.js", contact_us: "./myapp/static/src/pages/contact_us.js", }, ..., plugins: [new BundleTracker({ filename: "./webpack-stats.json" })] }; 

as it reads from the stats file the plugin BundleTracker produces.

If you have any thoughts on how to improve this please share

@viperfx
Copy link

viperfx commented Feb 2, 2019

@alihazemfarouk I installed django-webpack4-loader

However, I got the following issue

ModuleNotFoundError: No module named 'webpack_loader'

@viperfx
Copy link

viperfx commented Feb 2, 2019

@alihazemfarouk also the examples folder does not contain an example for entry_point. Could you add that?

@alihazemfarouk
Copy link
Author

@alihazemfarouk I installed django-webpack4-loader

However, I got the following issue

ModuleNotFoundError: No module named 'webpack_loader'

The package is working for me both locally and in production apps. Try uninstalling both django-webpack4-loader and django-webpack-loader and reinstall django-webpack4-loader again.

@alihazemfarouk
Copy link
Author

@alihazemfarouk also the examples folder does not contain an example for entry_point. Could you add that?

Sure I can. The first chance I get some time off I will do that.

@viperfx
Copy link

viperfx commented Feb 2, 2019

@alihazemfarouk thanks that worked.

I have gone through rest of the setup and made sure to upgrade the required dependancies and I have my setup running on webpack 4, with the render_entrypoint tag.

It's a shame that I am not able to split up my bundles based on route, being able to do that, would be really awesome.

However, with webpack4 I already notice a massive improvement in build times.

Thanks again for your hard work on this. If I make any improvement, I will try and contribute back to the docs.

I would recommend cleaning up the docs and maybe making clear documentation on how the 'BASE_ENTRYPOINT' works with examples. (I am still a bit unclear on this)

@viperfx
Copy link

viperfx commented Feb 2, 2019

Quick update and potential bug I found (could be my misconfiguration) for BASE_ENTRYPOINT

My webpack produces the following entry point

Entrypoint main = vendors.css vendors.js main.css main.js 

My current config is this

WEBPACK_LOADER = { 'DEFAULT': { 'CACHE': False, 'BUNDLE_DIR_NAME': "bundles/", 'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'), 'POLL_INTERVAL': 0.1, 'TIMEOUT': None, 'EXCLUDE_RUNTIME': False, 'BASE_ENTRYPOINT': 'main' } } 

I am including my tags similar to

{% load render_entrypoint from webpack_loader %} <html> <head> {% render_entrypoint 'main' 'css' %} </head> <body> .... {% render_entrypoint 'main' 'js' %} </body> </head> 

In the view source, I see two includes like this.

<link type="text/css" href="/static/bundles/vendors.css" rel="stylesheet" />   <script type="text/javascript" src="/static/bundles/vendors.js" ></script>   <link type="text/css" href="/static/bundles/main.css" rel="stylesheet" />   <script type="text/javascript" src="/static/bundles/main.js" ></script> 
#### BASE_ENTRYPOINT
`BASE_ENTRYPOINT` is meant to be used with `render_entrypoint`. When creating multi-page applications, it's common to want to
include common js in the base HTML. If the main entrypoint's name is `main`, you can do that by including `{% render_entrypoint 'main' %}` in your base HTML file. Now in another entrypoints (that extend the base HTML file), there might be some chunks that were already included in `main`, that means they would be included twice in the final rendered HTML, to avoid that, set `BASE_ENTRYPOINT` to `'main'`, then any duplicate chunks between an entrypoint and the main entrypoint would be included only once.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate "When creating multi-page applications, it's common to want to
 include common js in the base HTML"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not by mistake. If you have a clearer way to explain it, please suggest it to me, or do it yourself and push it here

@alihazemfarouk
Copy link
Author

Quick update and potential bug I found (could be my misconfiguration) for BASE_ENTRYPOINT

My webpack produces the following entry point

Entrypoint main = vendors.css vendors.js main.css main.js 

My current config is this

WEBPACK_LOADER = { 'DEFAULT': { 'CACHE': False, 'BUNDLE_DIR_NAME': "bundles/", 'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'), 'POLL_INTERVAL': 0.1, 'TIMEOUT': None, 'EXCLUDE_RUNTIME': False, 'BASE_ENTRYPOINT': 'main' } } 

I am including my tags similar to

{% load render_entrypoint from webpack_loader %} <html> <head> {% render_entrypoint 'main' 'css' %} </head> <body> .... {% render_entrypoint 'main' 'js' %} </body> </head> 

In the view source, I see two includes like this.

<link type="text/css" href="/static/bundles/vendors.css" rel="stylesheet" />   <script type="text/javascript" src="/static/bundles/vendors.js" ></script>   <link type="text/css" href="/static/bundles/main.css" rel="stylesheet" />   <script type="text/javascript" src="/static/bundles/main.js" ></script> 

I don't understand the problem. What you're showing is the correct output, all the files, whether js or css, consisting that entrypoint, are rendered only once.

@viperfx
Copy link

viperfx commented Feb 3, 2019 via email

@alihazemfarouk
Copy link
Author

I think you misunderstood my comment. It gets rendered twice. The 4 script tags for both JS and CSS, gets included in bottom and top of the page.

Ahh I had not implemented the filtering by extension part yet, and yet I included it in the documentation. Silly me.
Thanks for making me notice it. I added the feature and added a test case verifying it, it is now part of this PR and is also published at pypi with version 0.0.5. Please upgrade django-webpack4-loader and tell me if it is still not working for you

@viperfx
Copy link

viperfx commented Feb 5, 2019

Thanks for the update. That fixed the issue.

This was referenced Feb 14, 2019
@bhrutledge
Copy link
Contributor

For folks waiting on this PR, I've rounded up relevant links and workarounds in a comment on PR django-webpack/webpack-bundle-tracker#41, on which this depends.

@danihodovic
Copy link

danihodovic commented Dec 31, 2019

Since this repo is largely unmaintained is @alihazemfarouk fork the go-to solution now?

@benpetty
Copy link

Since this repo is largely unmaintained is @alihazemfarouk fork the go-to solution now?

We are using that fork in production and works great 👍

@jonathan-s jonathan-s mentioned this pull request May 10, 2020
@fjsj fjsj self-requested a review April 30, 2021 18:20
@fjsj
Copy link
Member

fjsj commented Apr 30, 2021

Closing this in favor of #261
Which shares some of the same commits

@fjsj fjsj closed this Apr 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet