Como integrar o MongoDB ao seu aplicativo Next.js
Ado Kukic, Kushagra Kesav11 min read • Published May 12, 2022 • Updated Apr 02, 2024
Avaliar este tutorial
Este tutorial usa o roteador de páginas do Next.js em vez do roteador de aplicativos introduzido na versão 13 do Next.js. O roteador de páginas ainda é compatível e recomendado para ambientes de produção.
Você está construindo seu próximo aplicativo incrível com Next.js? Gostaria de poder integrar o MongoDB ao seu aplicativo Next.js sem esforço? Precisa fazer isso antes que o café fique pronto? Se você respondeu sim a essas três perguntas, tenho boas notícias para você. Nós criamos uma integração Next.js<>MongoDB que o colocará em funcionamento em minutos, e você pode considerar este tutorial seu guia oficial de como usá-lo.
In this tutorial, we'll take a look at how we can use the with-mongodb example to create a new Next.js application that follows MongoDB best practices for connectivity, connection pool monitoring, and querying. We'll also take a look at how to use MongoDB in our Next.js app with things like serverSideProps and APIs. Finally, we'll take a look at how we can easily deploy and host our application on Vercel, the official hosting platform for Next.js applications. If you already have an existing Next.js app, not to worry. Simply drop the MongoDB utility file into your existing project and you are good to go. We have a lot of exciting stuff to cover, so let's dive right in!
Our app is now deployed and running in production. If you weren't following along with the tutorial and just want to quickly start your Next.js application with MongoDB, you could always use the
with-mongodb
starter found on Github, but I’ve got an even better one for you.Visit Vercel and you'll be off to the races in creating and deploying the official Next.js with the MongoDB integration, and all you'll need to provide is your connection string.
Para este tutorial, você precisará de:
- NodeJS 18+.
- npm e npx.
Para aproveitar ao máximo este tutorial, você precisa estar familiarizado com React e Next.js. Abordarei os recursos exclusivos do Next.js com detalhes suficientes para ainda serem valiosos para um novato.
Se você ainda não está familiarizado com ele, o Next.js é um framework baseado no React para a criação de aplicativos web modernos. O framework adiciona muitos recursos avançados – como renderização no lado do servidor, divisão automática de código e restauração estática incremental – que facilitam a criação de aplicativos escaláveis e prontos para produção.
![Vercel homepage](/developer/_next/image/?url=https%3A%2F%2Fimages.contentstack.io%2Fv3%2Fassets%2Fblt39790b633ee0d5a7%2Fblt572f8888407a2777%2F65de06fac7f05b1b2f8674cc%2Fvercel-homepage.png&w=3840&q=75)
O Next.js tem uma ampla biblioteca de exemplos que mostra como você pode integrar a estrutura com vários recursos, como servidores GraphQL, bibliotecas de autenticação e estruturas CSS. O exemplo que usaremos neste tutorial é chamado with-mongodb e, como você pode esperar, ele vem com tudo o que é necessário para se conectar a um MongoDB database.
Para criar um novo aplicativo Next.js com integração com o MongoDB, execute o seguinte comando no seu terminal:
1 npx create-next-app --example with-mongodb mflix
We are using the
npx create-next-app
command and are passing the --example with-mongodb
parameter, which will tell create-next-app
to bootstrap our app with the MongoDB integration example. Finally, mflix
is the name of our application. You can name your application something else if you'd prefer. Executing this command will take a couple of seconds to download and install all the npm dependencies, but once they're downloaded and installed, navigate to your project directory by running:1 cd mflix
Em seguida, instale todas as dependências do npm executando:
1 npm install
Nesse diretório, vamos iniciar nosso aplicativo e ver o que acontece. Para iniciar nosso aplicativo Next.js, no diretório mflix, execute:
1 npm run dev
Once the app is built, let's see our app in action by navigating to
localhost:3000
. Uh-oh. We get an error.![server error](/developer/_next/image/?url=https%3A%2F%2Fimages.contentstack.io%2Fv3%2Fassets%2Fblt39790b633ee0d5a7%2Fblt833e93bc334716a5%2F65de07c677ae451d96b0ec98%2Fserver-error.png&w=3840&q=75)
A boa noticia é que o erro é bastante descritivo. O motivo desse erro é que não fornecemos nossa string de conexão do MongoDB para o aplicativo Next.js. Vamos fazer isso a seguir.
If we look at our Next.js application directory, we'll find an
env.local.example
file. Let's rename this file to env.local and open it. This file contains one property that we'll need to fill out: MONGODB_URI
.We'll get this information from our MongoDB Atlas cluster. You can use a local MongoDB installation if you have one, but if you're just getting started, MongoDB Atlas is a great way to get up and running without having to install or manage your MongoDB instance. MongoDB Atlas has a forever free tier that you can sign up for as well as get the sample data that we'll be using for the rest of this tutorial.
Para obter nosso URI do MongoDB, em nosso painel do MongoDB Atlas:
- Hit the Connect button.
- Then, click the Connect to your application button, and here you'll see a string that contains your URI that will look like this:
1 mongodb+srv://<USERNAME>:<PASSWORD>@cluster0.<appId>.mongodb.net/<DBNAME>?retryWrites=true&w=majority
If you are new to MongoDB Atlas, you'll need to go to the Database Access section and create a username and password, as well as the Network Access tab to ensure your IP is allowed to connect to the database. However, if you already have a database user and network access enabled, you'll just need to replace the
<USERNAME>
and <PASSWORD>
fields with your information.![database deployment](/developer/_next/image/?url=https%3A%2F%2Fimages.contentstack.io%2Fv3%2Fassets%2Fblt39790b633ee0d5a7%2Fbltad2329fe1bb44d8f%2F65de1b020f1d350dd5ca42a5%2Fdatabase-deployments.png&w=3840&q=75)
To close out this section, our
env.local
file should look like this:1 MONGODB_URI=mongodb+srv://<USERNAME>:<PASSWORD>@cluster0.tdm0q.mongodb.net/sample_mflix?retryWrites=true&w=majority
Para garantir que nossa configuração esteja correta, vamos reiniciar nosso aplicativo Next.js indo para o terminal e compilando o aplicativo novamente. Execute o seguinte comando no seu terminal:
1 npm run dev
When the application is built, navigate to
localhost:3000
in your browser and you should see the following:![Welcome to Next.js](/developer/_next/image/?url=https%3A%2F%2Fimages.contentstack.io%2Fv3%2Fassets%2Fblt39790b633ee0d5a7%2Fblt798b7c3fe361ccbd%2F65de1b917c85267d37234400%2Fwelcome-nextjs.png&w=3840&q=75)
This is the
with-mongodb
Next.js app welcome page. If you see the message "You are connected to MongoDB," you are good to go. If you see the message "You are NOT connected to MongoDB," then verify your connection string and make sure that the database user, as well as the network connection, is properly set. If you run into any issues, head over to the MongoDB community forums, and we'll help troubleshoot.Agora que estamos conectados ao MongoDB, vamos discutir como podemos consultar os dados do MongoDB e trazê-los para nosso aplicativo Next.js. O Next.js oferece suporte a várias maneiras de obter dados. Podemos criar pontos de extremidade de API, obter dados executando funções renderizadas do lado do servidor para uma página específica e até gerar páginas estáticas obtendo nossos dados no tempo de construção. Veremos os três exemplos.
The first example we'll look at is building and exposing an API endpoint in our Next.js application. To create a new API endpoint route, we will first need to create an
api
directory in our pages
directory, and then every file we create in this api
directory will be treated as an individual API endpoint.Let's go ahead and create the
api
directory and a new file in this directory
called movies.tsx
. This endpoint will return a list of 20 movies from our MongoDB database. The implementation for this route is as follows:1 import clientPromise from "../../lib/mongodb"; 2 import { NextApiRequest, NextApiResponse } from 'next'; 3 4 export default async (req: NextApiRequest, res: NextApiResponse) => { 5 try { 6 const client = await clientPromise; 7 const db = client.db("sample_mflix"); 8 const movies = await db 9 .collection("movies") 10 .find({}) 11 .sort({ metacritic: -1 }) 12 .limit(10) 13 .toArray(); 14 res.json(movies); 15 } catch (e) { 16 console.error(e); 17 } 18 }
To explain what is going on here, we'll start with the import statement. We are importing our
clientPromise
method from the lib/mongodb
file. This file contains all the instructions on how to connect to our MongoDB Atlas cluster. Additionally, within this file, we cache the instance of our connection so that subsequent requests do not have to reconnect to the cluster. They can use the existing connection. All of this is handled for you!Next, our API route handler has the signature of
export default async (req, res)
. If you're familiar with Express.js, this should look very familiar. This is the function that gets run when the localhost:3000/api/movies
route is called. We capture the request via req
and return the response via the res
object.Our handler function implementation calls the
clientPromise
function to get the instance of our MongoDB database. Next, we run a MongoDB query using the MongoDB Node.js driver to get the top 20 movies out of our movies collection based on their metacritic rating sorted in descending order.Finally, we call the
res.json
method and pass in our array of movies. This serves our movies in JSON format to our browser. If we navigate to localhost:3000/api/movies
, we'll see a result that looks like this:![Serving movies in JSON format to browser](/developer/_next/image/?url=https%3A%2F%2Fimages.contentstack.io%2Fv3%2Fassets%2Fblt39790b633ee0d5a7%2Fblta204dc4bce246ac6%2F65de1ff8c7f05b0b4b86759a%2Fjson-format.png&w=3840&q=75)
We can add additional API routes by creating additional files in the
api
directory. As a homework exercise, why don't you create an API route that returns a single movie based on a user-provided ID?To give you some pointers, you'll use Next.js Dynamic API Routes to capture the
id
. So, if a user calls http://localhost:3000/api/movies/573a1394f29313caabcdfa3e
, the movie that should be returned is Seven Samurai. Another tip: The _id
property for the sample_mflix
database in MongoDB is stored as an ObjectID, so you'll have to convert the string to an ObjectID. If you get stuck, create a thread on the MongoDB Community forums and we'll solve it together! Next, we'll take a look at how to access our MongoDB data within our Next.js pages.In the last section, we saw how we can create an API endpoint and connect to MongoDB with it. In this section, we'll get our data directly into our Next.js pages. We'll do this using the getServerSideProps() method that is available to Next.js pages.
The
getServerSideProps()
method forces a Next.js page to load with server-side rendering. What this means is that every time this page is loaded, the getServerSideProps()
method runs on the back end, gets data, and sends it into the React component via props. The code within getServerSideProps()
is never sent to the client. This makes it a great place to implement our MongoDB queries.Let's see how this works in practice. Let's create a new file in the
pages
directory, and we'll call it movies.tsx
. In this file, we'll add the following code:1 import clientPromise from "../lib/mongodb"; 2 import { GetServerSideProps } from 'next'; 3 4 5 interface Movie { 6 _id: string; 7 title: string; 8 metacritic: number; 9 plot: string; 10 } 11 12 13 interface MoviesProps { 14 movies: Movie[]; 15 } 16 17 18 const Movies: React.FC<MoviesProps> = ({ movies }) => { 19 return ( 20 <div> 21 <h1>Top 20 Movies of All Time</h1> 22 <p> 23 <small>(According to Metacritic)</small> 24 </p> 25 <ul> 26 {movies.map((movie) => ( 27 <li key={movie._id}> 28 <h2>{movie.title}</h2> 29 <h3>{movie.metacritic}</h3> 30 <p>{movie.plot}</p> 31 </li> 32 ))} 33 </ul> 34 </div> 35 ); 36 }; 37 38 39 export default Movies; 40 41 42 export const getServerSideProps: GetServerSideProps = async () => { 43 try { 44 const client = await clientPromise; 45 const db = client.db("sample_mflix"); 46 const movies = await db 47 .collection("movies") 48 .find({}) 49 .sort({ metacritic: -1 }) 50 .limit(20) 51 .toArray(); 52 return { 53 props: { movies: JSON.parse(JSON.stringify(movies)) }, 54 }; 55 } catch (e) { 56 console.error(e); 57 return { props: { movies: [] } }; 58 } 59 };
As you can see from the example above, we are importing the same
clientPromise
utility class, and our MongoDB query is exactly the same within the getServerSideProps()
method. The only thing we really needed to change in our implementation is how we parse the response. We need to stringify and then manually parse the data, as Next.js is strict.Our page component called
Movies
gets the props from our getServerSideProps()
method, and we use that data to render the page showing the top movie title, metacritic rating, and plot. Your result should look something like this:![Top 20 movies](/developer/_next/image/?url=https%3A%2F%2Fimages.contentstack.io%2Fv3%2Fassets%2Fblt39790b633ee0d5a7%2Fblt955fc3246045aa82%2F65de2049330e0026817f6094%2Ftop-20-movies.png&w=3840&q=75)
This is great. We can directly query our MongoDB database and get all the data we need for a particular page. The contents of the
getServerSideProps()
method are never sent to the client, but the one downside to this is that this method runs every time we call the page. Our data is pretty static and unlikely to change all that often. What if we pre-rendered this page and didn't have to call MongoDB on every refresh? We'll take a look at that next!For our final example, we'll take a look at how static page generation can work with MongoDB. Let's create a new file in the
pages
directory and call it top.tsx
. For this page, what we'll want to do is render the top 1,000 movies from our MongoDB database.Top 1,000 movies? Are you out of your mind? That'll take a while, and the database round trip is not worth it. Well, what if we only called this method once when we built the application so that even if that call takes a few seconds, it'll only ever happen once and our users won't be affected? They'll get the top 1,000 movies delivered as quickly as or even faster than the 20 using
serverSideProps()
. The magic lies in the getStaticProps()
method, and our implementation looks like this:1 import { ObjectId } from "mongodb"; 2 import clientPromise from "../lib/mongodb"; 3 import { GetStaticProps } from "next"; 4 5 6 interface Movie { 7 _id: ObjectId; 8 title: string; 9 metacritic: number; 10 plot: string; 11 } 12 13 14 interface TopProps { 15 movies: Movie[]; 16 } 17 18 19 export default function Top({ movies }: TopProps) { 20 return ( 21 <div> 22 <h1>Top 1000 Movies of All Time</h1> 23 <p> 24 <small>(According to Metacritic)</small> 25 </p> 26 <ul> 27 {movies.map((movie) => ( 28 <li key={movie._id.toString()}> 29 <h2>{movie.title}</h2> 30 <h3>{movie.metacritic}</h3> 31 <p>{movie.plot}</p> 32 </li> 33 ))} 34 </ul> 35 </div> 36 ); 37 } 38 39 40 export const getStaticProps: GetStaticProps<TopProps> = async () => { 41 try { 42 const client = await clientPromise; 43 44 45 const db = client.db("sample_mflix"); 46 47 48 const movies = await db 49 .collection("movies") 50 .find({}) 51 .sort({ metacritic: -1 }) 52 .limit(1000) 53 .toArray(); 54 55 56 return { 57 props: { movies: JSON.parse(JSON.stringify(movies)) }, 58 }; 59 } catch (e) { 60 console.error(e); 61 return { 62 props: { movies: [] }, 63 }; 64 } 65 };
At a glance, this looks very similar to the
movies.tsx
file we created earlier. The only significant changes we made were changing our limit
from 20
to 1000
and our getServerSideProps()
method to getStaticProps()
. If we navigate to localhost:3000/top
in our browser, we'll see a long list of movies.![Top 1000 movies](/developer/_next/image/?url=https%3A%2F%2Fimages.contentstack.io%2Fv3%2Fassets%2Fblt39790b633ee0d5a7%2Fbltfb7866c7c87e81ef%2F65de2098ae62f777124be71d%2Ftop-1000-movie.png&w=3840&q=75)
Look at how tiny that scrollbar is. Loading this page took about 3.79 seconds on my machine, as opposed to the 981-millisecond response time for the
/movies
page. The reason it takes this long is that in development mode, the getStaticProps()
method is called every single time (just like the getServerSideProps()
method). But if we switch from development mode to production mode, we'll see the opposite. The /top
page will be pre-rendered and will load almost immediately, while the /movies
and /api/movies
routes will run the server-side code each time.Let's switch to production mode. In your terminal window, stop the current app from running. To run our Next.js app in production mode, we'll first need to build it. Then, we can run the
start
command, which will serve our built application. In your terminal window, run the following commands:1 npm run build 2 npm run start
When you run the
npm run start
command, your Next.js app is served in production mode. The getStaticProps()
method will not be run every time you hit the /top
route as this page will now be served statically. We can even see the pre-rendered static page by navigating to the .next/server/pages/top.html
file and seeing the 1,000 movies listed in plain HTML.Next.js can even update this static content without requiring a rebuild with a feature called Incremental Static Regeneration, but that's outside of the scope of this tutorial. Next, we'll take a look at deploying our application on Vercel.
The final step in our tutorial today is deploying our application. We'll deploy our Next.js with MongoDB app to Vercel. I have created a GitHub repo that contains all of the code we have written today. Feel free to clone it, or create your own.
Navigate to Vercel and log in. Once you are on your dashboard, click the Import Project button, and then Import Git Repository.
![Importing a project in Vercel](/developer/_next/image/?url=https%3A%2F%2Fimages.contentstack.io%2Fv3%2Fassets%2Fblt39790b633ee0d5a7%2Fbltc89beb7757ffec1e%2F65de20e0ee3a13755fc8e7fc%2Fimporting-project-vercel.png&w=3840&q=75)
The URL I'll use is the one provided above that has the application we built today. For reference, that URL is
https://github.com/mongodb-developer/nextjs-with-mongodb
. Add your projects GitHub URL and hit Continuar. On the next screen, you'll have the option to add Environment Variables. Here, we'll add the variables from our env.local
file.![Configuring a project](/developer/_next/image/?url=https%3A%2F%2Fimages.contentstack.io%2Fv3%2Fassets%2Fblt39790b633ee0d5a7%2Fblt0022681a81165d94%2F65de21086c65d7d78887b5ff%2Fconfiguring-project.png&w=3840&q=75)
After hitting the Deploy button, your Next.js application will be automatically built and deployed. This process will take a few minutes, but once it's done, you will get a URL where you can access your Next.js application.
NOTE: Vercel uses dynamic IP addresses, so you'll need to add an exception to access from any IP address in your MongoDB Atlas dashboard. To do this, simply navigate to the Network Access tab, hit the Add IP Address button, and then hit the Allow Access From Anywhere button, or for the Access List Entry, enter 0.0.0.0/0.
![Congratulations screen in Vercel](/developer/_next/image/?url=https%3A%2F%2Fimages.contentstack.io%2Fv3%2Fassets%2Fblt39790b633ee0d5a7%2Fblt7b00b1cfe190a7d4%2F65de212ac5985207f8f6b232%2Fcongratulations.png&w=3840&q=75)
We are live! Let's make sure everything works by navigating to the https://nextjs-with-mongodb-mauve.vercel.app/movies, https://nextjs-with-mongodb-mauve.vercel.app/api/movies, and https://nextjs-with-mongodb-mauve.vercel.app/top routes.
Neste tutorial, analisamos o exemplo oficial do Next.js com MongoDB. Mostrei como conectar seu MongoDB database ao seu aplicativo Next.js e executar queries de várias maneiras. Em seguida, implementamos nosso aplicativo usando o Vercel.
If you have any questions or feedback, reach out through the MongoDB Community forums and let me know what you build with Next.js and MongoDB.