In this episode, Jake investigates whether the existence of build tools is a symptom of the web being underpowered, or if they are part of the solution to make the web better. Surma shares his experience of learning about Bazel and how it can be used to build web projects.
Jake: Although "Terry's ringpull museum" isn't a real thing, the closest thing that comes to mind is a site I still use every time I buy a new pair of shoes, it's Ian's Shoelace Site.
Surma:All right, Jake, we're back. This is episode two of The Main Thread, which will surprise
Jake:All right.
Jake:Yes!
Surma:people because it's been a month. Yeah.
Jake:Rather than a year or two. Yeah, this is a... we're back on track. It's like the
Jake:old times, like, during lockdown, where we literally had nothing better to do than this.
Surma:Yeah. Let's see how quickly we can disappoint people again.
Jake:Did you think that's what we did last time? We were quite rusty. We should tell people that we,
Jake:the previous podcast people heard,
Jake:was the second recording, because the first one was just too rubbish.
Surma:Yeah, a bit boring, right? We're just a bit out of practice. And still, I think the last podcast, well, it was actually, I have to say, it was really, really lovely
Surma:seeing both the excitement leading up to the release and then the positive response after
Surma:release to our very first new episode. That really was quite energizing, which is probably
Surma:part of the reason why we were like, yeah, let's just lock in the next day to immediately
Surma:record one. But yeah, like listening back to it, still a bit rusty, still a bit of synergy.
Jake:Mmm, a lot of rust. Yeah. But in this episode, I want to talk about
Jake:build tools and whether they're a symptom of a problem or whether they're part of a solution.
Surma:Well, I'm going to talk about build tools. It is. Yeah, I'm gonna I'm gonna go a bit
Jake:And what are you going to talk about later on the show, Sam?
Jake:Oh, it's a very build tool heavy episode. That's exciting. Oh.
Surma:into a build tool that isn't popular on the web, I'd say, which in general probably isn't.
Surma:And we're going to talk about Bazel, the thing that Google open sourced. No, but it's nice
Jake:Excellent. Oh, okay. That's exciting. And we should say,
Jake:well, I am going to say that this podcast is sponsored by Shopify,
Jake:by which they let us do this and pay for the hosting and editing. And it feels like I have
Jake:to say that. They're not asking me to say that, but I'm just so happy that they're paying for it.
Surma:to acknowledge that, you know, they said, you go do your podcast while you work for
Surma:us as well. So that's nice. Indeed, I have ever told you that I find the phrase moving
Jake:So I'm in a new location because I have moved house since we last spoke.
Surma:house very weird as an ESL because not moving the house with the contents. I mean, unless
Jake:Oh, that is true. Huh.
Surma:you actually did move your house, which would be deeply impressive.
Jake:Oh, God, no. It was complicated enough, what we did. And our intention was to be in a different
Jake:building at the end. So, yeah, the buildings remained where they were, thankfully, throughout
Jake:the process. But the process of, I know, it's like such a privileged whinge. But the amount
Surma:But anyway, I'm going to talk about Bazel, the thing that Google open sourced. No, but
Jake:of people you just sort of hemorrhage money to that I don't understand what they do.
Jake:I got an email from our solicitor and it said, this was all part of the agreeing the contracts.
Surma:it's nice to acknowledge that, you know, they said, you go do your podcast while you work
Surma:for us as well. So that's nice. Indeed, I have ever told you that I find the phrase
Jake:And this email said, I have taken a release from the buyer solicitor and have given a release
Surma:moving house very weird as an ESL because not moving the house with the contents. I
Jake:to your seller's solicitor. And maybe it's because I have the humor and wit of a 13 year old boy.
Surma:Yeah, strong release.
Jake:But that sounds like farts to me. Does it sound? Yeah. And so I've just got this vision of the way
Jake:that whole process of moving works is it's a load of solicitors in a room
Jake:cupping their hand, farting into it, and then kind of throwing it at each other in a very
Jake:theatrical kind of Harry Potter wand battle kind of way, but throwing farts.
Surma:I imagine it a bit to be like the touching cloth in terms of atmosphere, the touching cloth sketch.
Jake:Oh, we will put a link to the touching cloth sketch because it is
Jake:an absolute, it's one of my favorite sketches and features. Yeah. Award-winning Olivia Coleman
Surma:Especially because it's Olivia Colman. And you just.
Jake:talking about poo. I must have told you this before, but I, to one of the directors at Google,
Jake:I told, I was talking to her about a thing I'm working on and I was like, I'll just send you
Jake:a link to it. And I pasted the link, but it wasn't the link I intended. It was just whatever
Jake:else was on my clipboard at the time. And it was that sketch.
Surma:Enjoy. Oh, yeah, that stuff you've sent me that I think would have been probably many
Jake:And when that happened, I was like, well, that's embarrassing, but do you know what?
Jake:Could have been worse. Could have been much worse.
Surma:HR violations, so. She has a sense of humor while also being extremely important, TM.
Jake:Yeah. Although it was, it was to Parisa, who is head of Crow Knees. I can't remember her title,
Jake:but she is a good person and definitely saw the funny side of it. Absolutely.
Jake:Yes. Important and competent. And that sense of humor. What a mix. What a mix.
Jake:Anyway, what have you been up to recently?
Surma:What have I been up to? Oh, you know, I flew to to Austria with my partner because they
Surma:were giving a talk there and I was just, you know, along for the ride. And what really
Surma:stayed with me for some reason, you know, sometimes you witness an interaction and you
Jake:Ah. Yep, yep, yep.
Surma:just keep thinking about it. And this seems like really mundane. But for some reason,
Surma:I watched two passengers on the airplane squeeze past each other, kind of like the typical
Surma:British, like, oh, apologies. Thank you. Thank you. I'm so sorry. And then saying,
Jake:No one enjoys flights.
Surma:enjoy your flight to each other. And I keep dissecting this three word sentence, enjoy
Surma:your flight. When they're both on the same plane and we all know it's not going to be
Surma:that enjoyable. But what a weird thing to say, I thought. I mean, you know how.
Jake:It's true. Yeah. Well, I mean, if one of them's in first class and one of them is in
Jake:economy, then there might be relatively different
Jake:enjoyments. But as you say, it's not going to be.
Surma:Inter-Europe flights, the business class is the same seats, but the middle seat has a
Jake:Oh, of course.
Surma:table duct tape to it. It's the same.
Jake:Yes, that is, yes, that is true. I've only, I got upgraded to one of those ones and it was
Jake:a massive disappointment. Although I was, I was sat next to, well, not next to, because obviously
Jake:the table is blocked out. Michael Portillo, who is a politician who now, instead of doing politics,
Jake:does documentaries about trains. And my, my friend who I was originally going to be sat next
Surma:Are you not massively into trains?
Jake:to, who was now a few rows back, is massively into his trains. And so there was, it was a huge
Jake:point of jealousy because I didn't, I didn't, I didn't bother Mr. Portillo about anything,
Jake:at least of all trains. My friend was absolutely furious. I, do you know what? I have spent years
Jake:as a commuter, which has really soured trains for me. Like, yeah, just horrible means to ends.
Surma:Yeah. In a way, yes. Although I've recently learned about the Emirates cabin class, which
Jake:Much like planes.
Jake:Oh, absolutely. And I, and I still might, I mean, maybe that will be different, but my,
Surma:is higher than first class. We have a whole cabin, like a closeable little cubicle with
Surma:a door. And yeah, I don't know. I didn't look up how much it costs, but it's like, that
Surma:looks nice. It's probably also going to be inaffordable to anyone.
Jake:my theory on air travel is that it's, no matter what class you look or pay your way into,
Jake:it's, it's still worse than, like, or you'd hope it's worse than your destination, right? Like,
Jake:it's still, you know, it's like, oh, this, this, I'm in a seat that, you know, for 10 hours,
Surma:Yeah, it's kind of like you're just offsetting yourself from the worst case within this flying
Jake:that costs thousands of pounds or does at normal price. And it's just not as nice as my sofa at
Jake:home or as nice as my desk chair. You know, it's, it's, you kind of, it's a feeling of relative
Jake:luxury, but not actual luxury. Absolutely. No, when I'm paying for flights myself, my,
Surma:metal tube. I agree. Fully agree. Let's talk about the web.
Jake:my attitude is, I don't, I don't know if I could pay less and just be strapped to the wing of the
Jake:plane, I would, because I will, I, it just feels like such a waste of money compared to like
Jake:spending the same amount at the destination on a nice meal or something. Should we talk about the
Jake:web? I genuinely didn't know that you were going to talk about, and I knew you were going to talk
Jake:about Bazel at some point. I didn't know you were doing that in this episode, but that's kind of
Surma:There's our title.
Jake:great because it makes it the big build tools bonanza, which I feel we might have, have we
Jake:done that before in another podcast? Anyway, let's, let's, let's assume, let's assume we're not
Jake:retreading entirely old ground. But yeah, I kind of wanted to talk about where build tools sit
Jake:in, in the way we build websites and whether they're a good thing or not. And if we come to
Jake:the conclusion, no, then it's going to make your section very redundant. But here's the thing,
Surma:Okay.
Jake:we're not. So a bit of a spoiler alert there. When I first used the web, I was on a 14K modem, which
Jake:was a little old even for the, for the time, but just browsing around the web, like the whole
Jake:communication aspect of it, I found absolutely amazing. And I was looking at sites like,
Jake:I don't know, Lisa's photos of disused underground stations or like Terry's ring pole museum,
Jake:like these proper sort of niche weird sites. But what struck me is like, until this moment,
Surma:Dun, dun, dun.
Jake:I was used to getting information from large publishing houses or like broadcasting
Jake:corporations, but like, that's not what Terry and Lisa were part of. They weren't backed by
Jake:these companies. So how were they doing it? And I found a little menu item in the browser I was
Jake:using at the time, which I think was probably Netscape. And it was view source. I know. Yeah,
Surma:Oh, for sure.
Jake:but it blew my mind because I was now like, I, like, you know, I'd been using computers a long
Jake:time before this, like playing games and stuff. And I'd always wondered how they worked, but you
Jake:can't in a, when you're playing a game, you can't just right click and go to view source. But, but
Jake:here I was looking at how the site was put together. And I could, I could start to map
Jake:bits of the code I was seeing to the site I was seeing. And I was like, it was how I got into,
Jake:into web development.
Surma:My origin story isn't on the web, but I had a similar driving force because for me, what
Surma:I want to find out is how do you make .exe files? Because it was a mystery to me. I looked
Surma:at them on my computer, I drag and drop them into notepad and that was gibberish. And I
Surma:sometimes sound individual like sentences and there are words and I tried changing them
Surma:and then everything broke because I didn't know. Because I didn't know it had to be the
Jake:Broke. Yeah, I've done that too.
Jake:Yeah.
Surma:same length. And that's what I literally remember asking like, how do you make .exe files?
Surma:Which is such a funny question to ask. But yeah, the web is then what I did actually
Surma:took my very first steps and it's like I write it in an editor and you open in the browser
Surma:and it does a thing. That's kind of amazing.
Jake:And you make a great point because I had done the same exe thing. And but then I did it with
Jake:a webpage. I saved the, you know, did save as, and I had a HTML file on disk and I went in and
Jake:changed it thinking because of the whole exe file thing, it's like, well, this isn't going to work.
Surma:Yes.
Jake:And then I dragged it into a browser. I was like, what? Like I have modified,
Jake:successfully modified this website. But I saw a talk recently that did like the same
Jake:view source thing with a modern website. And the code was
Jake:illegible. Like, particularly like those, those big class name lists, like that were
Surma:Oh, I have so many opinions and feelings.
Jake:illegible, like a couple of characters each, lots of different class names in a, in the HTML.
Jake:It was, it was probably tailwind, but minified. And the question that was being put is like, you
Jake:know, the, the web has sort of lost its way. And, you know, have, have we,
Jake:have we lost something from, from those early days where we both played around with, with view source?
Surma:But I guess you also have some. So.
Jake:I do. I do. Do you want to know them?
Surma:Yes. Tell me Jake.
Jake:Right. Okay. So I would consider myself part of the old school web crowd. Like there's been people
Jake:who have been around a lot longer than I have. But I feel like I share more of their ideals
Jake:than perhaps some of the folks who started on the web at the same time as I did.
Jake:A few years into my career, probably five, six, seven years into my career,
Surma:What year are we talking?
Jake:like the front end framework started becoming a big thing. And I was, oh yeah. I was worried
Jake:you might ask that. So in, like, I'm talking like Angular, Ember.
Surma:Yeah, I was going to say it strikes me as like a I would have liked hearing that statement.
Surma:I would have said, you know, 2010, 2012.
Jake:Yeah. Between 2010 and 2013, based on a blog post I wrote around the time.
Jake:That's the only hook I've got. But, you know, I was against these sites because they were
Jake:serving like an empty body tag and then doing everything else with JavaScript.
Jake:And that resulted in a much slower and worse user experience than the patterns I was using already.
Surma:I remember trying Angular one like at that time or having to because one of the companies
Jake:I felt like these things came with a steep learning curve, in my opinion,
Jake:and a lack of escape hatches. We talked, I think we talked about this before.
Surma:I was working for used it and it did not click for me. I like the idea because I think Angular
Jake:Yes.
Surma:was one of the first ones where you had like you wrote your own implement your own HTML
Surma:tags almost like visually in terms of the syntax. But then you had what was it like
Surma:directives and services and like I was probably just not understanding the pattern, but it
Surma:did not click when I should be using what and I did not enjoy.
Jake:Yeah, I couldn't get over I couldn't get up the learning curve either. And even when I was
Jake:had something working, I would think, oh, if I just do it this slightly different way, I can
Jake:make it twice as fast. But the framework was like, no, this is not your project. Now it's
Jake:my project. And you may not do those things because I don't know those things yet.
Surma:Yeah.
Jake:And I thought that sucked. I hated that as a pattern. Like there were benefits in terms of
Jake:the DX, but I didn't feel they outweighed the cons, even in terms of DX. And so yeah, this is
Jake:how I kind of have the date in my head because I wrote articles about these issues like 10 years
Jake:ago. So back in 2013, about like, you know, here's the benefits of progressive enhancement
Jake:and these frameworks throw it away and it's not good. And like one camp, the old school web people
Surma:And that distinction still lingers around today. Right.
Jake:were very supportive of these articles. But like everyone who I was trying to reach out to at the
Jake:time, the framework folks were just like plain, just dismissive, saying it was old-fashioned
Jake:thinking. Or that the patterns that I was talking about were not for, well, they were for websites,
Jake:not web apps, you know.
Surma:Like, I mean, even I sometimes make a distinction where the web in itself has started to be
Surma:a lot more accommodating to what you would consider an app.
Surma:But still the kind of like the documents base type still bleeds through and you have to
Surma:work against it, especially at the start.
Surma:You know, in a native app, you think in display sized views and you can build that on the
Jake:Yes.
Surma:web, but it's not the default.
Surma:And I'm not saying it should be, but that's definitely one of the things we're always
Surma:like, oh, I have to do this thing again where if I want to think in apps, I have to build
Surma:this kind of like a view model in there somehow.
Surma:And I yeah, I guess it's both a benefit and a drawback of the web and it is backwards
Surma:compatible eternally.
Jake:Yeah, that definition of sites and apps is a really tricky one because I sort of get it and I
Jake:do refer to things, I will use the term website and web app, but there's no real definition of
Surma:Yeah.
Jake:it, especially it's like you can get the BBC News native app, but people will say that's
Jake:definitely a website when you're looking at it in a browser. But then you've got things like,
Jake:well, you use Wikipedia, but if you're editing an article, are you now, is it an app now rather
Jake:than a site? Like it's, I do, there are vague feelings whereas, oh, that feels like a site,
Jake:that feels like an app, but I think it's difficult to, hmm.
Surma:I think I think it's just much more of a spectrum.
Surma:I don't think there is a point even in defining a hard line.
Jake:I think that's, I think that's reasonable. I think that's reasonable. But as years went by,
Surma:Right.
Surma:Like, what do we gain from having a very specific line between you are a site and the other
Surma:ones are an app?
Surma:What decisions do you derive off of that?
Surma:For me, it's much more about, you know, offline caching.
Surma:Both benefit, although probably traditionally more associated with being an app.
Jake:I think newer frameworks had better escape hatches. I think React actually does a really
Surma:Yeah.
Jake:good job of this right now, although I worry they're going to make it harder in future.
Jake:But they had ways of generating markup as well. So you could serve HTML from a server or from a,
Jake:you know, static build or something like that. Although I think it even, it took a number of
Jake:years from that point before we had tools that were making good use of it. And we see that now
Jake:with like Remix, with Next.js, that kind of thing. And so, yeah, this is modern day now.
Surma:Yeah, there's no bitterness in your voice at all.
Jake:And some of the people who were dismissive about things like progressive enhancements,
Jake:like 10 years ago, are now championing it, even building tools around it,
Jake:even promoting courses around it. And I'm mostly happy about it, so it's fine.
Jake:No, not at all. But it's, hey, look, it is a good thing. I wish it didn't take us 10 years
Jake:to get there, but whatever. But okay, we still use build tools, like more so than ever. Like,
Surma:I'm biting my tongue so hard right now.
Jake:whereas back when I started on the web, you'd write the code, send that code to the browser,
Jake:and it would render on the page.
Surma:It's such a trigger to make me go on an opinion rant.
Surma:Please continue, Jake.
Jake:Are build tools a symptom of a problem that we should be solving,
Jake:or should we be leaning into them more? And like I said at the start, because, you know, whatever,
Jake:like, my take is that build tools are part of the solution, not part of the problem.
Surma:Thank you.
Jake:And I think, but I do feel this is where I start to split a little bit from
Jake:the more old school web crowd that I have kind of considered peers and friends. I still do,
Jake:but like, I've kind of shared their thinking on a lot of stuff, but this is an area where I really
Jake:don't. And I think the old school folks really dislike the upfront complexity of frameworks and
Jake:build tools. But like, I see the point, but things like Terry's Ringpool Museum,
Surma:Thank you.
Jake:that you can still build that in the same way it was built back then. It still runs today.
Jake:You can still build in that simple way. It's not that simple things have got harder,
Jake:it's that the harder things have become possible, but you need tooling and like other, like,
Jake:newer patterns in order to make that happen. Yeah, I hated earlier frameworks because they
Jake:took a mallet to the user experience over what I saw as a fairly modest net gain in developer
Surma:For sure.
Jake:experience, but that changed. And now these newer frameworks and newer tooling, they close that gap.
Jake:And I think it's possible now to use a framework and get out the other side,
Jake:better user experience and a better developer experience than you would without those tools.
Jake:And I do think that is mostly down to the build tool.
Surma:There's always this thing of like make better developer experience.
Surma:So you free up developers to create better user experiences.
Surma:And I think generally, I don't think that is universally true.
Jake:So,
Surma:If anything, you free up the developer to spend time on other things.
Surma:I don't know.
Surma:It's a cynical thing.
Surma:But every language, at least when it comes to compiled languages, has a build step.
Surma:And that is there because programs are a lot better at squeezing performance and doing
Jake:hmm.
Surma:optimizations and being smart about the code base as a whole in one go than humans are.
Surma:I mean, the simple example is nobody wants to write minified JavaScript.
Jake:So,
Surma:Nobody wants to read code where variables have one letter and figure out what the code does.
Surma:You want to write readable code so that other humans can work with that readable code.
Surma:But you do want to ship minified code to your web server because less bytes over the wire equals good.
Jake:yeah, and you're right, like decades before the web, we had, you know, languages that had these
Jake:build steps and it meant that, yeah, what you wrote was different to what the machine ran
Jake:because what the machine ran was illegible. Whereas on the web in the olden days, like,
Jake:you would have to pick a target audience for the code. Like, is it the developers working on the
Jake:code base or the browser that loads and interprets the code? And yes, so these frameworks that I
Surma:Yeah.
Jake:hated were leaning towards the DX side and, you know, making compromises on the UX.
Jake:But in my own projects, like, it wasn't perfect. Like, I was making DX compromises
Jake:in order to make it fast and smooth. But like you're saying,
Jake:build tools mean you don't have to make that tradeoff.
Surma:I think there was a phase where build tools, I guess like frameworks, would do things to enable good experiences that turned into worse user experience,
Jake:So,
Surma:both in terms of performance, in terms of accessibility, in terms of bundle size.
Jake:hmm.
Surma:But that is all kind of like caught up a little.
Surma:And I don't know if this is right to credit TypeScript.
Surma:But I do think TypeScript, to an extent, has just made the build step, having a build step, much more normal.
Jake:So,
Surma:And once you have it anyway, it becomes a lot easier to add other tools to it as well that do some of the other optimizations,
Surma:minifying your HTML, processing your CSS, and just having a bundler set up in general.
Surma:I think we started exploring what other work that is usually deferred to runtime can be pushed into compile time so that the site is smaller or faster and things like that.
Surma:And, you know, I guess the extreme versions of this is stuff like Svelte, where they have almost like a pseudo language,
Jake:yeah.
Surma:which is all JavaScript with slight additions, but just much more stuff being done on the developer's machine at build time,
Surma:so that it doesn't have to be running on the user's machine or phone when they load the page.
Jake:Exactly. And another example, this is
Jake:Facel folks. They, you know, were showing off their code, which appeared to have an SQL statement
Jake:in part of the front end code. And they were baiting people when they did this. They knew
Jake:what they were doing. But a lot of people got very angry about separation of concerns.
Jake:But I think a lot of developers are too quick to draw that line down things like
Jake:there's an extra separation of concern. Front end, back end, there's a separation concern.
Jake:I don't think it's, I don't, I think that's too simplistic a view of that. I think,
Jake:similar to that, yeah, front end and back end, it's not the right separation concern.
Surma:Hmm.
Jake:Component models are a better separation of concern, I think. But also, a separation of
Surma:Hmm.
Surma:Hmm.
Jake:authored code versus served code is a valid separation. And that's one that build tools
Surma:Hmm.
Surma:Hmm.
Jake:let us make. And that's why I didn't, I think you didn't agree either. I didn't agree with
Surma:Hmm.
Surma:Hmm.
Jake:this talk that showed like the ugly source code of some website. And it was like, oh,
Surma:Hmm.
Surma:Hmm.
Surma:Hmm.
Jake:this is horrible and bad. Because like, once the code hits the browser,
Jake:all I care about is, does that work well for users?
Surma:Hmm.
Surma:Yeah, and I guess there is like a sentiment that I understand in that it was really nice back in the days to be inspecting other people's markup and website and learn from it.
Surma:But I don't think that that is worth enforcing or like worth keeping at the cost of the users.
Surma:In the end, you know, like some pages are open source and you can learn from that.
Surma:And by using build tools, we haven't prohibited the learning experience that we had at the learning approach where you start writing just an HTML file in notepad and drag and drop into the browser.
Surma:That still works.
Surma:You can still do that.
Surma:And I think that's the more important part that there is not the binary format that you have to put into browsers, right?
Jake:So, yeah, I agree with that.
Surma:Like you want to be able to continue just writing stuff, have no build tool and get started understanding the fundamentals, the primitive languages, how they interact with each other.
Surma:But a build tool is just doing optimizations that otherwise would not happen because they're too hard to do for a human by hand.
Surma:And then the users would suffer.
Jake:Agreed.
Jake:Yeah.
Surma:Well, not suffer.
Surma:That's how it's pretty hard, right?
Surma:But, you know, they could have had a much better experience.
Surma:There's things that you would get for free.
Jake:Yeah. And although, in some ways, view source is dead, like, long live DevTools,
Jake:because they'll give you a tree of elements. It doesn't matter if all the white space is
Jake:missing in the actual text. It will show you the cascade of styles. It'll prettify minified
Surma:Yeah.
Surma:I mean, if people care about, you know, keeping ViewSource alive for their production websites, deploy source maps.
Jake:code to some extent or the source maps, that kind of thing. So, yeah, although view source
Surma:Yeah.
Jake:might look ugly, I think we've got tooling there now, which is much, much better at doing that job.
Surma:I mean, if people care about, you know, keeping ViewSource alive for their production websites, deploy source maps.
Jake:Absolutely. Absolutely. And, yeah, so, we can use build tools to let us write beautiful,
Jake:maintainable, readable code, source maps so people can inspect it as well. And we don't
Jake:have to compromise on performance and usability or, you know, that kind of user experience stuff
Surma:Yeah.
Jake:once it hits the browser. That isn't to say that all build tools and build setups are good.
Jake:We've talked about it on the show before. I really struggle with Webpack. I could never
Jake:understand Webpack configs and I could never get my head around Webpack plugins. It has been years
Jake:since I tried. It might be better. The docs might be better. The actual implementation might be
Jake:better. But I have had a much better experience with Rollup. And I still consider it a superpower
Jake:to go and read that. The Rollup docs are not long. You could just spend a couple of hours
Surma:I mean, if people care about, you know, keeping ViewSource alive for their production websites, deploy source maps.
Jake:and read the lot and then you know how to write plugins and it is like a superpower,
Jake:the things you can do with that sort of stuff.
Surma:It is.
Jake:Hmm. Yes.
Surma:We gave a whole talk on this, which we should probably link to.
Surma:For me personally, like Vite has kind of replaced Rollup as my standard starting point.
Surma:On the one hand, because the plugins are, the plugin interface is the same.
Surma:So the superpower mostly remains intact.
Surma:I say mostly because there is some minor differences.
Surma:Like, for example, in Vite, while the development server is running, you cannot emit additional files.
Surma:Because it doesn't actually run Rollup.
Jake:Hmm.
Surma:It runs ESBuild and its own implementation.
Surma:In an actual build, it runs actual Rollup.
Surma:So there it would fully work.
Surma:That's, it's in general, I think, something that you always point out.
Surma:Having a different setup between development and production is always a bit of a concern.
Surma:But so far, Vite has done it right.
Surma:And I mostly use Vite because it does the one thing out of the box that I found quite hard to teach to Rollup,
Surma:which is take an HTML file as my entry point, not a JavaScript file,
Jake:Yes.
Surma:where it actually figures out which CSS files are pulled in, which JavaScript files are pulled in.
Surma:It does all the right things.
Surma:It has support for CSS, CSS modules, JavaScript, TypeScript, JSX.
Surma:All of that is just set up by default with good default configuration,
Surma:but also always with the escape hatches to change the configuration or write your own plugins.
Surma:And so for the vast majority of little things that I end up writing, Vite has been absolutely brilliant.
Jake:It's it's I've played a little bit with it. And it's every time I start a new project,
Jake:I'm like this is the one where I should, you know, lean heavily into Vite. But I'm
Jake:I'm so wanting to get to the rest of the project that I don't and I just use some
Surma:Oh, that's completely fair.
Jake:Rollup setup that I've already. But I need to find the excuse to to use it.
Jake:So, OK, build tools are good, but I also don't think we should stop advancing the platform
Jake:because particular things are covered by build tools. And I really hope we can get to a point
Jake:where bundling is less necessary. So because right now we bundle into just a few JavaScript files,
Jake:meaning if you make a small code change, you're invalidating the cache of a big chunk of code.
Jake:We had this whole promise of HTTP2 was going to solve this, right? But it didn't really pan out.
Surma:Hmm.
Jake:But even in that world, even if it.
Surma:Well, mostly because if you don't bundle the files, like if they're separate files,
Surma:to get the similar loading behavior to bundled files, you would have to utilize H2 push.
Surma:Because when the first file gets requested,
Jake:Yes.
Surma:you don't want to wait for the browser to discover what are the other dependencies.
Jake:Yes.
Surma:The server would like to go, and here's all the other stuff as well.
Surma:But push turned out to be so hard to get right that it's been, I think it's basically been deprecated.
Surma:Like it's not recommended by anyone at this point, as far as I understand.
Jake:Yeah, I'm pretty sure browsers pulled it out of their implementations as well.
Jake:But it'd still be nice to get that back in some way that actually works. But even if it did,
Jake:I would still want a build step. I still want minification. I still want tree shaking. I still
Jake:want hashing, right? Like they're still important things that you don't just get by authoring files
Surma:I think we have.
Jake:and throwing them onto an FTP server or whatever. But one feature that I do think is going to make
Jake:a big difference is import attributes, which have recently landed in Safari and recently gained some
Jake:some TypeScript support. And we have talked about this before on an episode, a video episode of
Jake:HTTP203. Do you remember the episode, Simon? It's... Yeah, it was. Well, do you know what?
Surma:Wasn't that type assertions?
Jake:I don't even think it was back then. I don't think it even become type assertions.
Jake:But we were talking about the reasons some feature like that was needed because of
Jake:bugs in importing JSON. And this was back in 2020. So three years ago.
Jake:Just to catch folks up who haven't seen the episode, which I imagine is most people,
Jake:a spec landed saying that you can import JSON now. Go have fun. So it'd just be like import data from
Surma:Yeah.
Jake:like foo.json. There you go. Landed in the spec until someone pointed out, this is really bad
Jake:because the person who decides if that's JSON or not is the server. Because it's not done by
Jake:file extension. It's done by the MIME type, the content type that's sent as an HTTP header.
Jake:So you could import JSON, which you know is super safe, like really safe to import
Surma:Yeah.
Jake:because it doesn't execute arbitrary code. You're only just going to get an object back.
Jake:But later, someone, the other person, the owner of that site can just change it and start executing
Jake:JavaScript on your site. So people decided that that's a bad idea.
Jake:The thing that should control whether it wants JSON or not should be the page,
Jake:like the script, the thing that is, the place it is going to be executed or parsed.
Surma:Yeah.
Jake:So as you say, we got a feature called import assertions, which was import data from foo.json
Jake:with assert JSON. So you're saying like, go and import this, but only if it's in a JSON format.
Jake:And that was a decision that was made, therefore, both by you as the importer,
Jake:but also by the site. It still had to use the correct content type.
Jake:And it shipped in Chrome ages ago. And it was in stage three in TC39. But they changed the syntax
Surma:Oh, okay.
Jake:from, you know, it stopped being import assertions and became import attributes.
Jake:So it was import data from foo.json with type JSON. And I think it was just that rename
Jake:was the difference because it still requires the correct MIME type to be coming from the server.
Jake:So it's, yes.
Surma:And is there a list of like supported MIME types?
Surma:Because where is defined what that variable that I'm importing from that module, what it contains?
Jake:Well, it's down to the host by which, a host is the browser. And so the HTML spec defines JSON and
Surma:Right.
Jake:CSS as words that can be used. And Safari has shipped this, they shipped it for JSON, not CSS
Surma:Okay.
Jake:yet. But that works today in Safari. It works with the old syntax in Chrome. But yes, you could
Surma:That's quite interesting for bundlers.
Jake:have things like node or dno or bun, like defining their own. It's potentially a place where you
Jake:could end up with sort of namespace collision issues, but hopefully people are just sensible
Jake:and work with standards groups. Because that's how it always works.
Surma:Because I know that in our projects, we have always prefixed our import paths with a magic word and a colon, for example,
Surma:both to signify to readers that this is special.
Jake:Yes.
Surma:This is magic.
Surma:This will be processed by a build tool because it's clearly a non-standard path.
Surma:But also that then when we write the plugin, we could just check for the prefix to know should this plugin handle that.
Jake:I know. And that's exactly the thing I'm excited about. So, yeah, yeah. In our projects, I've used
Surma:That's actually quite nice to potentially detach those two concerns, separations of concerns, Jake.
Jake:like fake URL schemes to signify that this import is doing something special. I kind of like that
Jake:pattern. The pattern that typically happens is that a file is .CSS. So, therefore, the build
Jake:tool is going to come and do something special with it. And, like, I hate that pattern. Because
Jake:you look at it, and it's it just looks like a normal JavaScript import, except it's a CSS file
Jake:or an image or whatever else. Because I'm left with, like, well, what does it get out the other
Jake:side? What does it mean to import CSS? Does it get a style sheet object back? Does it get a string?
Jake:Does it get a CSS module kind of thing? Like, if I import an image, am I getting an image bitmap,
Jake:an object, a URL, base64 URL, a human take array? Yeah. And the way you find it out is by going and
Surma:Yeah.
Jake:looking through the webpack config or whatever. Because this thing is defined with regex. So,
Jake:it's not even easy to find. You've got to crawl through and find it.
Jake:And I actually think that that pattern recreates some of the bug with JSON imports. Like,
Jake:because the script is requesting it. But the script doesn't decide what it gets back out
Jake:of the other side. It's the well, not the server in this case, but the build tool that chucks out.
Surma:I mean, yeah, they're in a privileged role to begin with.
Jake:It's not a security problem, because the build tool and the source hopefully kind of trust each
Jake:other. They have to, really. Exactly. But it's the same DX issue. You don't really know what's
Jake:going to be spat out the other side. And as you know, there's another pattern which I hate even
Jake:more in build tools. And that's ones that look at the AST and go, ooh, this looks like new worker
Jake:and then a string. So, I'm going to take that string and I'm going to assume it's a module.
Surma:Yep.
Jake:I'm going to import it as a JavaScript entry point that can be used as a worker. Because
Jake:every time I use a plugin like that, or a project that uses a plugin like that, I will modify the
Jake:code in a totally legitimate way to do something I need to do. And I just pop off the rails of what
Jake:that plugin understands as a worker. And okay. But as you say, these import attributes give us a
Surma:Yeah.
Jake:standard way of dealing with this. Now I can say, like, import URL from cat.avif with type roll up
Jake:URL. Or, like, roll up image URL with sizes. If I wanted to give me a URL for the image, but also
Surma:Yeah.
Jake:the width and height of the image as numbers that I can do stuff with. Or import JavaScript as a
Jake:worker. Like, give me the URL to that that I can put in new worker or service worker or a worklet.
Jake:All of that kind of stuff.
Surma:I actually like the idea, the future that where bundler plugins, unless really otherwise necessary, just are listed as a mapping for which import types are they responsible for.
Surma:And you know exactly that they don't then basically wouldn't be allowed to transform the AST of other files, except the ones that are imported with their specific identifier in the import statements.
Jake:Finding municipality looks like a lot of things.
Surma:And so that would make it very easy to find in your bundler's config.
Surma:You see a roll up image URL with sizes identifier and you go to the list of plugins and you see a mapping from roll up image URL with sizes to a specific JavaScript function.
Jake:Let me have a look.
Surma:You can then switch it out or look how it works.
Jake:Exactly!
Surma:And it makes it so nice and clean to look at.
Surma:I really like that idea.
Jake:That's the future I want. That's the future I want.
Jake:Unfortunately we're not quite there yet and the reason is like I said that TypeScript has support
Jake:for this and it does but what it doesn't have support for is changing what's returned based
Surma:That surprises me, but I mean, should I say, oh, that seems like an easy fix.
Jake:on the type which sucks.
Jake:Well look they know it's a missing feature and there are discussions on it and like how
Jake:because right now you end up with like one d.ts file mapped to one file but now you're
Jake:going to have a system where like one d.ts file is going to map to one file and the different
Surma:Yeah.
Jake:types it can be imported as but you know they just need to go and solve that problem and then
Jake:everything's good.
Surma:I mean, it's already a bit like, you know, like when we use our previous approach.
Jake:Mmm.
Surma:With, you know, like a special marker string at the start of the import path.
Surma:We had to solve this problem with what TypeScript gave us, which is you just declare module, like a user, you know, missing types DTS ambient module.
Surma:And you do declare module and do identifier colon star.
Jake:Yes.
Surma:This also works with other types.
Surma:Often you will find this in other projects where they have star dot CSS to define what will be returned when you import a CSS file in JavaScript.
Jake:Yes.
Surma:TypeScript can already do that.
Surma:I guess they will have to maybe potentially add new syntax for declare module potentially, but.
Jake:Well, I want them to go a step further than that. Like, I want them to do that,
Jake:because yes, for things like import an image as URL with sizes, it's like, right, okay,
Jake:whenever that's used, it's going to give you a URL and width and height numbers.
Jake:But I would like to get to a point where that can be done on a per file level.
Jake:So, like, if you've got a CSS file that's imported as CSS module, that it doesn't have to talk about
Jake:it in general terms. It could say, like, this specific file exports these properties when it's
Jake:loaded as, you know, type CSS module or whatever. Whereas right now you can just say it's like,
Surma:Yeah, I agree.
Jake:oh, it's an object with string keys and string values, you know. So,
Jake:being able to do it in individual d.ts files I think would be really valuable as well.
Surma:Well, let's, should we like, can we, can we link to a GitHub issue so people can comment plus one?
Jake:Absolutely. I can go and find that again. But yeah, I think we're on a good path. I
Surma:Yeah.
Jake:do think the web has changed in fundamental ways. I recently posted a silly 3D view transition
Jake:and a silly little demo and more than one person replied saying, can I get the code for this?
Jake:And I was a bit like, my friends, you have the code for this because you have the link to it.
Jake:You know, it was not minified. It was really simple. But I guess we have reached a stage
Jake:now where people assume that the source of a website is not going to be useful to them in
Surma:Yeah.
Jake:any way and they need the unbundled, unbuiltooled version. But I think where we are is much better
Jake:than where we were. And so I say that let's keep on build tooling.
Surma:Yes, on that note, Jason Langstorff, formerly Datlify, now does a really good YouTube channel called Learn with Jason.
Surma:Has started a new series called four web devs, one app idea where he has four web developers and all get the same concept given and they build it and then send it to each other and compare and critique.
Surma:And I haven't fully watched the video, but Cassidy Williams is the first one in this video.
Jake:Ooh.
Surma:And she built an app with no build tools.
Surma:She just hand wrote HTML, JavaScript and CSS.
Jake:Ooh.
Surma:And I was like, you go.
Surma:That's.
Surma:Really cool to see.
Surma:Also, it was really funny to see both the comments and reactions on Twitter where people were really surprised that almost said that's possible.
Surma:And I, it made me realize that it is, has become, I guess, a niche approach.
Jake:Ooh.
Surma:I do this all the time where I just, you know, grab object.
Surma:I give HTML elements and ID and grab them all off of document dot all just like quickly string things together.
Surma:But obviously, most, I guess, most starter kits, most people who start with document start a couple layers higher with a framework and a build tool in the middle.
Jake:Yeah.
Jake:Yeah.
Surma:So, yeah, has often Cassidy to showing off that that is very much a valid and completely capable approach to writing a web app.
Jake:Oh, absolutely. And like I say, you're considering, you know, when the code hits the browser,
Jake:you're considering the user experience the most. But if your users are developers who are using
Jake:that source to learn how to do stuff, then yeah, that's a great reason. And that's what I did with
Surma:Yeah, well, do you want to hear how I have probably offended the royal family?
Jake:the view transition demos and that's why I didn't minify them because, you know, it's a developer
Jake:audience. I want them to view source and I want them to have a good experience doing so.
Surma:And I'm not sure we can, we can leave this in, but I'm going to tell the story anyway.
Jake:Do you know what? Yes, I do.
Surma:And we'll see.
Jake:Okay.
Surma:We drove to London for friend's birthday.
Jake:Yep.
Surma:Dropped my partner off.
Surma:And I dropped them off.
Surma:At Green Park.
Surma:Cube station.
Jake:Oh, yeah. Very close to the Royals.
Surma:Very close to.
Surma:Yeah, Buckingham Palace.
Jake:Oh.
Surma:I had my dog in the back of the car.
Surma:I had lots of other stuff in the car.
Surma:And anyone who knows London knows parking in that area is virtually impossible.
Jake:I'm amazed you took a car there. You tend to only make that mistake once.
Surma:Well, we had reasons.
Surma:Well, I was just to drop my partner off.
Surma:I was then continuing on and was going to meet them somewhere else.
Jake:Ah, yeah.
Surma:But we were short for time.
Surma:That was the way to make sure they would make their appointment in time.
Jake:Mm.
Surma:So it was.
Surma:However, because we were late, we did a nonstop drive from Bristol early in the morning.
Jake:Yeesh.
Surma:And I had to wee.
Jake:Uh-huh. Yep. And there are famously, do you know what? Toilets at Green Park Station.
Surma:Yeah, but I'm in a car.
Surma:And I have a dog in the car.
Jake:Yep. Okay.
Surma:And there's nowhere to park.
Jake:No. Fair.
Surma:And I can't really leave.
Surma:My dog alone in the car, even if I had found a place to.
Surma:I was like driving around, trying to find like a spot or even just like an alley where.
Surma:You know, I could maybe put the hazards on and jump into a cafe or something.
Jake:Sure.
Surma:And you know, like and after driving around pretty much aimlessly, because this was getting very urgent, just like twice because I was even closer to Buckingham Palace and I did what any.
Jake:Yep.
Surma:Brave trucker would do.
Jake:I'm looking forward to this. Go on, then.
Surma:I, I, I peed in a bottle in my car right next to Buckingham Palace.
Jake:Yep. Mm-hmm.
Jake:Yay. And then you threw it into the big fountain while shouting, God save the Queen.
Surma:And.
Surma:And kill this one.
Surma:Maybe I should have done that.
Surma:But I.
Surma:That was the first in my life in general.
Surma:It's like I did see that.
Surma:And there was a CCTV camera.
Surma:And now I'm wondering if anybody has this tape.
Jake:Oh.
Surma:But I, I don't know.
Surma:I feel like is this is this a rite of passage as a British citizen?
Jake:What, to have a book pal peepee?
Surma:Yeah.
Jake:I've not done it myself because I have gone at the station, though, so I guess it counts as my
Jake:book pal peepee. Well, your joining pack is in the post. You can now be, I think, racist towards
Surma:Yeah, well, let it count, because it's obviously a thing now.
Jake:people coming to the country. I think that's what happens. You get your right of passage,
Surma:Ah.
Jake:and now you have to be like, close the door behind you and become one of those people.
Surma:I have been looking for that privilege for many, many times.
Jake:I've been looking forward to you talking about this topic for a long time, so yes, I am ready.
Surma:Should we rather talk about.
Surma:Well, I was going to say the web, but actually, this is not web, at least not super web.
Surma:Do you want to hear about Basel? Do you want to learn a little bit?
Surma:In fact, you have been staying away from a work meeting where I talked about Basel.
Jake:I know.
Surma:So you can actually not know what is coming.
Surma:It's, yeah, it's, it's, it's been a really interesting journey.
Surma:So I guess I should really make sure that people know what I'm talking about, because it is not a mainstream build tool, I'd say.
Surma:It is very much in use only at big companies with big products of like Snapchat uses it.
Surma:Uber uses it.
Jake:Is that right? His origins were in more of a typical C++ tool chain. Is that where it comes
Surma:Stripe, like all like fairly big names.
Surma:And I'm sure there's also smaller companies.
Surma:But when you look around, you don't hear about it a lot.
Surma:Naturally, especially in web development, because it was built for more projects.
Surma:But building, compiling is part of the process of Java, C++, now Rust and similar things.
Jake:from?
Surma:I think it was built at Google or like its predecessor is built at Google and still in use at Google called Blaze.
Surma:And I don't know exactly where the differences between Blaze and Basel are.
Jake:Mm.
Surma:But they're conceptually, and I think even syntactically, mostly the same.
Surma:And yeah, like, so it was built to do the things that Google needs to do.
Surma:Build huge Java code bases, build huge C++ code bases, and later on build huge Go code bases.
Jake:Mm.
Surma:So it has all of those things out of the box.
Surma:And very much you can, you can smell that it was made by Google, but you can extend it.
Surma:And it has been extended, which is where it actually becomes usable and interesting for large web code bases.
Surma:And so that's, that's the angle I want to talk about a little bit.
Surma:Like, because that's what this podcast is about, web stuff.
Surma:But I think it's first, it's important to note that Basel is not like Vite or not like Turbo Repo,
Jake:Mm.
Surma:what Vercel has published, which is also like big monorepos, because those are all JavaScript specific.
Surma:Basel is more like Make in that it's a build tool orchestrator.
Surma:So Basel itself doesn't do building.
Surma:It orchestrates other tools that do the building.
Surma:And in that sense, like Make, it invokes other tools and takes our outputs and does that multiple times recursively
Jake:Okay.
Surma:until the thing you want to have out the other end comes out the other end.
Surma:But yeah, so I'm going to talk about it in the context of web apps, because we now have lots of build steps in normal production web apps,
Jake:Mm.
Surma:which starts with, you know, you just have to take your TypeScript code and transform it into JavaScript code,
Surma:remove the type annotations and stuff.
Surma:But also, you know, SAS or CSS modules, all of those things are build steps.
Surma:This bundling is a build step and as such can be modeled in Basel.
Surma:The thing that a tool like Basel brings to the table is skipping work when it doesn't need to be redone,
Jake:Mm.
Surma:which sounds very simple, but it's actually quite hard to get right.
Jake:Yeah, this is something that I've not seen many web bundlers do
Jake:really well. It tends to be something you'll have in make rather than
Surma:Yeah, well, I think we're kind of getting there.
Surma:For example, you know, TypeScript, the TSC compiler introduced incremental builds,
Surma:which is that thing where it doesn't type check a file if it's already done it previously and it hasn't been changed.
Jake:empty.
Surma:Vite now has a cache as well, and especially tools like even Webpack has a cache.
Surma:Vite does as well, Rollup as well, but only while they're running in what is usually called watch mode.
Jake:Mm.
Surma:So they do everything, produce the output and they watch your source tree.
Jake:Yes.
Surma:And if a file gets changed, they are smarter about what work needs to be redone.
Surma:But if you kill the server and you restart it, usually it does everything all over again.
Surma:Even there, I think Vite now is starting to get better.
Jake:Mm.
Surma:But wouldn't it be interesting if not every tool had to reinvent these mechanisms?
Surma:Because it becomes a bottomless pit because then the SAS tool chain needs its own cache.
Surma:And then the bundling tool chain and the CSS model, each of those should start having their own cache.
Surma:That seems like wasted effort.
Surma:And so tools like Make take the approach like they have.
Surma:It's a bit like actually old school Unix philosophy where write a tool that does one thing and one thing well.
Jake:Mm.
Surma:And makes one thing is effectively knowing how to invoke build tools and knowing when it's not necessary.
Surma:And I guess I should maybe explain how without going into like how do you write a Make file,
Surma:but Make does this by annotating every command in your build script, so to speak,
Surma:with the input files that it needs and the output file that builds that generates.
Surma:And it then checks if any of the input files has a newer date, like a modification date, than the output file.
Jake:Mm.
Surma:And if that's the case, that means an input file has changed since it was last built.
Jake:Mm.
Surma:I need to rerun this build step.
Surma:And that's pretty much all the magic behind Make.
Surma:Of course, there's environment variables and all.
Surma:It is quite the complex system, but at a conceptual level, that's all Make is doing.
Jake:Mm.
Surma:Well, with Make, even you do at some point encounter it.
Jake:It's such a simple system, it starts to make me wonder why the web's build tools haven't done this, right?
Jake:Mm.
Surma:You run into a couple of problems.
Surma:For example, it doesn't really know when you upgrade your compiler.
Surma:Like the tool that you invoke, it doesn't know whether it's been updated since the last build
Jake:Mm.
Surma:or it can't really check that easily.
Surma:So if I, for example, were to update from if I used a Make file,
Surma:and I were to update from SAS version 19 to SAS version 20,
Surma:a Make file would not rebuild because it thinks the build is still completely out.
Surma:The input files haven't changed, but the tool has changed.
Jake:Right.
Surma:When it comes to actual compilation...
Jake:The output would be different, but it doesn't know that it needs to make it happen.
Surma:Yeah.
Surma:So there's a couple of things where Bazel goes a step further on this front.
Surma:On the first thing, it doesn't use dates.
Surma:While it seems to work quite well for Make, it always feels a bit fragile to me.
Jake:Yes.
Surma:I don't trust the dates on my files, on the file system.
Surma:Like if you unpack an archive, you can put arbitrary dates on them.
Surma:Bazel instead uses content hashes.
Jake:Hashes? Yeah, there we go.
Surma:Yeah.
Surma:So it's based on the content and it says basically, well,
Surma:if the hashes of the input files haven't changed, therefore, the output file wouldn't change.
Surma:Of course, it has to store that somewhere and there is your local Bazel cache,
Surma:but that's just a detail.
Surma:But in the sentence is an interesting assumption,
Surma:namely that if the input files haven't changed, the output will not change,
Surma:which means that Bazel assumes and enforces that every one of your build steps is,
Jake:Mm.
Surma:I could say, pure.
Surma:Like same inputs to the function must give the same output.
Surma:If that isn't true, Bazel will not be able to cope with it.
Surma:That's a very good question, Jake.
Surma:Basically, Bazel says your build steps need to be hermetic
Jake:Mm.
Surma:because what they want to achieve is cacheability and reproducibility.
Surma:They want to be able to roll back and rebuild the exact same version of your build,
Jake:Mm.
Surma:even from years ago.
Surma:So everything in your build setup needs to be explicitly specified and hermetic.
Surma:So in Bazel, not only are your files encapsulated in your build files,
Jake:Mm.
Surma:but also the tool chains, and that is stuff like Node.
Surma:So in Bazel, you specify which exact version of Node you want to use to do this build.
Surma:In that sense, now the tooling, your compiler or whatever, is part of the cache key.
Jake:Mm.
Surma:So it all becomes obviously files are hashed,
Surma:but not only are the files together used for the cache key,
Surma:but also what is your processor architecture,
Surma:which for JavaScript is technically not relevant,
Surma:but for compiled languages, it very much is.
Surma:But also, which exact tool are you invoking?
Jake:Mm.
Surma:What is the version of the tool? Where do I get it from?
Surma:Because Bazel also takes care of setting that up.
Surma:So if I clone a fresh Bazel project and I say, build it,
Surma:it downloads the tools.
Surma:Even if I have Node installed on my system,
Surma:it downloads the exact version to make sure the build remains hermetic and reproducible.
Surma:And of course, yes.
Jake:Mm.
Surma:Actually, that parallel is a good point because it goes further.
Surma:They also do these builds in a sandbox.
Surma:This is not like a security sandbox.
Jake:Nice.
Surma:It is more a sandbox where each build step is executed in a sandbox
Surma:where only the files and the tools that you have declared as inputs are there.
Jake:Mm.
Surma:So while your actual GitHub repository has loads of files,
Surma:if my build step is only about the CSS file
Surma:and the tool that turns that CSS file into a CSS module,
Surma:then while that script executes in the sandbox,
Surma:only that one CSS file will be visible.
Surma:It's as if the file system had nothing else but those files.
Surma:And that way, Bazel helps you discover if you rely on more than what you have specified.
Jake:Nice.
Surma:So really, in a way, it helps you be hermetic
Surma:and make sure that what you have is reproducible.
Surma:I should be clear that Bazel itself out of the box
Surma:doesn't know how to do JavaScript and bundling or any of that.
Surma:There is, of course, you know, it invokes those other tools.
Surma:But because they have to be hermetic and Bazel needs to know,
Surma:like, where do I download this tool?
Jake:Mm.
Surma:There's an ecosystem mostly by the people from a company called Aspect
Surma:which have written rules for, you know, JavaScript,
Surma:which does Node for TypeScript, which has a TypeScript compiler,
Jake:Mm.
Surma:ESBuild, Rollup, SWC, Jest.
Surma:There's a good chunk of off-the-shelf...
Surma:I'm going to call them plugins because it is kind of that,
Jake:Mm.
Surma:but in Bazel, they're called rules.
Surma:So they take care of all the heavy lifting.
Surma:What's really interesting is that they also take care of your dependencies.
Surma:So they understand the package.json,
Surma:which is actually correct. They don't look at the package.json.
Surma:They, in fact, ignore the package.json.
Surma:They require you to use the package lock.json
Surma:or the yarn lock or whatever.
Jake:Mm.
Surma:And the hash, and they actually...
Surma:Yeah, and the hash, they verify as well
Surma:to protect you from supply chain attacks, for example.
Surma:They make sure that what you're putting is exactly what is expected.
Jake:Mm.
Surma:Again, like, reproducibility is one of the big things of Bazel.
Surma:Right, so I won't be able to give a narrator tutorial on Bazel.
Jake:Mm.
Surma:I might actually see if I can write up a little example repository
Surma:where people can look at what it looks like to work with Bazel instead.
Surma:But what you do, like when you use make,
Jake:Mm.
Surma:you write a makefile, which is effectively
Surma:a series of command line invocations
Surma:with those extra annotations of inputs and outputs.
Surma:In Bazel, it's a bit more complex due to the nature of it.
Surma:And you write it in a language called Starlog,
Surma:which really is just Python.
Surma:They just remove... Yeah, it is really just Python.
Jake:Mm.
Surma:They just removed the abilities to have side effects.
Surma:So from within Starlog itself, you cannot access the file system.
Surma:You only can almost work declaratively.
Surma:Again, this is for the reason that Bazel wants to be able to analyze
Surma:what your build looks like before actually having to run it.
Surma:And it helps it yet again to be hermetic, to be pure,
Surma:without side effects.
Jake:Mm.
Surma:Under the hood, all what you're writing in Starlog
Surma:is usually macros, which are invocations of more macros,
Surma:which in the end boil down to rules.
Jake:Mm.
Surma:And rules just emit series of actions.
Surma:So everything in Bazel boils down to actions,
Surma:which are very simplistic, low-level activities like
Jake:Mm.
Surma:copy a file, run a command, take a file as output.
Surma:And you just chain those together arbitrarily complex.
Surma:What is interesting though, because they enforce this rule
Surma:of having to specify the tool and the input file
Jake:Mm.
Surma:and the expected outputs explicitly every single time,
Surma:Bazel gets implicitly for free this entire deep dependency graph.
Jake:Mm.
Surma:And when one single file changes,
Surma:it can immediately tell you which actions need to be rerun.
Surma:If a file didn't change, the copy doesn't need to be done.
Surma:It's already done. But if a file did change,
Surma:it knows exactly which path to the graph it basically has to take
Jake:Mm.
Surma:to get the refreshed output at the end.
Surma:And that's how Bazel gets so good at rebuilding very fast
Surma:because it is able at a very, very granular level
Surma:to skip work that doesn't need to be done.
Surma:And I will say this one thing, with Bazel,
Surma:the caching works.
Surma:Not once in my entire journey so far did I have to
Surma:wipe the local cache or any cache to fix a build.
Surma:It was always I who was wrong.
Jake:Mm.
Surma:While with Make, I definitely had the other experience
Surma:where I typed in Make, it said,
Surma:oh no, your build is up to date. I deleted the cache,
Surma:I ran Make, and I got a completely different output file.
Jake:Yes.
Surma:I think many people have encountered it, and I think with most build tools
Jake:Mm.
Surma:we have encountered that. I remember with Parcel as well,
Surma:which is a quite sophisticated tool chain
Surma:and does a lot of caching, but there I had it a couple of times
Surma:where I had to wipe the cache to fix my build.
Jake:Mm.
Jake:Mm.
Surma:So I should be clear, Bazel isn't perfect.
Surma:You can make them not hermetic, and sometimes it's necessary,
Surma:sometimes it's just what it is.
Surma:Especially, I think, in C++ land, which I haven't done with Bazel,
Surma:I have heard that there is just no way around
Surma:the fact that you need to link against operating system libraries
Surma:that are on the system, on the machine.
Jake:Mm.
Surma:And that is, of course, technically not hermetic.
Surma:I think, for example, on macOS
Surma:you need to link against one of the operating system libraries
Surma:for the kernel to even allow you to run it.
Surma:But to the most extent, they try to guarantee
Jake:Mm.
Surma:that these build tools are hermetic.
Surma:So I guess we should finally talk about web
Surma:and what it looks like building web stuff with Bazel.
Surma:If you take the rules for JavaScript,
Surma:you could just invoke stuff from NPM.
Surma:So I could just write a single rule and say,
Surma:And that would work, and that would probably...
Jake:Mm.
Surma:Exactly, you would...
Surma:Exactly, you would throw away all the benefits
Surma:that you might be getting.
Surma:But let's think about what a default setup with Vite
Surma:or our default setup with Rollup would do.
Surma:It turns all your TypeScript into JavaScript.
Surma:It bundles all your JavaScript.
Surma:CSS modules, which under the hood is,
Surma:on the one hand, mangling the class names
Surma:and then outputting a JSON file that has a mapping
Jake:Mm.
Surma:from the original class name to the new CSS model class name
Surma:and, of course, all the special CSS module directives that exist.
Surma:Maybe you have other stuff like you can import images
Surma:to get a path to the production URL of the image
Surma:or even the sizes, as you mentioned earlier.
Surma:You could even have stuff like if you import an SVG,
Surma:please run the SVG optimizer
Surma:before you add it to my production build.
Jake:Mm.
Surma:All these things are possible,
Surma:and most of these things end up being
Surma:plugins in modern build systems.
Surma:With Bazel, at the start, it feels a bit awkward
Surma:because of that sandboxing and the requirement
Surma:to having to list every single file.
Surma:It feels a bit awkward to just have to write that all down.
Surma:But it's definitely a bit different because it's even stuff like
Surma:your node modules folder won't be there
Surma:unless you specify it as an input.
Jake:Mm.
Surma:And now you can think about do you want the whole modules folder
Surma:or only parts of it, like specific packages?
Surma:Because, for example,
Jake:Mm.
Surma:if you update your test dependency, like if you update Jest,
Surma:that doesn't affect your build.
Surma:So really, ideally, you don't want
Jake:Mm.
Surma:to rebuild your project just because you updated your version of Jest.
Surma:You want your tests to rerun, but not the build.
Surma:And by default, the rules for JavaScript do the right thing.
Surma:But it's quite interesting to discover that
Jake:Mm.
Surma:these things actually are optimization angles
Surma:that you can benefit from. And on bigger projects,
Surma:all these things can add up to a huge difference.
Jake:Mm.
Surma:In Bazel, I actually ended up doing it a bit different.
Surma:So we are currently looking at Bazel at Shopify,
Surma:but instead of putting it all
Jake:Mm.
Surma:on one build tool and loading plugins,
Surma:we have tried to move most of the work
Surma:into either off-the-shelf CLI tools
Surma:from NPM or otherwise,
Jake:Mm.
Surma:or little one-off node scripts.
Surma:So, for example, instead of leaving it up to the bundler
Surma:to consume CSS and invoking a plugin on it,
Jake:Mm.
Surma:we have instead written a small script that invokes
Surma:PostCSS with a CSS modules plugin.
Surma:It takes a single CSS file as input
Surma:and outputs a single CSS file and a JSON file
Surma:with that mapping. And we run the script
Surma:individually on each CSS file, which sounds
Jake:Mm.
Surma:incredibly slow. And technically it is, because every time
Surma:you spin up Node, you load all the packages,
Surma:or actually, you know, you create the sandbox
Surma:with all the files, you spin up Node, you load the script,
Surma:you load all the required packages, you read the file,
Surma:you process it, and you do the output. But you only do that
Surma:once. And then the new output
Surma:files are now, together with your actual JavaScript
Surma:code, given to your bundler of choice.
Surma:In our case, it's esbuild, but you could use rollup. Later, maybe
Jake:Mm.
Surma:we can use rolldown when that becomes a thing.
Surma:And what is really interesting to me about that is...
Surma:Yes, that's the Rust rewrite that they're
Surma:working on. Yeah, but what's really interesting
Jake:Hang on, so just roll down, is that the Rust re-implementation of?
Surma:for me was the realization that we have
Jake:Mm.
Surma:decoupled our tools that do the preprocessing
Surma:from our choice of bundler.
Surma:Because if we wanted to migrate from, you know,
Surma:Vite or esbuild to rolldown, we would
Surma:have to make sure that the plugin exists for
Surma:CSS modules, but actually also that it's the same version of
Jake:Mm.
Surma:CSS modules behave the same way. Because otherwise, maybe
Surma:it's a corner case and now suddenly our app breaks. With this,
Surma:the CSS module processing is a separate tool.
Surma:And as far as the bundler is concerned, it's only consuming
Surma:JavaScript, nothing else. And that's actually also a performance
Surma:benefit, at least in our case, because esbuild,
Surma:being written in Go, does not
Surma:invoke Node or a JavaScript
Surma:engine unless absolutely necessary. So your plugins
Surma:usually... Exactly!
Jake:Oh, it stays in go land.
Surma:So it's parsing in Go, it's doing the bundling in Go, but if you have a
Surma:plugin, you have to register it with a regex
Surma:to say, only files that match
Surma:this regex should be handled by my plugin. And only then
Surma:does esbuild effectively shell out to Node,
Surma:which is, of course, full of overhead.
Jake:Yeah.
Surma:And so the one benefit is
Surma:esbuild gets to stay almost all the time
Surma:in Goland and be fast. But also
Surma:we have decoupled our
Surma:plugins from our choice of bundler.
Surma:And usually in esbuild, but also
Surma:rollup and other tools, when you restart the tool,
Surma:it would do all the CSS work and other plugin work
Surma:all over again. With Bazel now providing
Surma:a generic caching smartness
Jake:Mm.
Surma:engine almost,
Surma:it just reuses the previous
Surma:output. And so if you change
Surma:your JavaScript code, only the bundler gets invoked, which is now
Surma:very fast. None of the CSS stuff. And we've really seen some
Surma:very interesting numbers where that gets lots
Surma:of benefits in terms of
Surma:build speed, which is exactly
Surma:what we were after.
Jake:Mm.
Surma:Yeah.
Jake:Mm.
Surma:Yeah.
Jake:Mm.
Surma:Yeah.
Surma:There is a couple of things that are not as simple, which
Surma:I'm going to get to in a bit, or that have slight drawbacks, of course,
Surma:as well. But there is a huge angle for DX here
Surma:as well, because Bazel takes care of downloading
Surma:the toolchains and has all of that kind of codified.
Jake:Mm.
Surma:As I said, getting started on a project
Surma:that uses Bazel is as simple as just running
Surma:that Bazel command. And Bazel is published to
Surma:NPM. So basically, NPM run dev
Surma:can still work and it just runs Bazel. So as far as the developer
Surma:is concerned, they wouldn't even have to necessarily know that Bazel
Jake:Mm.
Surma:is being used. And because Bazel is agnostic, it actually
Surma:gets really interesting if you, for example, are a WebAssembly
Surma:user and you have multiple programming languages
Surma:at work. So I've been actually
Surma:thinking about for Squoosh, where we have
Surma:parts of it on Rust, part of it on C++ for a time we even had
Surma:a bit of AssemblyScript. Then the main app is TypeScript.
Surma:Actually, also almost like three TypeScript projects for workers,
Surma:for the service worker and for the main app,
Surma:built with Rollup. In Bazel, it is very easy to
Jake:Mm.
Surma:express that an output of the Rust project
Surma:should be an input for the Web project,
Surma:which currently is a bit shoehorned in.
Surma:And the main thing
Surma:where you can, well, at Shopify we're trying to save
Surma:time and money, but I think where even some open source projects could
Surma:benefit from is that the caching
Surma:while it happens on your disk can also
Surma:be stored remotely. So Bazel out of the box
Surma:is able to just put all these
Jake:Mm.
Surma:artifacts onto an
Surma:S3 or a Google Cloud Storage bucket.
Surma:And so if you make that bucket world readable
Jake:Mm.
Surma:or you give credentials to everyone,
Surma:Bazel will check whether a build step needs to
Surma:run. It will first check your local cache,
Jake:Mm.
Surma:but then it will check that remote cache and rather than actually building it,
Surma:it will just download the output, which
Surma:for longer builds, bigger builds like
Surma:Rust WebAssembly can be really beneficial
Jake:Mm.
Surma:or if you want to reduce
Surma:your minutes spent on GitHub Actions because it will just
Surma:download the artifact rather than building everything
Jake:Mm.
Surma:because maybe your PR is just a quick change
Surma:to one CSS file, which means you don't want to rebuild all the
Surma:bundling. There's a lot of things here where you can really
Jake:Mm.
Surma:squeeze
Surma:build time and performance out of
Surma:many things in your build pipeline by Bazel just like skipping work.
Surma:And I really like that they just allow you to just put in
Jake:Mm.
Surma:an S3 bucket and that is your remote cache now.
Surma:And again, it still works. Bazel's caching
Surma:factors in your operating system and architecture so that
Surma:you don't rely on artifacts that don't work for you.
Surma:I've been just really impressed with how reliable
Surma:the caching is, but usually caching is one of the hard problems
Surma:in computer science, isn't it?
Jake:Mm.
Surma:...
Surma:...
Surma:...
Surma:...
Surma:...
Surma:...
Surma:Yeah.
Surma:It is and I really
Surma:like that architecture as just like a mental
Jake:Mm.
Surma:model. But I guess I should then also talk about the things I
Surma:dislike about Bazel because it is
Surma:I definitely don't think it should in its current
Jake:Mm.
Surma:incarnation. It's not for everyone. It's not for every project.
Surma:You know, it's Bazel itself
Surma:is written in Java, then runs this Python like language
Jake:Mm.
Surma:and invokes all the other tools. It definitely has a
Surma:steep, steep learning curve and the documentation is
Surma:a bit meh. Like it's there. It's good.
Surma:But it definitely was a steep
Jake:Mm.
Surma:hill for me to climb. And the more
Surma:I look how specifically
Surma:the rules for JavaScript work under the hood
Surma:the more I feel a bit weird about it.
Surma:It obviously works and it works correctly and I think
Surma:they are the way they are for good reason.
Surma:But one of the things that they use in
Surma:the sandbox is that
Surma:to be faster, I suppose, they don't copy
Surma:all the files and tools you need into the sandbox.
Jake:Mm.
Surma:They use symlinks and for JavaScript that
Surma:can actually turn a bit into a problem
Surma:because if you imagine you're processing a file
Surma:as a bundler that is a symlink itself
Surma:and you have a relative import
Surma:like import a component from dot dot slash
Jake:Mm.
Surma:something. You are the bundler.
Surma:What do you do? Do you resolve that import to where
Surma:the symlink is or to where the actual file is?
Surma:And what if there's multiple levels
Jake:Oh, interesting.
Surma:of symlinks? And this has caused
Surma:many headaches for me to
Surma:figure out how to do the right thing.
Surma:Even Node itself because it actually executes
Surma:that line of JavaScript. You can tell
Surma:Node via command line flags to not
Surma:resolve symlinks or to resolve symlinks.
Surma:And both versions have caused problems in different scenarios.
Jake:I was going to say, resolving sounds like the right thing, in the same way that, oh, do you know what?
Surma:So what rule...
Jake:I was going to say, in the same way that, on the web, redirects are followed.
Jake:And now I'm losing confidence in that statement.
Jake:But I am 70% sure that redirects are followed and it's the final destination that is the module.
Jake:Oh, God, I don't know anymore.
Surma:Yeah, I mean if you want to dive
Surma:a little bit deeper for one minute. So as I said
Surma:you can specify that your input is the entire Node modules
Surma:folder or just sub-packages of it. So the Node modules
Surma:folder is a real folder but everything
Surma:inside is a symlink. Now if you
Jake:Mm-hmm.
Surma:written code without thinking about Bazel
Surma:a package could do something like
Surma:import dot dot slash other package name
Surma:because that would work in production.
Jake:Mm-hmm.
Surma:But now if you know you're in Node modules
Surma:your Node dot dot slash other package name will give you
Surma:the other package. Now in Bazel land
Surma:where you are actually somewhere completely different
Surma:on disk, if you don't resolve
Surma:the symlinks, then that still works. If you
Surma:do, you're importing nothing
Surma:or something different. And so sometimes
Surma:if your code base is written for Bazel
Surma:that's fine. If it wasn't for Bazel and you're migrating to it
Jake:Mm.
Surma:you will find lots of interesting
Surma:things breaking because of the assumption that
Surma:everything is actual files on the file system
Surma:and we just had lots of that. So that's definitely something
Jake:Mm.
Surma:and when I look at how these rules for JavaScript are implemented
Surma:they mostly make that work by
Surma:kinda injecting custom loaders
Surma:into Node that deal with all of that.
Surma:And I'm sure they did it right. I just don't like it
Surma:because it's not Node anymore. It is Node
Surma:with monkey patches. And again, I get it, but
Surma:I usually don't want that. And
Surma:it just feels a bit weird
Surma:to be honest. But yeah, I'm
Jake:Mm.
Surma:trying not to question it because the benefits just outweigh my
Surma:desire for purity, I guess.
Jake:There's a sign that it has not been built for the other tools that we use on the web right now.
Surma:Yeah, maybe. And I think
Surma:I was kinda thinking
Jake:But, you know, maybe that could change in future.
Surma:couldn't they add a flag where I say
Surma:for this build step, don't use symlinks, actually copy them
Surma:or use heartlinks or
Surma:I don't know, use a custom file system driver where you can actually
Surma:layer multiple things.
Surma:The other gripe I have
Surma:but it's not really a gripe, it's just something that has
Surma:caused frustration that in Bazel
Surma:the input file cannot be overwritten
Surma:by an output file.
Jake:Mm.
Surma:So every file name globally
Surma:in your build pipeline is pretty much
Surma:unique or at least can't be used at the same time.
Jake:Mm.
Surma:And that doesn't sound too bad, but I have had it where
Surma:for example, CSS modules where
Surma:I wanted the output CSS file to have the same name as the input
Jake:Mm.
Surma:CSS file, but Bazel would error me saying, sorry, your input
Surma:and output have the same name and that doesn't work. So I had to do
Surma:filename.process.css
Surma:and then figure out how to rewrite the import
Jake:Mm.
Surma:to now point to processed or to point to the JSON.
Jake:Oh, interesting.
Surma:So that's just minor nuisances and
Surma:you can totally deal with them. Overall
Surma:I find Bazel really interesting to think about
Surma:really interesting to work with and I'm genuinely considering maybe
Surma:not to merge, but just to try it out if I can migrate
Surma:Squoosh to it because I want to see
Surma:what it's like if people wouldn't have to
Surma:worry about having Docker or anything installed and could contribute
Surma:to both the codecs or just the web app with the
Jake:Nice.
Surma:same build tool. Mostly maybe as an experience report and then
Surma:potentially writing a blog post just to contribute to
Surma:one more piece of documentation for Bazel
Surma:out there. There's obviously a lot more I didn't
Surma:talk about. For example, Bazel can model tests
Surma:and applies the same smartness to tests.
Surma:As far as Bazel is concerned, a test is just a build.
Surma:So for example, the rules for Jest break your tests
Surma:apart into all the files and it will only rerun
Surma:the suite from a single file if any of the
Jake:Oh, nice.
Surma:inputs files have changed, which is really
Surma:smart. So it really reruns the tests that have been affected
Surma:by your code changes, which is really
Surma:good for stuff like CI where you potentially want to
Jake:Mm.
Surma:skip unnecessary work, unnecessary tests,
Surma:and still get a valid green checkmark.
Surma:So that's really interesting.
Jake:Mm.
Surma:It has, as I mentioned only in passing, this really
Surma:detailed dependency graph and that is actually
Surma:inspectable. You can write queries
Jake:Mm.
Surma:almost like a SQL query. It's a different language, but you can
Surma:write queries to figure out is there
Surma:some way where this package is imported by
Surma:that package and if so, how? Because for example, a problem we've
Surma:had is where the lazy loaded part of the app
Surma:was accidentally statically imported by the
Surma:initial part of the app. Bazel would help you
Jake:Mm.
Surma:write a rule that basically could fail CI when it
Surma:finds a static import edge from the
Surma:initial part to the lazy part and could say you did a bad.
Jake:Mm.
Surma:Don't do that. You could just express that as a
Surma:query. You could also visualize it as a graph.
Surma:You can find if you have multiple versions of the
Surma:same dependency from NPM in your app, all these
Jake:Mm.
Surma:things become quite easy to express.
Surma:Bazel can do remote execution because it does
Surma:this whole hermeticity thing where everything that is
Surma:needed, including the tool, is encapsulated declaratively.
Surma:Technically, you can just throw that at a different machine
Surma:and run the build there. So if you have a very build heavy
Surma:app, you can scale it out across a network,
Surma:across multiple machines and get a very easy build cluster.
Surma:And lastly, there's a...
Jake:This is what happens with Chrome, right?
Surma:Yes.
Jake:This is when they're building browsers that's a similar sort of pattern.
Surma:I guess lastly, there's iBazel, which is
Surma:the file watcher for Bazel. Again, because
Surma:it can inspect this dependency tree and
Surma:knows every single file and where it is used.
Surma:It is very good at knowing what steps to rerun
Surma:when you make a change. And iBazel just does this
Surma:automatically the second you save a file.
Surma:And that integrates really nicely within a dev server like Vite,
Surma:which just picks up the output and serves it to your browser.
Jake:Mm.
Surma:That is my current state of Bazel.
Surma:I probably should have said at the start, I'm still
Surma:in my journey of learning. I'm still very much a
Surma:beginner, so this should all be taken with a huge pinch of salt.
Surma:But I had fun. I have fun thinking about it and
Surma:using it. And I'm glad I was given
Surma:a reason to learn it.
Jake:Mm.
Surma:Yes.
Surma:Well,
Surma:I wanted to point out
Jake:Mm.
Surma:that we have managed
Surma:to record more than last time.
Surma:Look at us.
Jake:Mm.
Surma:We set this at 10 minutes,
Surma:and then we are roughly at the same time
Jake:Mm.
Surma:in the chat.
Jake:Mm.
Surma:And I'm glad we did.
Surma:We're not any
Jake:Mm.
Surma:further along on
Jake:Mm.
Jake:Mm.
Surma:a new sign-off catchphrase, are we?
Jake:Mm.
Jake:Mm.
Jake:Mm.
Surma:That was good, wasn't it?
Jake:Mm.
Jake:Mm.
Surma:Should we just do that?
Jake:Mm.
Surma:Because I enjoyed it too.
Jake:Oh, at some point I'm going to suggest going back to the old one, because I miss it.
Surma:Happy next time!
Jake:See you next time. Bye-bye!
Surma:Oh, are you kidding me?
Surma:I'm back.
Jake:End of the podcast sorted.
Jake:Maybe just every episode can be you going to the door and Watson barking, so.
Surma:It's how we roll.
Surma:Ooh, HMRC. That's not...
Surma:I'm gonna open this live on podcast now.
Jake:Oh, someone's done a fraud.
Surma:A self-assessment statement?
Surma:This is just... I did my job, isn't it?
Surma:Yeah, I did. I did my thing. All good.
Jake:Oh yeah, I...
Surma:I have not pulled any criminal activities into my taxes.