symfony / webpack-encore

A simple but powerful API for processing & compiling assets built around Webpack
https://symfony.com/doc/current/frontend.html
MIT License
2.23k stars 198 forks source link

Add support for preload/prefetch and Symfony's WebLink component #429

Open weaverryan opened 5 years ago

weaverryan commented 5 years ago

The WebLink component allows you to preload assets - https://symfony.com/doc/current/weblink.html

In the Webpack world, this is ability can be written into your Webpack config via https://github.com/GoogleChromeLabs/preload-webpack-plugin

We should be able to bring this nice functionality to Encore without too much trouble :)

1) Allow the user to configure which entrypoints should be preloaded. We should consider what the preload-webpack-plugin does for this. However, it may also make sense to add this as an option to addEntry(). This is something to think about.

2) Based on the above config, we would likely render new metadata in entrypoints.json about this.

3) WebpackEncoreBundle could then read this metadata and communicate with the WebLink component so that the proper headers are set.

Symfony already supports these new HTTP features. Let's make them easy to use in Encore!

nicolas-grekas commented 5 years ago

How does HTTP caching come into play? E.g. should we push files that are shared on all pages? since they would be cached most of the time, this may cause extra traffic by forcing the browser to send a frame discarding the push? Should we only push the page-specific assets? @dunglas what's your experience here?

dunglas commented 5 years ago

E.g. should we push files that are shared on all pages? since they would be cached most of the time, this may cause extra traffic by forcing the browser to send a frame discarding the push?

It's usually not a problem because browsers can cancel a push if they already have the data in cache. However some browsers have (had?) bugs, and may not cancel the push, or not leverage it (especially Safari IIRC).

There was a very interesting article about this topic, but it seems to be offline right now: https://www.shimmercat.com/en/blog/articles/whats-push/

dunglas commented 5 years ago

This article is a bit outdated, but provides a nice overview of how the different caches work together: https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/

rakelley commented 5 years ago

Without this feature splitEntryChunks is a mixed blessing for us as well. Our existing shared entry setup utilizes defered script tags with preloading to ensure shortest time to interactivity.

With split chunks and encore_entry_script_tags's non-deferred non-preloaded tags, the total build size is ~5% smaller, time to DOMContentLoaded is slightly faster on slow connections and slightly slower on fast connections, but full load always takes much longer.

stof commented 5 years ago

@rakelley encore_entry_script_tags renders non-deferred tags, but you can use encore_entry_js_files instead and render the script tags yourselves, giving you full flexibility over making them deferred

weaverryan commented 5 years ago

Hi guys!

See #455 for an initial attempt at this. But, I need real-world feedback before that PR can continue.

Thanks!

heleneshaikh commented 5 years ago

@rakelley encore_entry_script_tags renders non-deferred tags, but you can use encore_entry_js_files instead and render the script tags yourselves, giving you full flexibility over making them deferred

Can someone please provide an example on how to do this?

GenieTim commented 5 years ago
{% for js in encore_entry_js_files('my-encore-id') %}
            <script src="{{ asset(js) }}" type="text/javascript" defer="defer"></script>
{% endfor %}

with my-encore-id from e.g. webpack.config.js:

.addEntry('my-encore-id', './assets/js/app.js')
minimit commented 3 years ago

For defer just add to config/packages/webpack_encore.yaml

webpack_encore:
    script_attributes:
        defer: true

For preload would be very nice to have a functionality as defer.

loevgaard commented 1 year ago

This is ranked 1 on Google when you search for 'webpack encore preload', so I just want to add here that @weaverryan implemented this and all you have to do is this:

# config/packages/webpack_encore.yaml
webpack_encore:
    preload: true

Virtual high fives to you, @weaverryan ✋ Thank you!

carsonbot commented 1 day ago

Thank you for this issue. There has not been a lot of activity here for a while. Has this been resolved?