Check out a free preview of the full Introduction to Next.js, v3 course
The "API Q&A" Lesson is part of the full, Introduction to Next.js, v3 course featured in this preview video. Here's what you'd learn in this lesson:
Scott addresses students' questions about handling cross-origin resource sharing (CORS) and explains the differences between API routes in the pages directory and routes in the app directory.
Transcript from the "API Q&A" Lesson
[00:00:00]
>> What about CORS?
>> For CORS, so if you don't know what CORS is, CORS, C-O-R-S, cross-origin resource sharing. It's a security policy that browsers have implemented to prevent websites from accessing information from servers that aren't part of the same domain. So a server can implement. So what the browser will do is something called a pre-flight check, which basically means, let's say you did a fetch request in the browser.
[00:00:26]
Before that fetch request, the browser will actually go to that location first and do an options check, options method. Let's say you try to do a GET request. It'll first say, let me do an options request first just to see what the server is capable of. So then a server can respond back to that options request and be like, yeah, here, we support only these domains.
[00:00:48]
We support only these methods. So then the browser will get that back. And if it doesn't see the domain that you're on or the IP that you're on as supported, then your request will get blocked for CORS issue. So it's just a way to protect websites through the browser.
[00:01:04]
So as someone who's implementing a server, if you want anyone to be able to access your server, and this doesn't count like authentication. You're still gonna add authentication. This is just like just even being able to knock on your door, basically. You have to implement CORS. So you have to implement a strategy there.
[00:01:19]
So CORS is a OPTIONS request. So there's nothing stopping you from just doing OPTIONS like this, And sending back headers. So I think the headers you want, actually, I know exactly where that is in here, I was just reading it, so let's see. CORS, here we go, damn, yeah, so, looks like you can actually just do a GET request here.
[00:01:46]
So basically, the way you respond to CORS is typically you tell the browser what is possible by these access control headers. So you can say Access-Control-Allow-Origin. This means, yeah, anybody can knock on my door, basically. These are the messages they can send me, and these are the headers that they are allowed to send.
[00:02:09]
And then now, if the browser thinks this is okay, which in this case, it should be cuz this is pretty much everything, I guess if you said patch, we did a patch request, this will fail, cuz it doesn't allow patch. Then, yeah, you should be good to go.
[00:02:22]
This doesn't matter if you're doing server-to-server communication. Only browsers implement CORS. So if you have one server talking to another server, CORS doesn't matter cuz only browsers look for CORS.
>> And I think it also only matters cross-domain, right? If you're on the same app, it doesn't matter.
[00:02:37]
>> It only matters for cross-domain if you are on the same domain. If your API is on yourapp.com and your website is also on yourapp.com, or even app.yourapp.com, it probably doesn't matter. It's only for cross-origin resource sharing, so it has to be a different domain. So the question was what are the differences between API routes in the pages directory versus API routes in the app directory?
[00:02:59]
So last time I taught this course was when 13 first came out and they switched the pages over to the app directory, but they did not switch the API over to the app directory. So you still had to use the pages folder just to use an API, which was weird.
[00:03:13]
So you had an app folder with all your pages, and then a pages folder with your API. So it's very, very weird. You guys aren't getting that CORS today. So the difference other than that, before Next.js 13 came out was that it basically looked like this, right? The difference was you have an api folder, and then in that api folder, I wouldn't have to make another folder for a segment, I could just make a filename.
[00:03:39]
So let's say I wanted a route called todo. So in the new api folder, I have to make a new folder called todo, and then put a route in it. But in the old pages api folder, I could just come to the root of the api and just say todo.ts.
[00:03:52]
And that would make a route called /api/todo. It'd be the name of the file. The same thing with pages. I wouldn't have to do page.tsx, I would just say spa.tsx, and that would be the page. So that would be the difference, and then you'd come in here and you get a function that looks like this, right?
[00:04:08]
You have a function that says, usually people call it handler. You'll get a request and a response that's passed in. And then you could do whatever you want here, right? And then you just export this. You can only export a default, and that was it. And then anything like handling different methods, that'd be on you.
[00:04:29]
That'd be like if req.method === 'GET', then do this thing, right? And then if equals POST, then do this thing. You'd have to do that yourself in the code. So that's the difference. We don't have to write that logic for routing on methods, and we can only make new segments with folders now and not filenames.
[00:04:48]
And we can export different verbs this way. The other thing is you don't get a response object passed into you anymore, you can just import the response object. And the request object is a web standard now and not some request object that Next.js made that's based off Express.
[00:05:06]
So a lot of differences there, which is another reason why I wanted to update this course and teach it because it's so different. So yeah, that's the difference. Okay, let's just implement these API routes for our todos, which should be pretty simple. So we'll import our database from @/utils/db.
[00:05:28]
And then to get all the todos, pretty simple, todos will be await db.todo.findMany, like that, and then we're gonna send this data back. Super easy, if you wanna create a todo, we'll just assume this is the data that you're sending. And then we're gonna say todo is await db.todo.create, like that, data is data, and then we'll just send back the todo.
[00:06:17]
All right, so got those. So we can test it out, right? I can just go back to my browser, run this, got all my todos. That works pretty good, and then I can make another one from here. I know we need content, so we'll pass up content, and this is a todo from my vs code http app thingy.
[00:06:48]
So post that, you can see we got a new todo here. And if I go back and refresh this, should be at the bottom, there it is. Any other questions on API stuff? And when it comes to dynamic stuff, it's the same thing, right? So I needed /todo, /todo/id, and it's the same thing, right?
[00:07:14]
I would just go make a new folder here, say id, like this, and then I would make a route in here, and it's the same thing. I get access to the params, I can do pretty much the same thing that we did in the page, and nothing's changed.
[00:07:30]
Cool, yeah, I mean, APIs are pretty simple, and they should be. So you might be asking yourself, when would you use these APIs? I think if you ask the Next.js team, they really don't want you using these [LAUGH] for the app that you're making. They want you to use server actions and server-side data fetching like we did.
[00:07:49]
Where did we do that? In the dashboard todos page, like this. They want you to do this, and they're right, you should be doing this. This is way better. It's so much simpler. You don't have to go across the network. You're already on the server. The sweet thing about doing this is now the person's Internet is not a factor in how fast they get the data back because this happens on the server, which probably has fiber Internet.
[00:08:12]
It's probably in some private network that's really quick. And you're not relying on someone's network connection to determine how quick they're gonna get the data back because it's not happening on the client. It's happening here, it's not going across the wire. So they're only waiting to download the HTML that's rendered.
[00:08:29]
And their Internet connection is gonna determine how fast they get the HTML back, but not how fast that component gets this data back. So that's a good thing. So then you might ask yourself, okay, this is for getting data, but what about posting data, mutating data? That's where I would use the API.
[00:08:44]
Yeah, but then they created server actions. So it's like you could do everything with server actions, although I don't recommend it. You could, and they probably will evolve it to where you can. So then it's like, well, why do I even need APIs then if I can just do mutations with server actions, I can do server-side fetching?
[00:09:01]
Well, sometimes you're still gonna have client components that need to get data and sometimes you're still gonna have client components that need to mutate data. So that's where API comes in is just when you just need client components to do things. And then also if your product is some third party API that needs to offer API access to other people on their apps, then yeah, you need API for them.
[00:09:19]
Maybe it's not for your app. Maybe it's for other people's apps to consume, so you're gonna make an API. So those would probably be the two use cases I think the Next.js team would say if they were here. I think that's what they're doing based off their documentation and their recommendations.
[00:09:32]
And I have to genuinely agree. Other than using server actions for everything, I still think client-side API calls is probably the way to go if UI needs to be updated for now, but that could change soon, I'm sure.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops