#135 Efficient Asset Loading

## Document Notes
## Highlights
- **Load Block CSS Only When Used**
- Register block CSS files by scanning a theme folder and mapping filenames to block names using PHP glob and WP_Register_Block_Style.
- Let register_block_style() enqueue CSS only when the block appears, reducing unused CSS payloads.
Transcript:
Speaker 2
Um, the first one is all about basically efficiently loading CSS and JavaScript in our WordPress sites. And it came about, I'll do the intro mark. Cause I reckon you're going to be talking through the technicalities because it's mostly been your work so far. But it came about because of a performance kind of audit that we're doing for a client of ours. And one of the, you know, we're just running it through Google PageSpeed. One of the main insights was that the theme css file was quite large and it was it's kind of grown over time um and it's reasonably big and we have previously and since this project uh been Much cleverer about how we kind of load our css i don't know how why this project kind of we haven't we weren't doing those things um but what we what we thought is that we should probably Be loading block styles uh like block css specifically uh only when those blocks are on the page if possible and we know it is possible um so you set about to figure out um how to look for Those assets in a particular place in the theme if the block was on the page over to you what challenges did you face what solutions did you come up with i'm just checking out the right branch
Speaker 1
So i can see my code at the same time. Yeah, good idea. And it magically appears in my file logo. So I've done this before, actually. So it's just a matter of revisiting it. And I've actually approached it in a few different ways. The very first way I approached it was to get all of the blocks on the website. So you can do that. I think there's like a block registry class thing, and you can get all of the registered blocks. And then you kind of loop through each of those. You check whether you've got a file present, and if you have, you kind of enqueue it. But that was kind of inefficient, so I thought we may as well do it the other way around, in that if we have a block file present, then loop through those and then work out what the block is That you need to sort of add the block style. So that's the approach I've gone for. So essentially, we get, we're just using the PHP glob function, which basically looks at a directory of the file. So I'm looking at in this directory, I think it's assets. This is in the theme. It's assets blocks, essentially. And it looks for any files in there that are ending in.css. And then we loop through each of those files. We build a path because you need the path in a minute. We build a file name. And then from the file name, we build the block name. Because obviously the file name is going to be like core-paragraph, whereas the block is called core-paragraph. A bit annoying, but that's what you have to do. And then for each of those, we then use the core WordPress function, WPNQBlockStyle, which kind of does what it says on the tin. It registers your CSS file with WordPress, and it enqueues it when that block is detected in a page load. So you'll only ever get that loaded if you have that block on the page, which seems much more efficient. You know, if we've got some specific styles for a media and text block, but that's not on the current page, it seems silly to load the CSS for that when we don't read it. So this is trying to attack this so that only the CSS you want is loaded. And that should help because our CSS file is quite large. So we can split that into smaller files and only load those when they're needed. It makes sense. The other thing that the WP NQ block style does, and this is why you need the path of your style sheet, that's like the path on the server, is because it will try and inline those styles if It judges that they are suitable for being inlined. I haven't actually looked into what the criteria is that. I think part of it is how much CSS there is in your file. So if you've only got a few rules, it's probably just going to inline them straight away, which is, again, a little bit more efficient. So that works. So basically once that function has been running, and I've just added that into the theme, it's hooked in its hook, and it will try and queue styles for each block if they're present. ([Time 0:03:13](https://share.snipd.com/snip/0c3b365c-3e29-455c-9f63-b0833a7c4376))
- **Provide Paths To Allow Inlined Styles**
- Provide the filesystem path to WP_Register_Block_Style so WordPress can inline small block styles for efficiency.
- Split a large theme stylesheet into per-block files and keep a core theme stylesheet for global rules.
Transcript:
Speaker 1
So essentially, we get, we're just using the PHP glob function, which basically looks at a directory of the file. So I'm looking at in this directory, I think it's assets. This is in the theme. It's assets blocks, essentially. And it looks for any files in there that are ending in.css. And then we loop through each of those files. We build a path because you need the path in a minute. We build a file name. And then from the file name, we build the block name. Because obviously the file name is going to be like core-paragraph, whereas the block is called core-paragraph. A bit annoying, but that's what you have to do. And then for each of those, we then use the core WordPress function, WPNQBlockStyle, which kind of does what it says on the tin. It registers your CSS file with WordPress, and it enqueues it when that block is detected in a page load. So you'll only ever get that loaded if you have that block on the page, which seems much more efficient. You know, if we've got some specific styles for a media and text block, but that's not on the current page, it seems silly to load the CSS for that when we don't read it. So this is trying to attack this so that only the CSS you want is loaded. And that should help because our CSS file is quite large. So we can split that into smaller files and only load those when they're needed. It makes sense. The other thing that the WP NQ block style does, and this is why you need the path of your style sheet, that's like the path on the server, is because it will try and inline those styles if It judges that they are suitable for being inlined. I haven't actually looked into what the criteria is that. I think part of it is how much CSS there is in your file. So if you've only got a few rules, it's probably just going to inline them straight away, which is, again, a little bit more efficient. So that works. ([Time 0:05:33](https://share.snipd.com/snip/d1d15e15-b5f5-49e5-be42-5797e80a76ec))
- **Enqueue Block Scripts Only When Needed**
- Enqueue front-end JavaScript for blocks using the block type metadata 'viewScript' property so scripts load only when a block exists on the page.
- For per-style scripts, use render_block filters to detect a block instance's CSS class and call wp_enqueue_script() conditionally.
Transcript:
Speaker 1
Glad you asked. So we're not, but we probably could be. I've been experimenting with that this week. What was a key thing for me was you can load JavaScript for any block on the front end, quite straightforward. So we've done this for this particular project. So we have, I'll take an example. We have a gallery block, and we turn that into a slider when they want like a logo slider. So what we essentially do is we create a block style that's called logo slider, I think it's called. And when they apply that block style, the JavaScript that we've got will obviously then hook into the CSS class that's added and turn it into a slider. So you want to enqueue your JavaScript when the gallery block is loaded. So you can do that using the filter called block type metadata, which essentially filters the block JSON file for the blocks in question. And you can add your script into that. It's called view script. View means like viewing this on the front end. It's basically load this script when we're viewing this on the front end. So you'd register a script as you normally would, and then you'd filter this and pass the handle of the script to this block JSON or this block meta filter. And then your JavaScript will get loaded when the block's on the front end. Now that's great, and it works for any block as long as it has a block JSON file, because that's what you're filtering. So if you've got a very old ACF block that was using ACF register block type, it didn't work for that. And we've got a few blocks like that, so we need to update them slightly. But they have other functions that you can use to enqueue assets as well. So you can still do this. It's just a different method. The one thing it doesn't do, which is what I really wanted to try and solve, is that I only want to enqueue that logo slider JavaScript file that you've written when that block style is Selected. I don't want to enqueue it if they just had a gallery, a normal gallery. There's no point. It's a waste. They don't need it. Yeah.
Speaker 2
So that's what we have been doing currently. So we've got scripts, for example, that get loaded on every paragraph block because there's a certain paragraph style that does like a little counter. Yeah. Correct. That does a little counter.
Speaker 1
So every paragraph has that, which essentially means it runs on every page because pretty much every page has a paragraph. So I went about trying to solve that issue of how do we only enqueue block assets, sorry, block JavaScript when the block is actually being viewed. And I'm actually just going to load up the post I wrote. Hang on. So I can actually get a code in front of me. And then we can see. So I asked, used a bit of AI, as we do, and got some help from Bob. But essentially what I wanted to do is to say, if this block has this block style, then I want to somehow enqueue our JavaScript. So we'll use the logo slider as an example. And the way in which I'm doing that is you can't do that with filtering the block metadata, because at that point in time, the instance of the block hasn't loaded. You're just sort of saying this is the data for all blocks, if you know what I mean. Yeah. Not the actual instance that's on your page. Yeah. So the only method that I found to do it with, you have to do that using the render block filter, which if you didn't know, the render block filter allows you to change the block HTML, and It also allows you to obviously run your own code at the same time. So there is also render block filters for each individual block. So render, underscore, block, underscore, and then the block name will only run your code on that particular block. So in the gallery one, we do render block core slash gallery, and then we'd run our code. And what we're doing in the code that I've got is it's looking for a class name called is style, whatever your style is, ours is logo slider. If that class is not present, then we just return the normal block content as it was. We don't want to touch it. We just finish there. That's it. If that is the case, then what we can do is run the WPNQ script function, which will enqueue our logo slider JavaScript, and then just return the block content as it was. We don't want to touch the block content. We're not really interested in that. We just want to do something at a point in the block loads. And that works really well. The script gets enqueued only when your style is run. I haven't tested it on the actual site yet. I've been running it on a local little test environment, just a simple test WordPress. But I've added multiple blocks of different styles, and it all seems to only load when you've obviously got your style selected, which is great. ([Time 0:09:45](https://share.snipd.com/snip/61ca91a8-1a5d-47d3-b3fb-c842e0bbe910))
- **HTTP/2 Makes Multiple Assets Cheaper**
- Splitting assets into many files used to hurt HTTP/1 but HTTP/2 allows multiple concurrent transfers so many small files are less penalized.
- Browsers show parallel, vertically stacked network requests under HTTP/2 instead of serialized waterfalls.
Transcript:
Speaker 2
If we're breaking up style sheets and JavaScript files into smaller chunks.
Speaker 1
My understanding was that HTTP 2 can handle that.
Speaker 2
And I'll bring in Mark for that. So Mark then comments, if the site is loaded over HTTP 2, then it's more efficient to load separate files than one merged file. If the path attribute is passed to WP and Q block style, then the CSS is inlined, which makes the issue of separate asset loading moot. Okay. So that is what I kind of thought as well. I mean, does it get to a point where even with HTTP2, you know, like you can't have too many requests? I don't know, because presumably it can only kind of handle a certain number at a time.
Speaker 1
I don't know. My understanding with HTTP 1 or whatever it was, it 1.1, I can't remember, was that the browser can only handle one request at a time. So it requests the JavaScript file, it waits for the server to respond, the server responds with the JavaScript file, then it requests the next one and so on. Whereas with HTTP2, I understand, it can open a connection, and then it can say, give me this one, this one, this one, this one, this one, and then it can just send them to you.
Speaker 2
Yeah, you can see that in the network tab on most websites now. So if you open the network tab, and you can see that kind of waterfall view, they'll quite often just be like, it gets to the kind of right, I need to load my CSS or JavaScript files now. And they're all just stacked exactly vertically. Yeah, because they happen at the same time. Instead of like one after another. ([Time 0:15:40](https://share.snipd.com/snip/dc4818d9-d912-46a4-bee3-e04f3daf8433))
- **Don't Load Front-End Scripts In The Editor**
- Avoid loading front-end enhancement scripts in the editor unless you need editor interactivity; it can break editing UX.
- Keep editor experience simple by leaving blocks as basic content in the editor and enhancing only on the front end.
Transcript:
Speaker 2
And then one more from Elliot. Hook, WP and Q script to and Q block assets should work. You might have to help me with that one, Mark. I'm not quite sure what he means there.
Speaker 1
So NQ block assets is a hook that will run on both the front end and the back end. So if you want your JavaScript to load in the editor, as well as in the front end, then you want to use NQ block assets rather than something like render block. I would imagine that's what it's meaning. Most of the time with these things, we don't want to load these in the editor because it actually makes editing the content. Yeah, we don't load the JavaScript because if you turn it into a slider in the back end, how do you click on an image to then start replacing it and stuff like that? It depends what you're doing, I think. But I find most of the time you probably don't want to load the JavaScript in the back end.
Speaker 2
But that is very specific to what you're doing. Yeah, and that's exactly what Courtney's asking here. She said, how do you render sliders in the admin? Do you write admin CSS to just show one slide, for example? The way we've done it, so there's lots of different ways. It depends on the slider. We've built kind of custom blocks that are sliders, and in that case, we're often just using acf to build the block and then just using like a repeater field so there is ([Time 0:18:15](https://share.snipd.com/snip/fd4c452f-f4f5-44f5-8d26-df5ce89be220))
- **Umlaut Caused 403 On Job URLs**
- A job post delivered with an umlaut caused a 403 because sanitize_title_with_dashes didn't remove accented characters.
- Changing to sanitize_title (which calls remove_accents) fixed the URL sanitization and resolved the 403 issue.
Transcript:
Speaker 2
And I had a thing that just jumped out at me almost as soon as I saw it was that the job that had the issue, the 403, had an umlaut in the title of the job, and it was making the URL look very, very Strange. So we've kind of dug into that a little bit this morning have we actually kind of found the solution or figuring it out or well or do you think we're still a bit confused i haven't tested
Speaker 1
It yet yeah but i'll explain what happens so yeah when a job gets delivered from or gets delivered to the website, wherever it's coming from, whether it's Bullhorn or Broadbean or Logic Melon or wherever it is, we simply use the wpinsertpost function to sort of create the post in WordPress, the job post. And obviously, we pass the job title into there when you create the post. WordPress automatically generates the post name if you don't specify it and it will generate it by taking the title and essentially separating it with dashes and doing a few other checks And things. One of those checks that WordPress does is to check for, I'm just going to call them weird characters. I'm sure that Germans and French don't call them weird, but apologies for that. Special characters? Special characters. Are they special? They're not special to those anyway. Non-standard English characters. I don't know what to call them, but you get the point. There is an official word for this, but we haven't got it, so apologies. And what it does is it strips those out. So for example, in this particular case, it was the letter A with an umlaut over, which if you don't know, it's got two little dots over the top of it. And it just strips out for a normal A and then saves the post name. But then in my code, what we do next is we actually update the post name once the post has been created with appending the post ID. So I can't do it when the post is created because at that point, I don't know the ID. So I append the post ID at the end of it in an update. And the reason we do that is so every job has a unique URL because lots of recruiters, they recruit the same sort of jobs. So they end up posting a job and it's like marketing-manager and then that job gets deleted and another one comes in and it has the same URL as the original and it just confuses ATS systems. It confuses lots of things.
Speaker 2
Yeah.
Speaker 1
So long story short is we put the post ID on the end so they're always unique. And when I'm doing that update, so say WP update post, and I'm changing the post name, I needed to sanitize the title. So I used sanitize title with dashes, which kind of does what it says on the tin. It puts dashes in the title that was given. However, it would appear that that does not convert the accents or special characters or whatever we're calling them it doesn't do that it doesn't do that at all so then it left that in The url and then when you view it again i'm not entirely sure why it 403s is that a server thing is that a i don't know but it 403s and it's clearly the problem because you replace it and it Doesn't however what i've since worked out i think today is that you should use sanitize underscore title and the reason for that is because sanitize underscore title i believe calls Sanitize title with dashes and it calls the function called remove accents which does this little replacement between the characters to normal ones so i need to update our plugin to Swap that sort of sanitization function out and i think as i said i haven't tested it but once i do that it will actually solve this problem yeah we'll see that's a weird one i can't believe
Speaker 2
We haven't come across it before yeah that's what i was i was amazed that this hasn't been a problem before so and you're thinking maybe that is because there's some kind of like server Level configuration or even something within wordpress that's kind of yeah like a security plugin or something that isn't isn't loving the the character but yeah basically trying
Speaker 1
To it again i'm completely making this up as a guess but if the server is seeing that in the URL, is it sort of some firewall saying, that looks a bit weird, I'm just going to block it, a 403, Access denied, unauthorized, whatever. I don't know. Yeah.
Speaker 2
So Marcus said, make sure that the saved value part of the post name has been run through sanitized title. That will convert special characters. Exactly. And most browsers understand special characters but if they're not converted properly e.g utf-8 uh then that may well cause a problem so yeah that's something that's what we've been Uh experiencing so yeah hopefully we got a fix out for that but essentially ([Time 0:23:47](https://share.snipd.com/snip/b7dd31da-c3ea-44fc-9a24-de616bd28665))
- **Price Intentionally, Avoid Habitual Discounts**
- Set product prices intentionally and avoid habitual discounting; review price if sales indicate it is wrong.
- Use targeted discounts like early-adopter offers rather than arbitrary seasonal sales if your pricing reflects value.
Transcript:
Speaker 2
That's good. Last thing on the list, and I don't think, well, maybe we will. It wouldn't take too long on this, I don't think. Is sale pricing and discounts. Why did you put this one on the list, Mark?
Speaker 1
I was watching WP Builds earlier this week, and they were sort of chatting about Black Friday deals and things like that. Yes, yeah. And then we had a customer, actually, which has kind of brought it up again. So we had a customer earlier this week, and I'd sent them everything that they need to buy the product. They decided to buy the product. And then, interestingly, on the call, they'd already said, Oh, I spoke to you three years ago. And then it was like, your product was 35 quid and you know, now it's 49 quid. So immediately I'm thinking, you know, they're thinking about discounted prices. And, and I just said, well, you know, the world's moved on since the price is what it is now sort of thing. And then the customer, uh, I them everything they need to buy it. They said, yeah, yeah, I'm going to go ahead and buy it now. And then they sent an email about like two minutes later. They said, oh, I can see there's a discount code box on your checkout page. You know, is there a Christmas discount that I can use? You know, a feeling of goodwill and stuff. So I was just thinking, and it got me thinking about Black Friday prices as well. You know, like why offer a black friday deal i don't quite understand it because why are you offering this sale because if people want the product then surely they will they will pay for It and if if you're not selling them unless you offer discount then isn't your pricing just wrong as in make the price the black friday discount rather than having to run these sales and Discount codes i don't understand it yeah but then we were talking earlier weren't we about businesses have different models don't they how they sell things you know if you think about Um you know sofa companies in this this they constantly have offers on. You'd never buy a full-price sofa in this country because they've always got a sale on. So do a lot of businesses run like that.
Speaker 2
Which is technically illegal, by the way. I'm pretty sure.
Speaker 1
I'm sure they're not being illegal because they'll be pricing them at the right price for certain periods that's just long enough and so yeah yeah exactly yeah so is is the customer and I'm taking this customer in particular for us are they seeing like oh it's it's 419 pounds a year his job really yeah but we're not going to pay that way because there's always going to Be some sort of like discount that they're going to give us on the call you know and that sort of thing and a lot of us ask that you know is that the best price you can do and everything like That and i'm like yeah because that that's how much it costs whereas i think other custom other companies might be yeah well but if you buy it today we can give you a discount code for 20% Off and then and so on so is the customer that was asking us in the mindset that if they pay 419 pounds then they're they're losing out. Like why are they paying that much when there's a discount code box on the checkout and everyone else will be putting a discount code in there and I'm not. So it's an interesting, I just think it's a really interesting like mindset. My thought process is that we shouldn't offer discounts. We shouldn't offer discounts for the products. And because we value, well, we price the product at what we think is a value to the customer. And they either think that's valuable or not. Now, if we experience that and like, you know, 75% of the customers book calls, they love the product. And then they go, oh, I'm not buying it because the price is too expensive. Then we'd have to think about whether it's the right price. But I don't think that's the case with our product. I think the price is the right price. So why would we want to offer discounts? I don't quite understand why that would be the right thing to do.
Speaker 2
I think our product is so niche as well that we don't have a lot of kind of direct competition. There isn't, we actually do have some competition in our space for job relay, but it's not like, it's not like buying a hi-fi or like a TV and you're like, you can buy the same Panasonic TV from a million different places and you're going to search through them all to find the one that's giving you the the best deal like yeah i i've got kind of different experiences i guess With sales and discounts so for example i just bought a sound bar for my home my tv in my living room uh and i've i've waited for nearly two years actually for a black friday sale because I forgot to buy it last year um so but like black friday came along and i was like right i'm actually gonna like troll about and see if i can find a good song bar for a good price and i did and I bought it so having a black friday sale at this point in time meant i bought that particular thing.
Speaker 1
But if they never had a Black Friday sale, would you have waited two years to get a Black Friday deal? Or would you have decided, I'm going to buy it?
Speaker 2
Well, I didn't have a specific model in mind until now. So I just knew that electronic equipment is is sold on black friday it's nearly always discounted around this time of year i like do people think of things like that with wordpress products And plugins and web sass stuff as in wait for black friday yeah so there's the black friday thing i think katie keith has loads of like thoughts on this she's run like experiments and put Stuff out into the world, so maybe try to track down some of her content on whether Black Friday works or not. I think it's been a bit hit and miss. I think they sell a lot because it's discounted. It's not quite right. I think it'll work.
Speaker 1
I mean, why won't it work? You're probably going to sell products around Black Friday if you've got a Black Friday discount. It's not rocket science, is it? People are going to – anyone who was in two minds, and, like, they jump on, oh, they've got a Black – oh, right, okay, I'll buy it now. So I don't quite understand, like, that will work, but you're selling it for less than you thought it was worth. Yeah. And if the case is, well, actually – hang on. Most customers aren't buying it. They're just waiting until Black Friday. Why not just make the Black Friday price the price?
Speaker 2
And then you'll sell them all year. Yeah.
Speaker 1
Because that's the price you want to pay for it.
Speaker 2
I really don't know.
Speaker 1
The one company that I think jumps into mind is Apple. They don't do sales. They just don't do sales. So no one feels they're missing out because they never do sales. So the price you see on the website is the price I pay, you pay, everyone pays. Yeah, that's true. There's no feeling of missing out or anything. The only thing they do is like the student thing, don't they? They get AirPods if you buy something for students. But that's it. That's all ([Time 0:29:07](https://share.snipd.com/snip/28179306-bc3d-4871-931d-bb1e3d3422c9))