mariusbalcytis / webpack-bundle

Bundle to Integrate Webpack into Symfony
MIT License
122 stars 36 forks source link

Twig insert CSS that are required from JS files #74

Open aalwash opened 7 years ago

aalwash commented 7 years ago

Hi,

I'm trying to figure out how to use this correctly. In Twig I have this:

{% block javascripts %}
    <script type="text/javascript" src='{{ webpack_asset('@app_assets/js/dashboard.js') }}'></script>
{% endblock %}

Inside dashboard.js I have this

require('./storage.js');
require('highcharts/css/highcharts.css');
require('@app_assets/css/dashboard.css');
var Highcharts = require('highcharts');
//....

THe JS code loaded, but the CSS isn't loading. I assumed it was injected somehow.

One work around is to put this in Twig But somehow, it doesn't feel like I'm using it correct?

{% block javascripts %}
    {% webpack css '@app_assets/js/dashboard.js' %}
    <link rel="stylesheet" href="{{ asset_url }}"/>
    {% end_webpack %}

    {% webpack js '@app_assets/js/dashboard.js' %}
    <script type="text/javascript" src="{{ asset_url }}"></script>
    {% end_webpack %}
{% endblock %}

Is there a way where I can see in twig, output all needed CSS files, that came together with the JS require's? Something like this for example?

{% block javascripts %}
    {% webpack css  %}
    <link rel="stylesheet" href="{{ asset_url }}"/>
    {% end_webpack %}
{% endblock %}
mariusbalcytis commented 7 years ago

Yes, you are using it correctly (by duplicating entry file for both js and css files).

You could alternatively disable extract_css (see https://github.com/mariusbalcytis/webpack-bundle#stylesheets) so that you wouldn't require to explicitly include stylesheets, but, as JavaScript would load your styles, you would get initial flicker while styles load.

About the suggested feature to skip providing JavaScript files for stylesheets, it's quite possible, but would work (probably) not as expected in some situations.

The main difficulty is to know which of the files are required. To include all the files would be wrong, as several entry points could be used in separate parts of application. To know which files are needed at runtime we would need for JavaScript files to be included before CSS files (when rendering twig template) to collect them. Unfortunately, that's not the case in most situations. One possible solution is to know this at twig compilation time, but in this case it would work only with other tags inside the same twig template. It would not be possible to include {% webpack css %} in base template and forget about it at all. That's why I don't think it's good to make this feature at all, as it could be easily misunderstood.

Unless you have any ideas how this could be handled automatically?

aalwash commented 7 years ago

Hmm, oke, I will give the extract_css: false a try tomorrow.

About the rendering issues, to be honest, I don't have enough experience with how this is setup.

The main difficulty is to know which of the files are required. To include all the files would be wrong, as several entry points could be used in separate parts of application. Why not? If someone doesn't need CSS, then why would he/she bother doing a require()? And of course, duplicate css files that are required through multiple entry points should be only included once in Twig.

I'm trying to figure a way to find a one-solution-fixes-all-issues, but it's too hard without knowing how the plugin is build exactly.

Maybe something like this? (I'm just thinking out loud) Instead of doing a separate webpack js and css, you can combine them in one call

{# Overwrite webpack_js_line block, because people want custom async attribute #}
{% block webpack_js_line %}
    <script type="text/javascript" src="{{ asset_url }}" async></script>
{% endblock %}

{% webpack js,css '@app_assets/js/dashboard.js' %}
{# Load default template of webpack bundle which contains default webpack_stylesheet_line and webpack_js_line blocks #}
{# Which can be overwritten if needed. A bit similar to the Symfony Form Components #}

    {# if type == 'css'#}
        {{ block('webpack_stylesheet_line') }}
    {# endif #}
    {# if type == 'js'#}
        {{ block('webpack_js_line') }}
    {# endif #}
{% end_webpack %}