Navigation Menu

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

Allow custom script/link tag attributes to be passed #10

Closed
weaverryan opened this issue Oct 29, 2018 · 17 comments · Fixed by #102
Closed

Allow custom script/link tag attributes to be passed #10

weaverryan opened this issue Oct 29, 2018 · 17 comments · Fixed by #102

Comments

@weaverryan
Copy link
Member

weaverryan commented Oct 29, 2018

There are a few legit use-cases for wanting to use the encore_entry_script_tags() functions, but pass a custom attribute:

  • integrity attribute
  • preload, async, etc

Another attribute, in theory, would be adding data- attribute on your script tag. But, that doesn't make sense with encore_entry_script_tags(), because this could render multiple script tags.

I think the main use-cases then are the ones in the list above. And, these might be best integrated (especially integrity) with some global option. I'd like to get use-case feedback and use that to motivate how this is designed.

@dunglas
Copy link
Member

dunglas commented Nov 5, 2018

It could be nice to be able to integrate encore_entry_script_tags() with the WebLink component too, to allow the use to adk the web server to push the assets when using a HTTP/2 connection.

@nicolas-grekas
Copy link
Member

💯 with Kévin!

@alexismarquis
Copy link

Having an option for generating absolute urls would be useful as well. In my case I need these for wkhtmltopdf rendering.

@iquito
Copy link

iquito commented Nov 7, 2018

A way to just get a list of files would be nice - encore_entry_script_tags() only covers one use case, instead having something like encore_script_files() in Twig which returns an array of files you can then do whatever you want with, and also a service in PHP to get these files, so one can generate script tags in any way needed and (for instance) do preloading or other HTTP things in a controller.

For Content-Security-Policy 3, nonce and strict-dynamic one would also need custom script tags (to add another use case) - a generic way of letting anybody do what they want would be most flexible, because I don't think there is a finite set of use cases you can completely cover when you only offer to specifically generate the script tags (or, for example, specifically add it to WebLink) via the bundle.

@iquito
Copy link

iquito commented Nov 7, 2018

Ah I just saw that those already exist - encore_entry_js_files and encore_entry_css_files. Having a clearly visible tutorial on how to use those to generate custom HTML code and also use the service in a controller (or somewhere else) would solve the problem better then having a more complicated encore_entry_script_tags(), in my opinion, but both are of course possible.

Maybe it is also worth mentioning encore_entry_js_files and encore_entry_css_files in the blog article on symfony.com as an alternative to the new syntax, as it is "closer" to the old way of doing it and more flexible. I saw now that it is mentioned in the comments, but not all people might read all the comments or might overlook it.

@stof
Copy link
Member

stof commented Nov 7, 2018

yeah, the 2 functions returning the list of files should be documented, as they allow full flexibility.

@GenieTim
Copy link

GenieTim commented Nov 8, 2018

Additional use case for parameters: the media tag (e.g. media="print")

@weaverryan
Copy link
Member Author

Having an option for generating absolute urls would be useful as well. In my case I need these for wkhtmltopdf rendering.

@alexismarquis you should do this by either setting the public path to an absolute URL in webpack.config.js or setting the framework.assets.base_urls to your absolute URL in framework.yaml. That probably deserves some documentation, even though it's not a new feature.

@alexismarquis
Copy link

@weaverryan yeah I thought about that, but this approach would make all asset urls to have an absolute url, which is not something I need for the other templates. Anyway, using the encore_entry_js_files & encore_entry_css_files functions gave me the flexibility I needed (e.g calling absolute_url and preload on each file).

@aarongerig
Copy link

@weaverryan Any news on this feature?

Since having the possibility to add integrity hashes to your assets (which is great), it's even more complicated to add custom attributes than before. For example, if I'd wanted to add defer to my script tags, until now I was doing it like so:

{% for file in encore_entry_js_files('entry') %}
    <script src="{{ asset(file) }}" defer></script>
{% endfor %}

But how do you add the integrity hashes now? Is it even possible? As far as I understand, that's only possible using either encore_entry_link_tags() or encore_entry_script_tags().

@ohartl
Copy link

ohartl commented May 8, 2019

As @iquito stated before, it would be nice if we could pass a nonce attribute as that is required for some CSP configurations. I haven't found any possibility to set/override the $defaultAttributes, as the service is private and the class of TagRenderer is final.

Had to do a hack to insert the attribute via {{ encore_entry_script_tags() | replace({'type=': nonce_attr() ~ ' type='}) | raw }}..

