webpack-encore icon indicating copy to clipboard operation
webpack-encore copied to clipboard

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

Open weaverryan opened this issue 7 years ago • 10 comments

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!

weaverryan avatar Nov 06 '18 15:11 weaverryan

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?

nicolas-grekas avatar Nov 06 '18 15:11 nicolas-grekas

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 avatar Nov 06 '18 16:11 dunglas

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/

dunglas avatar Nov 06 '18 16:11 dunglas

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.

rakelley avatar Nov 07 '18 15:11 rakelley

@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

stof avatar Nov 07 '18 16:11 stof

Hi guys!

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

Thanks!

weaverryan avatar Nov 16 '18 18:11 weaverryan

@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?

heleneshaikh avatar Jan 17 '19 09:01 heleneshaikh

{% 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')

GenieTim avatar Jan 17 '19 09:01 GenieTim

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.

minimit avatar May 21 '21 15:05 minimit

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!

loevgaard avatar Nov 08 '22 08:11 loevgaard