00:00:00.000 --> 00:00:06.240
Good DX also has to like weigh against, uh, having good user experience.
00:00:06.620 --> 00:00:22.109
So a lot of things that we do in next is also like running you for cases where, uh, you're going to affect user experience by including synchronous scripts, or you're going to include an image stack that blocks rendering of the whole page or, uh, that kinda stuff.
00:00:22.111 --> 00:00:34.189
Like in next 11, we, we have a lot of goal system of plugins that basically warn you like, okay, this is going to be a lot better if you make it, uh, like change it to, to use this other approach.
00:00:35.210 --> 00:00:37.350
And it goes for like phone preloading all that.
00:00:37.570 --> 00:00:42.859
And then like, from, from our perspective, we also try to get out of the way very often.
00:00:43.200 --> 00:00:56.859
So there are some conventions, but like, we're not telling you how to do data fetching, uh, particularly like where you're getting data from, how you're getting the data, because then you, you get the full flexibility of being able to, to build what you want.
00:00:57.479 --> 00:01:12.209
And that is also led to basically like seeing next sites from like a few pages, personal websites to like massive web applications that, that are served through to millions of people, uh, every day.
00:01:15.629 --> 00:01:16.370
Hi everyone.
00:01:16.549 --> 00:01:21.409
And welcome to developer experience a podcast by Algolia.
00:01:22.290 --> 00:01:30.239
We, we chat with guests who build products for developers about their developer experience strategy, what it means for them, why it's important.
00:01:31.019 --> 00:01:33.439
And so on, my name is Saha.
00:01:33.939 --> 00:01:40.560
And on today's episode, we are going to talk about how to nail down the right abstractions.
00:01:41.840 --> 00:01:45.629
Building abstraction is at the core of API design.
00:01:46.219 --> 00:01:55.629
They become the face of your software and they dictate a significant part of its developer experience, how to design the right abstractions.
00:01:56.420 --> 00:02:05.739
What is the difference between opinionated software and a failing abstraction to answer those difficult questions?
00:02:05.939 --> 00:02:08.500
I have two remarkable guests with me today.
00:02:09.400 --> 00:02:18.979
Tim Neutkens is the lead engineer of N JS one, if not the most popular and versatile react based framework.
00:02:19.520 --> 00:02:36.610
He also co-authored MDX an authoring format that will its U mix markdown and JSX team is responsible for many of the awesome patterns we love in next JS and largely contributed to its skyrocketing popularity.
00:02:37.189 --> 00:02:37.650
Hey Tim.
00:02:38.110 --> 00:02:39.090
Hey, thanks for having me.
00:02:39.430 --> 00:02:41.289
Our second guest is my homeboy, François Chalifour.
00:02:41.550 --> 00:02:45.960
François is a software engineer at Algolia.
00:02:46.509 --> 00:02:53.400
He's been working on Algolia instant search for several years, and co-author our recommend UI library.
00:02:54.300 --> 00:03:02.879
He also completely designed Algolia's Autocomplete library from scratch after over a year worth of work and research.
00:03:03.599 --> 00:03:03.599
Hi,
00:03:04.680 --> 00:03:04.919
Hey Sarah.
00:03:05.680 --> 00:03:05.800
All right.
00:03:05.860 --> 00:03:06.919
So let's get started.
00:03:07.520 --> 00:03:09.560
Building abstractions is difficult.
00:03:09.719 --> 00:03:22.469
I think we can all agree on that premise under abstracting kind of misses the point, but over abstracting can make your abstraction and unusable and force users to work against it.
00:03:23.520 --> 00:03:31.139
And when I look at next JS, it's really praised for how versatile it is, and it has many examples of really great abstractions.
00:03:31.520 --> 00:03:39.770
For example, uh, get static props is a really flexible way to pass data to a page, whatever the data, wherever it from.
00:03:40.039 --> 00:03:50.050
When I look in auto complete, you have things like get sources or the reshape API that open many possibilities for mixing all kinds of suggestions.
00:03:50.909 --> 00:04:03.000
So my first question, uh, for you both would be how do you approach building abstractions that solve problems the right will way, but also stand a test of time.
00:04:05.000 --> 00:04:11.740
So in next shift, we have pretty large premise in, in terms of like what the framework itself can do.
00:04:11.960 --> 00:04:33.310
So basically allows you to build complete websites, such web apps and go from like really small, to really large like applications and say like the, the way that we build things is it's always been around like some of the base principles that we've had since the very beginning, for example, creating a pages directory that's met to route.
00:04:33.850 --> 00:04:43.019
And then that basically allows you to build on top of this core set of features that we built and enhance stem over time.
00:04:43.920 --> 00:04:50.579
So an example that you gave with get set props, for example, that didn't exist when we, uh, introduced next.
00:04:50.850 --> 00:05:04.250
What we did instead was we created a like API called get initial props and we started, uh, using that you basically had initial server request get, get initial props will be called.
00:05:05.439 --> 00:05:11.000
Uh, then when you, uh, like then the, the content that is generated out of that is sent browser.
00:05:11.620 --> 00:05:17.759
And then when you start navigating around it calls get initial props on the, in the browser as well.
00:05:18.649 --> 00:05:26.699
So, uh, in order to reason about that, you basically have to think about, okay, this code is going to run in a, like no GS environment.
00:05:27.199 --> 00:05:31.620
And then after that, every single page change is going to run in your browser.
00:05:32.009 --> 00:05:35.540
That actually caused a lot of like confusion and issues.
00:05:35.689 --> 00:05:42.259
When next year it's got more popular, cuz basically you'd have to, to think about like, okay, it's going to run here.
00:05:42.370 --> 00:05:43.379
Then it's going to run here.
00:05:43.439 --> 00:05:47.610
And the environments are different code can break in different, uh, cases.
00:05:48.629 --> 00:06:17.350
And then like, how do I think about like this rendering then basically this process from like going from getting props to get static props to over like a year, year and a half or so of collecting feedback and making sure that like kneel down that abstraction in terms of like making sure that you could do still do the same things that you wanted to do, uh, in the first place of get initial props, but also give you the slightly more flex as well.
00:06:18.350 --> 00:06:24.870
Uh, so like what we landed on there is that get static props actually always runs on a notice environment.
00:06:25.470 --> 00:06:38.160
Um, so, uh, what that means is that if you like do a request to the page, it's going to like all aesthetic props, uh, at least in develop in, in, uh, production build, it's going to be aesthetically generate it.
00:06:38.680 --> 00:06:41.360
Um, that's like a whole different thing to talk about as well.
00:06:41.420 --> 00:06:50.560
But, um, basically, uh, then when you start navigating around, it's still going to do a fetch to the server to then get the props back.
00:06:51.519 --> 00:06:55.759
Uh, and uh, the reason that we did this is that it basically optimizes two things.
00:06:55.761 --> 00:06:59.709
Like the one is we saw that we we've got initial props, you have to do your own cashing.
00:07:00.250 --> 00:07:06.949
So that means that if you forget to like add any type of cashing into your get initial props, it would be slower.
00:07:07.709 --> 00:07:12.110
Um, and then the other is that the code is all running in the same environment.
00:07:12.250 --> 00:07:15.550
So you only have to think about reason about one specific case.
00:07:16.529 --> 00:07:29.129
And then, uh, the interesting thing will way of aesthetic props as well is that, uh, we did some more optimizations there that you're not aware of when you're using it, but later on are going to be, uh, massively important.
00:07:29.439 --> 00:07:42.079
Like when we introduced it, it was like, okay, this is a slight friction in so far that like, for example, you couldn't get access to request response like we did for, uh, get source props and get initial props.
00:07:42.699 --> 00:07:55.120
But the main reason behind that is that you can then start generating things at build time, for example, uh, or like izing them across multiple workers or making sure that you can run in different environments as well.
00:07:55.439 --> 00:07:59.079
Cause you don't get like variables that, that are very specific to one environment.
00:07:59.709 --> 00:07:59.709
Yeah.
00:07:59.711 --> 00:08:07.310
Like that is where, like that's one example of like how we like change API surface while also adding in more features as well.
00:08:08.009 --> 00:08:25.579
I'd like to go maybe, uh, maybe upper level when we talk about get static props, because one of the big things for me and like why I think this is really from, you know, a user perspective, why it's a really interesting abstraction is because how simple and powerful it is.
00:08:25.581 --> 00:08:26.699
And it looks kind of obvious.
00:08:27.089 --> 00:08:34.179
It's like you get a function that you name a certain way and you export it with a certain name so that the framework recognizes it.
00:08:34.759 --> 00:08:42.490
And it's just going to pass props to your component, which is your page and the way you fetch that data completely belongs to you.
00:08:43.070 --> 00:08:48.690
And it's a, it's a different paradigm than, uh, not to say it's, uh, it's less, less good.
00:08:48.691 --> 00:09:03.159
But like when you look at something like Gadsby, which is a similar product to next JS in terms of what it you can do with it, um, it's different in Gadsby, you would have to, to plug your source to, um, to graph QL.
00:09:03.259 --> 00:09:12.960
And then you would source from basically a centralized data store, uh, in X JS, you don't have this concept of centralized data store, uh, whatever the page is.
00:09:13.139 --> 00:09:15.590
It is kind of a contain environment.
00:09:15.669 --> 00:09:21.509
I think even every page run when you build every page, it runs in a single worker or threat.
00:09:21.570 --> 00:09:25.549
So you don't have access to everything else, but most of the time it's fine.
00:09:25.929 --> 00:09:28.830
And when you look at it at the end of the day, you're like, yeah, it's awesome.
00:09:28.889 --> 00:09:29.429
It works.
00:09:29.710 --> 00:09:41.019
Uh, of course they built it like that, but what's the thought process, uh, when you building the abstraction, what's the, the thought process of, yeah, this is how people want to fetch data.
00:09:41.049 --> 00:09:42.779
Some people will have files locally.
00:09:43.250 --> 00:09:50.259
Some people will want to maybe fetch some something on the GitHub API and cross reference it with some something else.
00:09:50.279 --> 00:09:55.929
So how do you approach designing such a core part of different mark?
00:09:57.110 --> 00:10:05.629
Yeah, so like when we started out, uh, building XGS, there was already this constraint of like, we need to fetch data from somewhere else.
00:10:05.740 --> 00:10:09.590
Like it's not going to be inside of the X app itself per se.
00:10:09.769 --> 00:10:17.750
And then like the first version of that was basically we need to have some kind of, uh, way to, to colon asynchronous function.
00:10:18.649 --> 00:10:23.389
And this is like when ay weight was like just a thing, uh, that, that people start using.
00:10:24.019 --> 00:10:28.830
Like we had to add in like async to generate or transforms that kind of stuff in order to make it work.
00:10:29.090 --> 00:10:33.269
But basically like eventually next didn't start out as a react framework.
00:10:33.470 --> 00:10:40.860
Actually it started out as a framework to build, uh, applications using its own template language as well.
00:10:41.940 --> 00:10:47.299
Uh, and then like later on, uh, before it was open sourced, uh, it was changed to use react.
00:10:47.559 --> 00:10:56.220
And then like we added some sprinkles on top of react, uh, at that point it's this is when like function components, weren't really a thing.
00:10:56.240 --> 00:11:04.970
It was like everything was glass components and that actually allowed us to use the static keyword to get like static, get, uh, get into props.
00:11:05.850 --> 00:11:10.570
Uh, so like on the component itself, you would put your, uh, like data fetching basically.
00:11:11.389 --> 00:11:23.519
And then what we said is basically like, okay, this is an asynchronous function it's going to block like, like before rendering, we basically, and this function call like being called and you as a user can get data from anywhere.
00:11:23.539 --> 00:11:28.399
So that could be from the file system or from a, an external API.
00:11:28.500 --> 00:11:34.879
And then in general, like what we saw in the beginning is that most of the apps that were built with next were built on external APIs.
00:11:35.909 --> 00:11:46.250
Uh, so this ended up being like, uh, or like cell API, separate repo, lots of microservices were all being called from the front end, basically.
00:11:47.090 --> 00:11:51.929
Uh, and then you didn't have this like, basically like this abstraction on top of, okay.
00:11:52.000 --> 00:12:09.039
Like I need to map all the values from the API into like a GraphQL compatible document or anything like that, or even like the API being GraphQL, cuz it was all, uh, microservices didn't have a centralized, um, like API, uh, router basically.
00:12:09.500 --> 00:12:13.230
And this has all changed over time as well, uh, for sale.
00:12:13.289 --> 00:12:17.149
But like at the time that like that is where very, it all started.
00:12:17.929 --> 00:12:28.269
And then like over time we, we got more and more usage and more and more use cases as well of people like either wanting to do data fetching from an external URL.
00:12:28.270 --> 00:12:29.710
Like that is fairly simple.
00:12:30.070 --> 00:12:30.789
It's a synchronous function.
00:12:31.029 --> 00:12:38.259
You just fetch it from somewhere or use the S K that like a CMS provider gives you and then you, you get your data back and then it renders.
00:12:38.779 --> 00:12:42.179
So like, that was always the thing that we wanted to preserve over time.
00:12:42.769 --> 00:12:56.210
Like later on we basically like started figuring out like, okay, how can we, like we see so many nexus apps out there, like simpler sites that are doing cuz nexus doing server site rendering really well.
00:12:56.309 --> 00:13:05.809
So like basically what you've got was every single page that you would request would be server site rendered from the like specific, uh, location that the app was hosted in.
00:13:06.110 --> 00:13:20.320
And it was like, generally not serve from a CDN, but we realized that a lot of the pages that we saw and people were tweeting and, and all that, uh, or gave feedback or showed us, uh, stuff for showcase these pages didn't even have to get initial props at the time.
00:13:21.659 --> 00:13:37.289
So, uh, what we realized is like, okay, we can make this optimization, uh, sort of like an abstraction on top of like, like here theistic for how can I make this page fast without actually needing the user to change anything about their app?
00:13:37.291 --> 00:13:39.169
Like they can just upgrade and it will be faster.
00:13:39.629 --> 00:13:49.450
So we started out with just static generations, like static generation of pages that did not have get initial props, uh, which we called automatic static optimization.
00:13:49.470 --> 00:13:56.279
And it basically means that if you have a default next app and you don't use get initial props, it would just be completely static by default.
00:13:56.659 --> 00:14:08.879
Now this has some, some trade offs as well, like some APIs that had to change a little bit, uh, or like the behavior that they had, uh, cuz of the not having the, the indeed request information.
00:14:09.480 --> 00:14:12.000
It's like, for example, with RA, like with the rider, that would be an issue.
00:14:13.000 --> 00:14:15.440
Um, but over time we, we fixed all those as well.
00:14:16.590 --> 00:14:30.690
It basically means that like when people upgraded to that, that specific version, they then got a, uh, aesthetically rendered page that would previously be source that rendered even though they didn't have to make any changes to their app.
00:14:31.409 --> 00:14:54.240
Cuz we knew from the constraints that, uh, react gives us that uh, a tree has to render without any asynchronous, uh, data fetching and all that, uh, that we could render it statically based on like if you're not using actually specific APIs and like over time that evolved into get static props, get server site props as well, uh, to, to basically cover a lot more of these cases.
00:14:57.019 --> 00:15:05.940
When, when I look at, uh, at autocomplete, one of the core parts of autocomplete is the get sources function, which allows you to return the sources for your autocomplete.
00:15:05.941 --> 00:15:15.370
And I cannot help, but think that there might be either inspiration at, it looks really similar to the concepts of get initial props.
00:15:15.370 --> 00:15:19.570
Ultimately it's a function that can be a synchronous and that returns data.
00:15:20.309 --> 00:15:23.090
How did you approach that when you design or to complete V1,
00:15:24.639 --> 00:15:36.149
But to complete V1, was that a library that aims at powering such experiences, but the way that we saw such experiences at the time was the, that rich search experience actually combines multiple sources.
00:15:36.970 --> 00:15:50.269
So we, we didn't want to be opinionated in terms of where you fetch the data, uh, which kind of rings it bits, uh, like Tim was mentioning about next, this kind of concepts are similar, but on pitch is a, is a library developed at Algolia.
00:15:50.409 --> 00:15:53.620
So of course we, we use mainly the last search engine.
00:15:54.259 --> 00:16:07.379
Uh, this is where auto computable shines, but Al doesn't provide any features like recent searches or favorite searches or of stuff like that because there is no value in Algolia, uh, actually, um, creating these kind of features.
00:16:07.720 --> 00:16:15.889
But we as a front end team, uh, realize that actually rich experiences, which search experie is must combine these kind of different sources.
00:16:16.149 --> 00:16:19.850
So this is where, uh, the get sources, uh, option actually came from.
00:16:21.250 --> 00:16:39.759
Uh, but then there, there was another, uh, concern that we had, uh, which was how do we actually transform the data that the search engine genes and that the sources, uh, return as the thing with databases and the web in general is show database, uh, is not a strict representation of how your website looks like.
00:16:40.019 --> 00:16:46.799
And with search engines, we oftentimes reproduce what the data structure is, uh, on the back end on the front end.
00:16:47.299 --> 00:16:51.000
But this is not usually is a friender way of showing the, the data.
00:16:51.940 --> 00:16:59.230
And this is where we introduce another API on top of gets sources, which we call the reshape API that actually entered these kind of cases.
00:16:59.730 --> 00:17:05.309
And the, the very first reason why we needed some kind of APIs like that was to remove, duplicate between sources.
00:17:05.450 --> 00:17:13.869
So there was one use case that we had, but we didn't really want to introduce an API just for removing duplicates in the search results, because there was quite limited.
00:17:14.509 --> 00:17:27.460
I like to think of by, in terms of what we call overfiting in statistics and overfiting is basically the, the production of something that correspond too closely or exactly to a particular dataset.
00:17:28.000 --> 00:17:39.930
And, um, it leads to having basically not matching any future observation that you get, or it's, it's good ifs the data, the data that you're training it with to accurate this.
00:17:39.931 --> 00:17:42.529
So it's not gonna be extendable in any sense.
00:17:43.549 --> 00:17:54.039
Uh, so we wanted to avoid this overing problem when designing the API, uh, which is why we, um, actually use some, some kind of, uh, patterns like in version of control and stuff like that.
00:17:54.210 --> 00:17:58.240
She's also quite similar to, um, get static props and this kind of APIs in.
00:17:59.299 --> 00:18:12.349
So the goal was not to just allow users to remove duplicates across the associates, but to allow low users to create on functions that place some transformation, for instance, they now can group their sources.
00:18:12.539 --> 00:18:15.589
They can sort their sources and they can do whatever they want.
00:18:16.019 --> 00:18:18.230
They can also package the presets themselves.
00:18:18.849 --> 00:18:28.789
So the way that we design the API is really, we provide you a hook where you can plug your own logic, which we're not gonna create an option for each of the use case that you may have.
00:18:29.779 --> 00:18:31.420
Uh, this is basically what we thought about it.
00:18:33.549 --> 00:18:51.559
One thing that I see in common in both ways of, of approaching obstructions is that is the simplicity and the attempt to stay as close as possible to the language or the underlying abstraction get sources is it's a function you can use whatever you want in it.
00:18:51.560 --> 00:18:55.240
Like you're not forced to use some other abstractions from the library.
00:18:56.200 --> 00:19:00.480
Uh, you don't have to learn things that the language already does.
00:19:00.579 --> 00:19:05.839
And I think it's also what contributes to the success of aesthetic props like once.
00:19:06.069 --> 00:19:06.359
Okay.
00:19:06.440 --> 00:19:11.079
I know I have to write a function that has that name and that's fairly easy to understand.
00:19:11.589 --> 00:19:15.549
I need to return it under a key called props, but that's about it.
00:19:15.650 --> 00:19:17.470
And then the rest is really up to me.
00:19:17.471 --> 00:19:26.670
So if I already understand the fetch API, if I already understand the file system API or whatever, um, this knowledge is not lost.
00:19:26.829 --> 00:19:32.700
I, I don't have to just dive into a bunch of documentation to simple things.
00:19:33.079 --> 00:19:56.079
So like this may be this tendency of trying to micro abstract and only abstract when it's necessary, but stop at the level where the software is going to understand it, but the user can be free to use what they know like X JS uses react and like they wanna use react the way they understand and they'll react.
00:19:56.080 --> 00:20:05.000
And if you add some something around it or some rapper around it, then maybe it'll not be retract compatible with the, the, the next versions, uh, of react.
00:20:05.019 --> 00:20:07.519
So it also contributes to the fact that they want to use next.
00:20:07.819 --> 00:20:40.579
So, so I think this is one of the things that I take away from it is that one way of designing abstractions that will spend a test of time is trying not to over abstract and trying not to make grand abstractions that kind of solve everything and hide everything, but rather find the little places where you need to have the glue and consider them as, as the glue and then recognize the power of other APIs and things that are baked in, in the language or the other abstractions that you use.
00:20:41.380 --> 00:20:41.670
Yeah.
00:20:41.809 --> 00:20:53.599
We usually have a, a three layer process at when we design APIs, which is, uh, okay, can we actually leverage the APIs that we have right now and just write some guidance, some documentation about it.
00:20:54.369 --> 00:21:00.069
And sometimes this is a good way to actually over time, better understand if the feature is actually required.
00:21:00.170 --> 00:21:02.109
Do we need to build an abstraction for that?
00:21:02.869 --> 00:21:07.420
Uh, do users feel some friction when they, when they're actually for the, for the guide?
00:21:08.339 --> 00:21:10.140
Uh, this is the first step that we try.
00:21:10.240 --> 00:21:15.019
We try usually to stop there so that we don't have to build new features and new abstractions.
00:21:15.980 --> 00:21:24.859
Uh, then we try to build features as plugins that could be adds middleware presets and stuff like that, uh, because they are not parts of the API.
00:21:24.920 --> 00:21:29.170
So they are easier to change and to deprecate usually.
00:21:30.279 --> 00:21:38.619
And the very last layer is actually creating a car feature, uh, which is sometimes required, but sometimes it's not.
00:21:39.000 --> 00:21:42.539
And this is where we think that most of the users could benefit from it.
00:21:42.540 --> 00:21:46.619
And there is value in having, uh, in actually reporting that in the product.
00:21:47.539 --> 00:21:54.130
Now, one of the, the interesting things with regards to next is that we actually don't have a plugin system per se.
00:21:54.730 --> 00:22:17.759
Um, so one of the, the que decisions that we made is that we give you this three low level, get static props that basically, uh, like solves the data fetching part and a don't get, um, like you don't need specific plugins per se, as like, okay, I'm going to hook into the whole system and then like have to back, like, make that back compatible as well.
00:22:18.640 --> 00:22:28.000
Uh, but instead you get this really simple, uh, like asy function contract where I can just import my, uh, like a Golia SDK, for example.
00:22:28.180 --> 00:22:43.950
And they use that to, to fetch data, um, and use that in my components then immediately, uh, as opposed to like having to install a plugin that then provides you with the SDK maybe in inside of the function or something like that is parameters.
00:22:44.509 --> 00:22:53.700
And like one of the, the interesting mistakes ish that we made with getting your props as well is that it's a function that just returns props.
00:22:54.440 --> 00:23:01.980
So that means you return an object and then that object is the, the thing that you can pass to, um, your component.
00:23:03.069 --> 00:23:09.730
But, uh, as you mentioned, uh, there, there is a, uh, like in tic props get server props.
00:23:10.039 --> 00:23:13.640
We actually return props an object that has the props key.
00:23:14.480 --> 00:23:19.720
Uh, this is very, uh, like a conscious decision that we made, which was okay.
00:23:20.119 --> 00:23:27.720
Uh, if we're going to introduce this new API, we need to make sure that we like can extend it as well, cuz because of Becker's compact.
00:23:27.960 --> 00:23:37.269
So like we're very, um, like keen making sure that you can just upgrade the latest version of next, uh, most of the time and have many tests to, to back that up.
00:23:37.769 --> 00:23:52.240
If we were to add a feature to get initial props, to return, for example, not fan page or something like that, we would start breaking, uh, existing apps, cuz those would be returning like not found with some other key that they they're using in their app.
00:23:52.720 --> 00:23:56.130
Um, so we've got set props, got server server props.
00:23:56.131 --> 00:24:04.930
You can actually now like you have to return props, uh, as the, the key in object, then next to it, we can actually return other things as well.
00:24:05.839 --> 00:24:10.039
It's like returning a redirect or returning, uh, not found, uh, that kind of stuff.
00:24:11.000 --> 00:24:28.339
Uh, and it basically allowed us to like over time evolve the feature set of get props, get server props as well, uh, where previously, like you would have to, for example, return not found as a property and then use our property to render, uh, for a four page in your page itself.
00:24:29.019 --> 00:24:33.289
Um, so like every page would be completely standalone.
00:24:33.290 --> 00:24:36.529
Like if you would render it with the props, it would always be the same thing.
00:24:37.609 --> 00:24:50.759
Um, and like over time we basically edit in these like sort of helper features where, uh, you can just return not found, it's going to do a lot of things automatically for you, uh, which is not possible way of getting props.
00:24:50.760 --> 00:24:51.160
For example,
00:24:52.549 --> 00:24:56.579
Frameworks and, and libraries usually strive for flexibility.
00:24:56.640 --> 00:25:12.410
You know, we want to cover many use cases and we, we, we don't want to overfit as you said earlier, uh, but many successful solutions and definitely thinking of next JS in, uh, when I, when I'm talking about that have opinionated parts.
00:25:12.910 --> 00:25:17.089
So for example, next JS uses a file system based router.
00:25:17.549 --> 00:25:24.490
And if you want to programmatically generate pages, you can, but you will kind of have to exit the framework.
00:25:24.490 --> 00:25:28.250
You will have to, uh, like write your own your own custom server.
00:25:29.200 --> 00:25:31.839
And it's going to take a few things away from you.
00:25:31.840 --> 00:25:35.880
For example, you will not be able to natively deploy to Versace.
00:25:35.940 --> 00:25:41.599
So it's like, there is this opinion about the framework that says, this is how you should do it.
00:25:41.819 --> 00:25:51.390
We think this is how most people, if not everybody should do it because, uh, like that's that, that's something that, that we've vetted.
00:25:51.390 --> 00:25:55.069
That's a decision, that's a conscious decision that, that we have taken.
00:25:56.029 --> 00:26:00.349
Um, and, uh, I can see the kind of, kind of the same thing in auto complete JS.
00:26:00.351 --> 00:26:06.069
So auto complete JS is the, like the VDO implementation of, of auto complete in auto complete JS.
00:26:06.070 --> 00:26:14.460
You can completely customize the sources, the terms, but the library fully controls the dam and the state of the surge box.
00:26:14.519 --> 00:26:24.339
So you can style it the way you want, but the way it's gonna, it's gonna behave like showing the, the loader and, and all of that, all of that is really hidden from you.
00:26:24.340 --> 00:26:26.539
There is no specific API to access it.
00:26:26.640 --> 00:26:39.410
So that's an opinion, uh, for, for other complete JS is that, that thing, we think that we are better off if we control it ourselves and you focus on your, uh, on your sources and your items.
00:26:40.230 --> 00:26:56.119
So my second question would be what is for you, the difference between the wrong abstraction and an opinionated one, when do you consider that it is time to be opinionated and when should you be more flexible?
00:26:58.519 --> 00:27:10.849
The main thing that we always opted for is that the app that you could build, like, like next, basically like the, the initial commit for next was a readme with the complete API dog for how going to work.
00:27:11.990 --> 00:27:13.069
Uh, there was no code involved.
00:27:13.070 --> 00:27:15.549
Like there was no like actual implementation there.
00:27:16.390 --> 00:27:23.910
Uh, the implementation actually came later, like basically went and wrote down, like all the things we wanted to solve basically.
00:27:24.049 --> 00:27:37.859
And that turned out to be like the first documentation page, cuz like for the longest time we had to read me being the, the full documentation and over time, like other feature for added and eventually that turned into the website to make sure that you could search it.
00:27:37.960 --> 00:27:42.019
And uh, and like it basically got way too large for a single page.
00:27:43.329 --> 00:28:10.690
Um, over like basically when, uh, when we started because of the debt core principle, like basically the initial, um, like with me still works today except for like some, uh, nuances way of styling, for example, like we switched, uh, styling in version two, um, because of the, like the initial version, not being the most ideal way to, to write CSS.
00:28:11.210 --> 00:28:26.180
Um, but over time, like that app that you would build with like pages, uh, and then like index suggests being mapped to the, the road route, uh, and then even get initial props, which was there from the start, um, that still works today.
00:28:27.079 --> 00:28:35.440
That was like one of the principles that we had like, okay, we're going to use this and evolve it over time.
00:28:36.569 --> 00:28:41.150
And then like incrementally improve it based on like feedback from users.
00:28:41.539 --> 00:28:46.390
Initially it was mostly driven by like internal needs Atell.
00:28:46.990 --> 00:28:55.849
So like, uh, and I'm talking end of 20 16, 20 17, 20 18, uh, like basically, uh, years ago now.
00:28:56.289 --> 00:29:12.740
Um, and, uh, that was mostly cuz we were the, the biggest user of next, uh, and then like over time other companies started using it, uh, especially in 2018, like we saw a lot of really large companies start using it with hundreds of developers.
00:29:13.039 --> 00:29:31.440
And that's when you, you start getting a lot of really detailed feedback on like, okay, like our, uh, our engineers are struggling with, uh, like this particular way of doing things or this API or like I, I keep using get initial props, but, uh, it breaks on the client side, writing is broken, that kind of stuff.
00:29:32.059 --> 00:29:35.640
And then like we started evolving that API service over time.
00:29:36.269 --> 00:29:46.400
Like basically like initially we opted for, and especially when, uh, when it started contributing to next, uh, we opted for like adding as many features as possible.
00:29:46.470 --> 00:30:00.329
Like anything people would ask, we would add it, um, uh, like customizing disc directories, like all kinds of stuff that wasn't super needed for the framework itself to function, uh, but did help some users.
00:30:01.039 --> 00:30:05.920
Uh, and during it, like that would be like at the time it would be like only a few people like in practice.
00:30:06.960 --> 00:30:08.279
Uh, and those features are still there.
00:30:08.280 --> 00:30:15.400
Like we, we maintained be with a lot of these, uh, these initial features that weren't as ideal as it could be.
00:30:15.819 --> 00:30:34.700
So like over time, like when, like we found that like there isn't better new of doing things or like making things easier or like evolving that we get the old API around, but still, uh, like highly recommend using some other APIs that are like journey easier to understand, easier to use.
00:30:35.849 --> 00:30:49.119
An example is like the end key in next config, um, that allow to basically create like global environment variables that you can access in clients that code cuz they're in line in the, the browser bundle.
00:30:49.700 --> 00:30:57.720
We evolve that to like, just have a, like, you can have a environment variable with a prefix called next, under public.
00:30:58.079 --> 00:31:05.190
And the score with that in front of your environment, variable, it's going to be, uh, inline into the browser bundle automatically.
00:31:05.329 --> 00:31:10.230
So then you don't have to add like next config items, uh, make sure that like those match up.
00:31:10.529 --> 00:31:19.230
And then even from the perspective of like you writing the code, it actually is a lot clearer that this is going to be inline into the browser bundle as well.
00:31:20.140 --> 00:31:24.910
But we still support the NP cuz like people are still using that as well for, for other cases.
00:31:25.470 --> 00:31:29.109
So like basically like over time, especially for next like things evolve.
00:31:29.529 --> 00:31:36.960
But the, uh, the nice thing is that they also like, in most cases, these conflict options don't add weight if you don't use them.
00:31:37.390 --> 00:31:44.069
Like what I mean by that is like, it's not going to increase browser bundle size cuz we actually tree shake away features that you Don use.
00:31:44.589 --> 00:31:46.029
Um, and stuff like that.
00:31:46.030 --> 00:31:52.670
So if you don't using international as a internationalized routing, it's not going to be added into the re end.
00:31:54.029 --> 00:31:59.109
Uh, if you're not using and it's not going to replace like all your environment variables for, for whatever reason.
00:31:59.410 --> 00:32:04.980
But then like also from the other perspective, we also give you full control over like the web.
00:32:05.680 --> 00:32:09.619
For example, at the time, for example, create react app, didn't allow you to do that.
00:32:09.920 --> 00:32:11.940
It allowed people to eject very quickly.
00:32:12.039 --> 00:32:16.380
People would basically start ejecting their app immediately when they needed to customize anything.
00:32:16.880 --> 00:32:24.420
We did allow that cuz uh, cuz some people asked for it and over time that that really helped the nexus community grow as well.
00:32:24.690 --> 00:32:33.490
Like there are people creating, uh, like customizations to next shares that relied on like compilations or like Webpac or like be config as well.
00:32:33.990 --> 00:32:38.690
And then like over time we started adding a lot of these customizations by default.
00:32:38.750 --> 00:32:44.519
So like if you want to import images, you can now import images, uh, using next image.
00:32:45.039 --> 00:33:06.269
Um, if you want to, um, do the same for SVGs that also works like set up record, like record threats or like web records that is, uh, supported by default in web now, uh, all those kinds of things that you would previously have to reach for, uh, custom ation you can now do by default or to conflict flag.
00:33:06.940 --> 00:33:14.390
That is basically like the, the interesting thing there is that it's actually really beneficial to not have custom configuration your app.
00:33:15.069 --> 00:33:23.359
Uh, for two reasons like the one is, uh, we know that your app is compatible, uh, cuz we have a massive test suite of integration tests.
00:33:23.420 --> 00:33:36.759
So we make sure that, uh, those all piles from every pool request, um, and the other is that, um, we can actually start doing optimizations that you would previously not be able to do, um, because you're using custom weapon config.
00:33:37.720 --> 00:33:49.829
Uh, so an example is if you had on web config, uh, you would be opted out of web five by default in order to, uh, make sure that we didn't break those apps by just like upgrading to the latest access version.
00:33:50.869 --> 00:33:52.630
Uh, then in major version we change that.
00:33:52.650 --> 00:33:55.670
So you can opt out of web five if you need to.
00:33:56.549 --> 00:34:11.579
Um, and then like eventually we can deprecate those options cuz people start naturally moving to the new, the newer thing, but in, in practice that, uh, like if you didn't have custom config, so if you didn't have custom weapon config, we would just opt you into epic five out of nowhere.
00:34:11.650 --> 00:34:21.130
Like you just upgrade next and you are on the latest, uh, version of WebEx, for example, you're leveraging, uh, discussing optimized, like usage.
00:34:21.320 --> 00:34:28.570
Like we created a new PLO that is much faster than the default one and added a bunch of other like cashing on top of that.
00:34:29.110 --> 00:34:32.489
And that would not be possible if you have custom config in all cases.
00:34:33.309 --> 00:34:41.010
So then we have to be really like careful in preserving, uh, backer's compatibility for, for those use use, uh, that use.
00:34:42.179 --> 00:34:50.440
And now like even looking to the future, like we're currently working on porting all the next year transforms.
00:34:50.440 --> 00:35:00.400
So like the things that we do in be a new risk based compiler called S WC and that's going to massively reduce bill times and development integration loop as well.
00:35:01.539 --> 00:35:08.570
Um, and in doing so, uh, like if you currently have custom be config, like we're going to opt you out and still use be for that.
00:35:09.090 --> 00:35:29.219
Uh, cuz obviously we don't want to break your existing app, but um, like the, the abstraction that we have of like, okay, we're going to compile it for you and you don't have to add configuration, uh, cuz like by the thought you don't really need it, uh, has really allowed us to evolve and make next, faster, over time.
00:35:29.320 --> 00:35:44.159
So like if you upgrade, um, like next year, uh, like 10 to 11 and you were using custom and it enables WebEx five is going to be much faster than, uh, than it was before you upgraded basically.
00:35:45.590 --> 00:35:45.880
Yeah.
00:35:45.880 --> 00:35:46.519
It's interesting.
00:35:46.719 --> 00:36:05.550
And in uh, in the computer, as you mentioned, sir, we were open 80 about some, um, UX and UI perspectives, like, uh, the search we realized, um, along the girls that uh, when users starts, uh, creating their own saltbox it's most of the time, very floated in terms of accessibility and even news age.
00:36:06.619 --> 00:36:14.360
So our thinking process was really, um, if some people should be good about building search boxes, it should be us really.
00:36:14.860 --> 00:36:31.269
So we decided, uh, for instance, in doc R B3 and also in auto D one, you kind of shift, um, in terms of we are not gonna just open some kind of dropdown to, to your own search, but we are gonna, uh, create the search for you.
00:36:32.070 --> 00:36:46.659
Uh, and this allow us to build, uh, way more complex and uh, interactive interactions with the user also for mobile purposes, uh, search experiences and mobile are quite different than such experiences on the web.
00:36:47.519 --> 00:37:07.769
So really there was a, our thinking also, um, this is one topic that we should actually, uh, be opinion on it about, uh, but for the sources and for the search results, we cannot be too native because this is very, um, custom based on, uh, on the user and the, and the, the use case of the website that they're building really could be eCommerce.
00:37:08.130 --> 00:37:12.969
It could be measure, it could be any kind of, um, of, uh, of vascular, really
00:37:13.789 --> 00:37:30.280
One thing you mentioned, uh, team, you, you mentioned the create react app and that it release, parked something for me because, uh, so last last episode we had, uh, we had the, um, Seck from and Aun talking about blending in other people could bases.
00:37:30.280 --> 00:37:40.869
And Aun mentioned that escape hatches are so important when you're building anything really whatever, and no disrespect to the, a create react app team.
00:37:40.871 --> 00:37:57.789
Like, uh, I use this for, for a long time, but, but one of the reasons that I stopped doing it and I actually moved on to, to next JS, which I use for most of my projects today is that for me, the line of opinions was maybe a little bit too far.
00:37:58.730 --> 00:38:22.969
And I enjoy when opinions are not like dictating what I should do without caring about what my specific problem is because at the end of the day, when you're, you're building an auto complete, which is already pretty focused, but when you get into it, you realize like the variety of use cases that you can tackle, uh, with a framework, a JavaScript framework, it it's probably even wider.
00:38:23.670 --> 00:38:26.690
People are gonna have different problems.
00:38:26.750 --> 00:38:32.969
And for me, when I was using create app, and I don't know if it's different today, but I wanted to use tailwind.
00:38:33.469 --> 00:38:40.480
And when you want to use tailwind, you need to have a custom post CSS file that that's it just because you want to use this framework.
00:38:41.400 --> 00:38:48.519
Uh, and that's not something that you at least back then were able to do with create react app without ejecting.
00:38:48.699 --> 00:39:01.380
And the problem that I had with this level of opinion is that it felt like this tool that was enabling me was suddenly telling me, okay, we we're letting you go.
00:39:02.179 --> 00:39:06.099
Uh, because you are going out of the road that he paved for you.
00:39:06.639 --> 00:39:14.380
And what I enjoy about, uh, a tool is when it tells me, okay, that's not necessarily the best way to do things.
00:39:15.199 --> 00:39:18.969
So this, you can escape that and it's, it's gonna be different.
00:39:18.969 --> 00:39:22.809
It's gonna be maybe a bit harder to do, but it's still possible.
00:39:23.150 --> 00:39:27.409
And that it understands to what level I will need to customize something.
00:39:27.929 --> 00:39:34.010
Uh, being able to have a, a custom post CSS file is definitely something that many people will want.
00:39:34.690 --> 00:39:37.840
Uh, maybe having programmatic grounds is not so common.
00:39:38.300 --> 00:39:48.039
And conversely, when I look at autocomplete, what I find interesting is that I can start with autocomplete JS, uh, and I'm going to be able to build a lot of things.
00:39:48.619 --> 00:39:53.840
And then let's say, I want to have my custom surge box because this is really something that I need.
00:39:53.840 --> 00:39:56.320
Like I need to be able to do something extremely custom.
00:39:57.110 --> 00:40:00.349
I can go to autocomplete core, but what's really interesting.
00:40:00.369 --> 00:40:12.829
So I, I will have this Ren less, uh, auto complete, uh, like library and then I can do whatever I want, but I will have learned from looking at how autocomplete JS is built so I can pick those principles.
00:40:12.831 --> 00:40:14.909
So it feels like I'm learning at the same time.
00:40:14.940 --> 00:40:24.380
Like you're learning the API and it's not like, well now you basically have a, a project that would be what you would've built if you had done it yourself.
00:40:24.380 --> 00:40:41.769
So I would say that's one of the limits, one of the lines that I draw between the right amount of opinion and too much opinion where it might look like, oh, this is like, this opinion is a substitute for a problem that you really don't want to solve
00:40:44.349 --> 00:40:51.030
Because like the, the comparison with great react app, like great react up is, is great at what it does, which is get you started using react.
00:40:51.289 --> 00:41:02.429
And, uh, like you don't have to set up much and, and you can get started, um, in doing so it's super opinionated about, okay, this is how you're going to do the whole compilation part.
00:41:03.139 --> 00:41:34.480
That is, uh, obviously a trade off cuz like the, the main thing to consider here is that, um, like the example way of tailwind, uh, for example, is that tailwind is built on top of both CSS and post CSS is a tool in itself of, uh, if you want to like do the performance optimizations that we're currently doing, for example, like rewriting parts and rest, all the configuration that we give users is super, uh, like limiting what we can do.
00:41:34.869 --> 00:41:50.400
Like, uh, an example is if you want to, like, if you would want to move from bevel to rust, uh, like to S SOC inside of create react app, it would be fairly a bit simpler then, like, for example, in next, because of the custom.
00:41:51.059 --> 00:42:01.150
So because you are allowed to add a bevel or a bevel, ORRC into like an excess app, we have to think about like, okay, how are we going to make this vector compatible?
00:42:01.610 --> 00:42:09.230
And then for how long are we going to support bevel as the output target likely very long, cuz we're very committed to like Vic.
00:42:10.289 --> 00:42:15.940
So if you have that config, you, you then have to make, make sure that that stays up to date as well.
00:42:15.940 --> 00:42:16.179
Right?
00:42:16.239 --> 00:42:20.739
So like that you can like keep using it over time, even though you're introducing new features.
00:42:21.500 --> 00:42:41.219
The, the example I gave before, like web four to epic five post CSS, like what if we, uh, like rewrite, uh, like parts of Bo CSS in rest, um, or like replace it completely for like the, the basic case where you don't have custom config, those are all things that we're thinking about and would be interesting.
00:42:41.820 --> 00:42:46.820
Uh, obviously we're currently very focused on the JavaScript part of things, a trade off either way.
00:42:46.820 --> 00:42:53.019
Like if you would have a, if we were super strict, we didn't have custom weapon config, we didn't have custom be config.
00:42:53.539 --> 00:42:56.050
A lot of people, people would not be able to use next today.
00:42:57.369 --> 00:43:14.570
Cuz like the moment, like you said, the moment you need till wind or the moment you need start components, the moment you need emotion, uh, that kind of stuff, it all requires some custom config like the, for till it's, uh, custom posts, um, for start components it's custom, uh, be config.
00:43:15.630 --> 00:43:21.199
Like if you don't have that option to use that, it makes it really hard to, to start using these libraries.
00:43:21.500 --> 00:43:26.199
And it especially becomes apparent when you start doing source at rendering of pre rendering.
00:43:26.639 --> 00:43:37.349
Cause most of these tools have, uh, custom transforms to make sure that the using be for example, uh, like adding some extra metadata in order to make sure that hydration works in the browser.
00:43:38.269 --> 00:43:40.590
It's like, that is a, like an interesting case.
00:43:40.809 --> 00:43:47.670
But then also, uh, by allowing you to have this custom, it allows people to experiment as well.
00:43:47.670 --> 00:43:47.949
Right.
00:43:48.369 --> 00:44:00.139
If there wasn't, uh, like if PO CSS didn't exist, uh, till wind would have been like maybe it was something that was built that, um, it would've likely been a lot harder for like Adam to get started, uh, building that.
00:44:01.360 --> 00:44:04.679
Um, and then obviously like it, it was kind of the reverse in the beginning.
00:44:04.681 --> 00:44:11.280
So it was like a big season output and now it actually is like a lot smarter and can generate CS for you on demand.
00:44:12.670 --> 00:44:22.900
Um, but like basically like these tools or these compiler libraries, like have allowed a lot of experimentation, like have allowed, uh, components to be created.
00:44:23.210 --> 00:44:27.840
That kind of stuff from our perspective, like config is not bad.
00:44:28.110 --> 00:44:30.679
Like if you have to use config, it's totally fine.
00:44:31.059 --> 00:44:35.480
But we also have to make trade offs of like, okay, this is what we're going to optimize in next.
00:44:35.760 --> 00:44:43.840
And like port two to SBC, for example, like custom transformed right now, like in next for example you have five, six custom be transforms.
00:44:43.840 --> 00:44:45.880
We poured all of those to SBC as well.
00:44:45.880 --> 00:44:54.429
So like they're all native interest, uh, as well now, which also in practice means that we have to contain two versions of it, which is also from the user perspective.
00:44:54.539 --> 00:45:06.369
Like this is something that a lot of people don't really see, but like, uh, like maintenance becomes infinitely harder when, uh, you start like basically diverging on like some tools.
00:45:06.510 --> 00:45:15.119
So like if you start, uh, like, because the config is there, you have to maintain specific conflict option, but then also the version, if it's not enabled, right.
00:45:15.599 --> 00:45:24.920
Uh, and then like the version and it's not enabled could be a lot faster cuz there is no like artificial overhead that people could introduce into the, the application.
00:45:26.820 --> 00:45:27.860
Everyone makes mistakes, right?
00:45:27.860 --> 00:45:42.530
Especially with early versions, like V zeros V one S like when you don't have enough user feedback most of the time, and sometimes you can rectify things, uh, but sometimes you're too far off and you need to start over.
00:45:43.400 --> 00:45:48.260
How, in your opinion, do you gracefully recover from the wrong abstraction?
00:45:50.380 --> 00:45:53.960
It becomes super hard to remove something once it's introduced.
00:45:54.480 --> 00:46:05.590
So what we generally do is that try to spend a lot more time thinking about, okay, if we introduce this, what is it going to solve and how long is it going to make sense to maintain it?
00:46:05.769 --> 00:46:11.829
And then like for most of the new things that we're making, we basically make sure that it can be maintained for quite a long time.
00:46:12.869 --> 00:46:16.500
Uh, but then also we already have like different solutions insight.
00:46:16.519 --> 00:46:31.900
So like an example is get props, get server props could actually go away when, uh, newer versions of react are released direct 18 and then like suspense based solutions actually, and allow us to further evolve, get props, get server props.
00:46:32.309 --> 00:46:34.380
We've had some of the restrictions thats the day.
00:46:34.760 --> 00:46:40.889
So like over, over time, the libraries that you use are going to evolve and you sort of have to evolve with them.
00:46:41.550 --> 00:46:47.130
And like, from our perspective, like we, we're always trying to make sure that like, it's always backwards compatible as well.
00:46:47.650 --> 00:46:51.849
Like even if we introduce a new feature, we still are going to maintain the older feature.
00:46:52.469 --> 00:47:00.639
And like in next 11, for example, we remove some features, uh, that had been deprecated since next four or something like that.
00:47:01.519 --> 00:47:08.519
Uh, so like we keep even keep deprecated features for quite some time, but it really depends on like how much the maintenance burden is as well.
00:47:08.619 --> 00:47:28.590
So like, like WebEx four being deprecated very soon going to mean that in the next major version, but we've com communicated that all already for quite some time, it's get to be removed in the next major version, uh, so that we can then basically focus on making sure that the, the one K so five is a lot more performant than it is today even.
00:47:30.170 --> 00:47:48.750
And in, uh, in instant search libraries, we, we made a mistake at the very beginning, which was to abstract some kind of search concept into fr what we thought as friendlier, uh, APIs, but in the end, these APIs were, were too high level and users could not achieve what they wanted to with them.
00:47:50.000 --> 00:48:06.079
Uh, so that's, uh, one example of when we had to, uh, basically use incremental recovery, uh, by introducing new APIs or tweaking existing APIs to allow users to basically, uh, send some custom such parameters to do such engine.
00:48:07.199 --> 00:48:09.079
Uh, so we created two APIs for that.
00:48:09.599 --> 00:48:18.670
Now we consider that Simpson such is kind of as powerful as the underlying mechanisms, but it took some time to actually recover from that.
00:48:18.849 --> 00:48:31.500
And also we kind of lost a bit of credibility among the community because of this kind of mistake, which is why I think it really all comes down to communication even with the community.
00:48:32.119 --> 00:48:40.500
So to recover from a wrong abstraction, usually as long as you actually explain the community, um, why it wasn't made that way.
00:48:40.559 --> 00:48:48.300
And now they will be able to actually, uh, do it because of a new API and they can actually understand it.
00:48:48.659 --> 00:48:53.809
Uh, usually you're fine, but we, to me really, um, comes down to communication.
00:48:54.969 --> 00:49:06.849
Uh, another example where we actually, um, kind of when, when we were an not victim of like a, a wrong abstraction, but an outdated abstraction, uh, was, uh, when we created autocomplete V zero.
00:49:07.070 --> 00:49:26.320
So the, the previous version of the, the current library, it was started in, um, 2015, it was originally a fork of the type head JS library and the library, uh, autocomplete, the auto library, uh, became like in maintenance mode very shortly after because the code base was too hard to contribute to.
00:49:26.820 --> 00:49:38.829
And we thought that it was sufficient to build search search experiences at the time with this library, but the search ecosystem grew, uh, and search is now, um, presented in most of the apps.
00:49:39.389 --> 00:49:42.710
Uh, search is actually the foundation of the experience in most of the apps.
00:49:42.809 --> 00:49:48.789
Now in capital Google maps, Amazon, YouTube, you couldn't really use these apps, uh, now without search.
00:49:49.690 --> 00:49:59.179
So we were observing such a gap between a complete V zero and the search experiences that we could design that we decided to start from scratch.
00:49:59.719 --> 00:50:07.579
So this is a rare case where we actually took the decision to start from scratch, which is usually, um, a risky decision.
00:50:08.579 --> 00:50:20.010
Uh, so six years later, 2021, we release to complete V and, um, we consider it as a good abstraction nowadays because it allows you to be way more complex such experiences.
00:50:20.309 --> 00:50:27.760
So, um, I don't think it was necessarily a bad abstraction at first, but it was definitely an outdated
00:50:28.000 --> 00:50:28.360
Abstraction.
00:50:29.739 --> 00:50:29.960
Yes.
00:50:30.320 --> 00:50:33.159
Uh, I, I, I like what you said also on, on communication.
00:50:33.480 --> 00:50:37.880
I, I think like sometimes, okay, you realize it was the wrong way.
00:50:37.969 --> 00:50:40.199
We'll learn something and we're gonna move on.
00:50:40.201 --> 00:51:01.670
We're not just gonna stay stuck and that in that, uh, in that scenario, but what's important is that you communicate also that you own it explaining why you failed, uh, going above and beyond to ease the migration, whether it's with a guide, like a really, really well done guide, or maybe maintaining the old version a little bit more if it's necessary.
00:51:02.590 --> 00:51:29.969
Um, there are really good examples for examples, uh, on episode, uh, mentioned that whenever they do, they break the API, for example, the schema of the content, they will take the migration on themselves for paying customers, uh, and maybe it's even free customers, but I know at least for, uh, a set of, uh, maybe business or enterprise customers, they will do the migration themselves because they decide it's on us.
00:51:29.969 --> 00:51:31.610
Like we, we broke it.
00:51:31.670 --> 00:51:40.730
So if we want people to use the next version, especially for them, because it's a, it's a hosted service, um, we, we have to, to, to do it ourself.
00:51:41.250 --> 00:51:47.730
And I think it also can be interesting is to, instead of just going like, yeah, this was crap.
00:51:48.099 --> 00:51:49.000
Let's move, move on.
00:51:49.449 --> 00:52:00.199
Maybe take a little bit more time to identify the root causes of what led to those like faulty abstractions, because my mistakes usually don't don't happen in a vacuum.
00:52:00.389 --> 00:52:03.159
Usually there are some, some patterns behind it.
00:52:03.539 --> 00:52:06.840
We were in a rush, we were too UN experimented.
00:52:06.860 --> 00:52:08.679
We did not talk to customers.
00:52:09.869 --> 00:52:35.730
Uh, we forked something because we wanted it to be easy, but because we were in a rush, so trying to reflect back and maybe postmortem or, you know, root cause analysis, I think can be, can be beneficial, even if we usually want to move on and just go to the next thing, because we think we know what to do be, cuz we also tend to repeat mistakes when we, we don't take the time to externalize them.
00:52:36.269 --> 00:52:58.000
And again, this is one of the, the things that I, I really love about, uh, both next and, and autocomplete is, uh, is the concept of micro abstracting and Moi modularizing, your abstractions, making sure that you don't build this whole monolithic system, that whenever you tweak something, you're gonna pull down the entire, you know, house of cards.
00:52:58.800 --> 00:53:01.000
Um, that to me is super important.
00:53:01.001 --> 00:53:08.880
Being able to say, okay, we build that thing, but if we change it to more like we don't have to deprecate the entire thing.
00:53:09.480 --> 00:53:14.949
Uh, like we don't have to go next JS 20 just because this function no longer works.
00:53:15.010 --> 00:53:26.969
So trying not to couple all your pieces together so that yeah, you have like this kind of huge drips of glue that make everything not even touchable.
00:53:27.909 --> 00:53:33.329
So I will, uh, before we wrap up, I will ask you the traditional question of the, of the show.
00:53:33.869 --> 00:53:39.449
How do you define great DX and what is your personal level of expectations?
00:53:40.420 --> 00:53:42.760
That's about generally three things.
00:53:42.900 --> 00:53:46.309
So like one is that you get your update.
00:53:46.311 --> 00:53:49.670
Like if you make a change, the update is there as soon as it can be.
00:53:50.250 --> 00:54:09.079
So as, as fast as possible, uh, which is what we've been working towards, uh, very heavily for next, uh, to make sure that like, if it changes really small and it doesn't touch like large parts of the code base, um, or like you're importing a new library, it's going to be there in, uh, like less than a hundred milliseconds.
00:54:09.081 --> 00:54:20.570
That's the, the goal that we have, uh, it's like, that's the, the first thing, things have to be really fast and that's just like, it goes from booting up the dev server to, uh, opening pages.
00:54:21.130 --> 00:54:23.329
Uh, like we do all of that on, on the amount for next.
00:54:23.679 --> 00:54:26.719
Like we don't even start to do work, uh, when it's not needed.
00:54:27.840 --> 00:54:29.800
Uh, but we do try to do things optimistically.
00:54:29.960 --> 00:54:39.679
So like when you put up the next server, it's going to optimistically compile some of the files that we know that, that you're going to need either way then is the errors.
00:54:40.099 --> 00:54:46.630
So I think that is generally overlooked is that if an error happens, it generally is not super helpful.
00:54:47.780 --> 00:54:53.739
Um, so if you're using a library, it's going to throw an error, it's gonna say like, okay, this value was wrong or something like that.
00:54:54.119 --> 00:54:59.909
But in general, like what you see very often is that it's not, um, as helpful as it could be.
00:54:59.911 --> 00:55:02.550
Like, why did it throw that error specifically?
00:55:02.579 --> 00:55:05.829
Like, okay, I'm passing in a string, it should be an integer or something like that.
00:55:06.469 --> 00:55:07.230
These are simple cases.
00:55:08.670 --> 00:55:25.400
The complicated cases are like I'm using, uh, tic props and I'm returning some value that doesn't exist, but what are the other values that, uh, that could be used and, or like you make a typo that kind of stuff, things that we could detect, like, Hey, you're making a typo, you can fix it in this way.
00:55:25.760 --> 00:55:40.500
Um, so what we do for next is actually like sent, uh, with every error or at least most of them at this point, we sent a, uh, specific link to the documentation with special pages specifically for those errors.
00:55:40.519 --> 00:55:48.300
So anytime an error is added, what we do is we actually add a documentation page as well in the docs messages, uh, folder.
00:55:49.500 --> 00:55:53.010
Um, and, uh, that's going to explain why did the R happen?
00:55:53.519 --> 00:55:58.329
Okay, you put it in the wrong value or like you're using the, like, you're holding it wrong, that kind of stuff.
00:55:58.869 --> 00:56:04.730
And, uh, then gives you an like a way to investigate it or to fix it.
00:56:05.530 --> 00:56:08.809
Uh, so it tells you why, uh, and then like, how can I fix it?
00:56:09.429 --> 00:56:11.519
And then also all the documentation around it.
00:56:11.719 --> 00:56:14.719
So like useful links that, that you could read through as well.
00:56:15.809 --> 00:56:21.849
Uh, and it has been really good cuz that also we expanded that onto like also collecting feedback from those pages.
00:56:22.610 --> 00:56:26.940
So we get a lot of feedback from people that read into errors and then say like, okay, this was not helpful.
00:56:27.199 --> 00:56:29.420
Or like I fixed it in this way.
00:56:29.420 --> 00:56:33.820
Please add that to the document cuz then, then other people can benefit from it as well.
00:56:34.539 --> 00:56:38.699
The really big part of of development is actually like reading errors and figuring out what is going wrong.
00:56:39.159 --> 00:56:51.190
And then the, the, the third thing is that also like the, the good DX also has to like weigh against, uh, having good user experience.
00:56:51.610 --> 00:57:19.099
So a lot of things that we do in next is also like running you for cases where, uh, you're going to affect user experience by including synchronous scripts, or you're going to include an image stack that blocks ring of the whole page or, uh, that kind stuff like in next 11, we, we have a lot of goal system of plugins that basically warn you like, okay, this is going to be a lot better if you make it, uh, like change it to, to use this other approach.
00:57:20.170 --> 00:57:22.269
And it goes for like phone preloading all that.
00:57:22.530 --> 00:57:27.820
And then like, from from our perspective of, we also try to get out of the way very often.
00:57:28.159 --> 00:57:41.820
So there are some conventions, but like, we're not telling you how to do data fetching, uh, particularly like where you're getting data from, how you're getting the data, because then you, you get the full flexibility of being able to, to build what you want.
00:57:42.440 --> 00:57:57.170
And that is also led to basically like seeing, uh, sites from like a few pages, personal websites to like massive web applications that, that are served through to millions of people, uh, every day.
00:57:58.519 --> 00:57:58.809
Yeah.
00:57:59.199 --> 00:58:06.449
Good gig for me is really, um, about focusing on my application features and not necessarily on the platform or the infrastructure of feature.
00:58:07.679 --> 00:58:17.760
Uh, so as, as you said, Tim, basically getting out of the way of the developer and some examples could be, um, at less UIs, like erratic primitives or stuff like that.
00:58:18.019 --> 00:58:21.360
If you want to create a context menu by yourself, it takes some time.
00:58:21.360 --> 00:58:30.269
And I try that and basically you waste so much time and the logic of the component itself and that you could actually invest in your, uh, application.
00:58:31.150 --> 00:58:32.670
Uh, that's it's a waste of time.
00:58:32.769 --> 00:58:39.869
So to me, good DX is actually providing me the tools that I, that maybe the platform should have, uh, provided me.
00:58:40.469 --> 00:58:41.829
Although examples could be next best.
00:58:42.030 --> 00:58:47.429
I don't need to understand that my route is gonna trigger alarm function somewhere in some server.
00:58:48.099 --> 00:58:51.300
I don't really need to understand that as a user or as a developer.
00:58:52.179 --> 00:58:55.139
Uh, so this to me, uh, is what DX is about.
00:58:56.199 --> 00:59:20.110
I like also thinking about the fact that there are so many projects that we start and we don't finish, uh, because we hit a roadblock or we hit like, oh yeah, that conflict thing, or that, as you mentioned, team errors, I think for so many years, I've been like the, the worst DX, uh, of like the entire software, uh, development field, uh, because you see something and you don't, you have no idea what to do with it.
00:59:20.110 --> 00:59:24.079
And it's like, it's telling you the consequence, but doesn't tell you anything about the cause.
00:59:24.460 --> 00:59:28.320
And so, yeah, to me, it's really similar to what you just, uh, that you just described.
00:59:28.880 --> 00:59:32.079
It's like, give me a head start, but don't pick a path for me.
00:59:32.559 --> 00:59:33.840
Like there are things I wanna do.
00:59:34.250 --> 00:59:35.239
Don't do them for me.
00:59:35.400 --> 00:59:36.039
I want to do it.
00:59:36.070 --> 00:59:37.000
It's, it's gonna be fun.
00:59:37.159 --> 00:59:40.320
And, and it's also the value that I add with my program.
00:59:41.000 --> 00:59:48.150
There are things that I don't wanna do, and there are things that I shouldn't do no matter where I, I want to do them or not.
00:59:48.289 --> 01:00:00.230
And grad DX really lets me do everything I wanna do relieves me from what I don't want to do and convinces me not to handle what I should not be handling.
01:00:00.429 --> 01:00:05.059
And because, uh, the library of the framework is gonna do it like a million times better.
01:00:05.539 --> 01:00:07.099
Uh, I, you know, I don't wanna configure.
01:00:07.579 --> 01:00:09.619
Webpac like, I know I don't wanna do it.
01:00:10.260 --> 01:00:13.019
Uh, I don't wanna worry about my Google lighthouse score.
01:00:13.760 --> 01:00:25.409
And even if I enjoy that, I don't really, I should probably not configure my own server, but I wanna craft the web website of my dreams, like down to the tiniest pixel with the libraries that I love.
01:00:25.530 --> 01:00:28.690
I like it's not gonna be next year is not gonna be my entire life.
01:00:28.730 --> 01:00:30.050
I want to use tailwind.
01:00:30.130 --> 01:00:31.130
I want to use Radix.
01:00:31.130 --> 01:00:34.730
I want to use whatever auto completes, uh, and same for auto complete.
01:00:34.769 --> 01:00:37.690
I don't want to read the re specs for combo books.
01:00:37.849 --> 01:00:39.090
I don't have time for that.
01:00:39.929 --> 01:00:46.360
Uh, I should probably not try to read, build an auto complete solution, even if I think it would be fun because yeah.
01:00:46.639 --> 01:01:10.829
When, when you see that it takes, uh, dedicate people who are dedicated to, to the problem a year to come up with like a really robust solution, I will probably not nail it down in a, in an afternoon, but I want to be able to grab suggestions from any, anywhere, any API, any static file and, you know, dynamically control, uh, like the, the, the behavior of all that.
01:01:10.849 --> 01:01:12.590
And that's what I should be focusing on.
01:01:13.159 --> 01:01:19.050
Especially knowing that my excitement will fade away after a certain period of time.
01:01:19.050 --> 01:01:25.920
And if I want to ship, I need to be helped in a way that already ahead, by using the right tool.
01:01:26.579 --> 01:01:29.679
So where can people go to find you online?
01:01:32.510 --> 01:01:37.489
So, for me, it's just, uh, my full name as my handle, pretty much everywhere.
01:01:37.590 --> 01:01:48.360
So like can get a Twitter, been tweeting a bit less, uh, the past, uh, few months, mostly because just been really busy with building out next features and performance.
01:01:48.949 --> 01:01:51.199
Improvement's a lot of good things to come there.
01:01:51.340 --> 01:02:01.119
If you want to learn more about next, you can go to next org, let's learn, uh, it's a interactive tutorial that, that guides you through basically building a NHA app.
01:02:02.190 --> 01:02:05.989
Uh, all the, the features that we talked about today is like aesthetic props servers.
01:02:06.110 --> 01:02:08.780
Our props out sees as, uh, all that.
01:02:08.869 --> 01:02:11.380
We're also, uh, hosting a conference very soon.
01:02:11.599 --> 01:02:17.099
So, um, on nexus slash con, you can register for a free ticket there.
01:02:17.610 --> 01:02:17.900
Cool.
01:02:17.960 --> 01:02:22.320
And you can find me on GI, uh, with my full name lowercase and on Twitter.
01:02:22.920 --> 01:02:24.880
Um, my name is actually too long for Twitter.
01:02:25.199 --> 01:02:29.039
And so it's cons C H L F R.
01:02:30.079 --> 01:02:30.239
All right.
01:02:30.579 --> 01:02:35.840
And, uh, you can find me on Twitter at front stuff, underscore IO, which is the worst end ever.
01:02:36.400 --> 01:02:41.789
Uh, and you can also find my work at my full name, SOA with Anh dion.com.
01:02:42.650 --> 01:02:50.389
If you want to learn about auto complete, you can go on our fantastic short URL, alg.ally/autocomplete.
01:02:50.391 --> 01:02:57.789
You'll find the documentation and you can learn anything about algolia.com team UA.
01:02:57.791 --> 01:02:58.710
Thank you so much.
01:02:59.219 --> 01:03:01.099
Chatting with me today was really fascinating.
01:03:01.139 --> 01:03:07.099
Conversation went over time, and I wish we could do an extra hour listeners.
01:03:07.219 --> 01:03:08.340
I hope you had a blast.
01:03:08.800 --> 01:03:12.820
Thanks a lot for, uh, following developer experience and station.
01:03:13.079 --> 01:03:14.179
For the next episode.
01:03:15.650 --> 01:03:20.010
This was developer experience, a podcast brought to you by Golia.
01:03:20.510 --> 01:03:23.489
You can find this podcast on your favorite podcast platform.
01:03:23.909 --> 01:03:30.449
We are on Spotify, apple podcast, Google podcast, Pandora, overcast, everywhere.
01:03:31.110 --> 01:03:38.050
If you want to know more about Algolia check us out on algolia.com and we are at Algolia on Twitter.