@Simperfit
Copy link

@weaverryan do you have an ETA for this ? do you need some help ?

@Saryon61
Copy link

Saryon61 commented Feb 5, 2020

I think it would be interesting to load JS assets at the very end of the rendering of a page with Webpack Encore. It is well explained in this interesting video.

But the encore_entry_script_tags does not provide such a feature if I am right. it only renders the script HTML element with src attribute.

What if the encore_entry_script_tags could render a script element in which we would find:

window.addEventListener("load", () => { const script = document.createElement('script') script.src = "script.js" document.body.appendChild(script) })

So that, like explained in the video, all the JS assets would be parsed after the page rendering.

Or am I missing an already implemented functionnality of Webpack Encore that I don't already know?

Thanks for your feedbacks

@BruceGitHub
Copy link

BruceGitHub commented Mar 12, 2020

It maybe raise a dispatch before render some tags, this is more flexible and inline with the symfony style. Or some other hook's mechanis to change the attributes array

           //Symfony\WebpackEncoreBundle\Asset\TagRenderer.php
            if (isset($integrityHashes[$filename])) {
                $attributes['integrity'] = $integrityHashes[$filename];
            }
            
           <---- HERE  

            $scriptTags[] = sprintf(
                '<script %s></script>',
                $this->convertArrayToAttributes($attributes)
            );

For the case of CSP and nonce the nonce must be generated for each request, so with this feature
it is possible put a placeholder to replace for example in each nginx request

@ucay
Copy link

ucay commented Dec 12, 2020

any update on this feature?

@dsech
Copy link

dsech commented Jan 8, 2021

It seems there are multiple issues discussed here and it might make sense to discuss (and implement) each one separately, hopefully this will help things move forward:

  1. encore_entry_script_tags() and encore_entry_link_tags() lack flexibility. This could be solved by leveraging the named arguments in Twig, for example like this:
    a. for extra attributes:

    {{ encore_entry_script_tags('entrypoint', attributes: {
        nonce: csp_nonce('script'),
        defer: null
    }) }}
    

    example output:

    <script src="/path/to/entrypoint.js" nonce="BWkMcuOoTSkvrIDjzfhmKQ==" defer>
    <script src="/path/to/chunk.js" nonce="BWkMcuOoTSkvrIDjzfhmKQ==" defer>
    

    This covers the scenario when all emitted tags for an entrypoint need the same attributes. For more advanced scenarios either split the js/css assets in multiple entrypoints, or rely on encore_entry_js_files() / encore_entry_css_files()

    b. integration with weblink:

    {{ encore_entry_link_tags('entrypoint, preload: true, nopush: true) }}
    

    c. other features... new arguments?

  2. encore_entry_js_files() and encore_entry_css_files() do not provide enough information - in this case the integrity hashes are not available. This could be solved by returning objects/associative arrays instead of only the asset URL:

    {{ encore_entry_js_files()|json_encode }}
    

    example output:

    [
      {
        "path": "/path/to/entrypoint.js",
        "url": "http://localhost/path/to/entrypoint.js",
        "attributes": {
          "integrity": "sha384-L5Qbaa3lC1QA5E9NddB9nnj1AeBSRmaw9HXFwHjjWV7CNFeF2Cxzud/jXzuJqDjO"
        },
        .. and potentially other stuff here
      },
      {
        "path": "/path/to/chunk.js",
        "url": "http://localhost/path/to/chunk.js",
        "attributes": {
          "integrity": "sha384-YQEHTaHYBIBdU0L4Ax+Jha19P/tpy1w6xcgnqt7xKtdnd5Xrn9CB2jnl50a6d/sz"
        }
      }
    ]
    

    This will allow to easily add extra information for new features in the future. But no idea how to handle BC - maybe create new twig functions that output an array/object?

  3. Runtime hooks - allow plugins to modify the asset object.
    a. Imagine there could be a plugin that automatically sets the CSP nonce attribute. In this case the "nonce" attribute will be automatically outputted by encore_entry_*_tags() (see point 1.) and also available in the object returned by encore_entry_*_files() (see point 2.)

I would love to have at least point 1.a implemented (allow custom attributes). This will unlock plenty of features right now (media="print", nonce="..", type="module"/nomodule, async, and others).

@weaverryan
Copy link
Member Author

I’ve done 1a and 3 from the last comment in #102 - I hope it will help! If you need anything else, please open a separate issue. Thanks @dsech for the inspiration on the implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet