addStyleEntry(): CSS-Only Entrypoint

There are only two files left in the public/ directory, and they're both CSS files! Celebrate by crushing your js/ directory.

We have two page-specific CSS files left. Open account/index.html.twig:

... lines 1 - 4
{% block stylesheets %}
... lines 6 - 7
<link rel="stylesheet" href="{{ asset('css/account.css') }}">
{% endblock %}
... lines 10 - 51

Yep, this has a link tag to the first... and in security/login.html.twig, here's the other:

... lines 1 - 4
{% block stylesheets %}
... lines 6 - 7
<link rel="stylesheet" href="{{ asset('css/login.css') }}">
{% endblock %}
... lines 10 - 37

Oh, and we also include login.css from register.html.twig:

... lines 1 - 28
{% block stylesheets %}
... lines 30 - 31
<link rel="stylesheet" href="{{ asset('css/login.css') }}">
{% endblock %}
... lines 34 - 78

This is kind of a tricky situation.... because what Webpack wants you to do is always start with a JavaScript entry file. And of course, if you happen to import some CSS, it'll nicely dump a CSS file. This comes from the single-page application mindset: if everything in your app is built by JavaScript, then of course you have a JavaScript file!

So... hmm. I mean, we could leave those files in public/ - we don't need them to go through Webpack. Though... I would like to use Sass. We could also create account.js and login.js files... and then just import each CSS file from inside. That would work... but then Webpack would output empty account.js and login.js files... which isn't horrible, but not ideal... and kinda weird.

In the Encore world, just like with Webpack, we really do want you to try to do it the "proper" way: create a JavaScript entry file and "import" any CSS that it needs. But, we also recognize that this is a legitimate situation. So, Encore has a little extra magic.

First, move both of the files up into our assets/css/ directory. And just because we can, make both of them scss files.

Next, in webpack.config.js add a special thing called addStyleEntry(). We'll have one called account pointing to ./assets/css/account.scss and another one called login pointing to login.scss:

... lines 1 - 2
Encore
... lines 4 - 22
.addStyleEntry('account', './assets/css/account.scss')
.addStyleEntry('login', './assets/css/login.scss')
... lines 25 - 75
;
... lines 77 - 78

Easy enough! Find your Encore build, press Control + C, and restart it:

yarn watch

Awesome! We can see that the account and login entries both only dump CSS files.

And this means that, back in index.html.twig, we can replace the link tag with {{ encore_entry_link_tags('account') }}:

... lines 1 - 4
{% block stylesheets %}
{{ parent() }}
{{ encore_entry_link_tags('account') }}
{% endblock %}
... lines 10 - 51

Copy that and do the same thing in login.html.twig for the login entry:

... lines 1 - 4
{% block stylesheets %}
{{ parent() }}
{{ encore_entry_link_tags('login') }}
{% endblock %}
... lines 10 - 37

And then in register.html.twig, one more time for login:

... lines 1 - 28
{% block stylesheets %}
{{ parent() }}
{{ encore_entry_link_tags('login') }}
{% endblock %}
... lines 34 - 78

Ok! Let's double-check that the site doesn't explode. Go to the /account profile page. Everything looks fine.

So... yea, addStyleEntry() is available for this. But... to pull it off, Encore does some hacking internally. Really, addStyleEntry() is the same as addEntry(), which means that Webpack does try to output an empty JavaScript file. Encore basically just deletes that file so that we don't have to look at it.

Next, oh, we get to talk about one of my favorite things about Webpack and Encore: how to automatically convert your CSS - and JavaScript - so that it's understood by older browsers. And how to control exactly which browsers your site needs to support.

Leave a comment!