Do I have to use express in Next.js project? - javascript

Iā€™m making a website via Next.js.
Next.js provides SSR and dynamic routing.
Do I have to use express?
If so, why do I have to use it?
What kind of features of express are useful that are not provided from Next.js?
I think next build & next start show pages as well as I expected.

You do not need to use express, Next JS already has its own built-in server. However since express is popular, it is easier for developers to communicate with databases or handle other backend work.

Answer:
You do not need to use express to use nextJS out of the box; the vast majority of people don't.
Long Answer:
If you are not hosting on Vercel's platform, for example self-hosting (AWS,Digital Ocean, Azure etc...) you optionally have the ability to define a custom nextjs server and swap the underlying server implentation/framework (to use express, fastify, vanilla node etc..).
When might a custom server be a good idea?
when you're not hosting on vercel
when you have custom requirements & custom existing infrastructure
Scenario:
Imagine a large company that has lots of custom built infrastructure (logging, AB testing, custom linters etc) they've built over the years. They now want to take advantage of some of NextJS abstractions like:
different SSR rendering strategies
modern/flexible build system
all the other stuff you would need to implement from scratch, maintain, test...
Let's call this company XCompany. XCompany uses ExpressJS (doesn't matter which node server/framework) for their web server. They want to continue using ExpressJS since they've invested lots of time, resources building custom infrastructure and tools to work with it like AB testing integration, logging middlewares etc.
A custom server would allow XCompany to continue using Express without a complete re-write change and still benefit from the stuff NextJS that next offers SSR, the build system etc, nice conventions & guardrails etc.
At end of this response I linked to Lyft's engineering blogpost of their migration to using NextJS with their own infra
When you self-host your server and deploy it to your on infrastructure you get a long running node server, which is different from hosting on vercel, where the server is a serverless function.
Context/History
NextJS under the hood uses vanilla HTTP server. If you would like to get similar express functionality like the way routes are setup/organized you can use a package like next-connect.
Express use to rely on the connect package directly. Most nodejs servers follow connect like API for routing & setting up handlers.
For folks coming outside of the NodeJS world (python/flask), the connect style of organizing server routes is sort of like WASGI - Web Server Gateway Interface in philosophy.
Cons/Challenges of using Custom NextJS Server?
initial time investment learning custom nextJS server patterns.
The vast majority of people don't go down this route so documentation is more scarce
if you're not hosting on vercel you don't get serverless functions. This may not be con or downside, if you don't have a serverless use case.
For example, if you're web server will be using websockets/WebtRTC which require persistent long running connections
between client and server than serverless function's arent the best
choice here; there are work arounds, but i still think its not the
best use case. Note, you can still use add on serverless features to your custom server through another provider (AWS, Azure, etc...)
Moving Forward
Most js runtimes have been converging on exposing & using the Request & Response object APIs and exposing them to consumers.
Note, there's a ton of stuff that could be talked about here. Please leave follow up questions & I will try to update this answer accordingly
Resource(s)
how to deploy a nextjs custom server to another provider (not vercel)
fastify-nextjs has example how to create a custom nextJS server using fastify.
Changing Lanes: How Lyft is Migrating 100+ Frontend Microservices to Next.js
NextJS docs for Custom Server
npmjs - connect
npmjs - next-connect
How ExpressJS works under the hood
Video: From Scratch Express Routing
Express6 open source modern implementation of expressJS for educational purposes

Both, Next.js and Express.js are server side render solutions (SSR). However, you can integrate Next.js with Express.js with a custom server api, as stated in the documentation:
Most of the time the default Next.js server will be enough but there are times you'll want to run your own server to integrate into an existing application. Next.js provides a custom server api.
const express = require("express");
const next = require("next");
const port = 3000;
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = express();
server.get("/test", (req, res) => {
return app.render(req, res, "/test");
});
server.get("*", (req, res) => {
return handle(req, res);
});
server.listen(port, (err) => {
if (err) throw err;
console.log(`Ready on http://localhost:${port}`);
});
});
In example, it's showed how to use get Express method to handle routes in a Next.js app. The code above will render the React component at /api/test when user points to http://localhost:3000/api/test and pass down req and res objects to render.

Related

Next JS with API routes vs. Express.js API

How does NextJS with API routes differ technically from running an Node.js server with Express.js?
For example - If I want to develop a full-stack web application with MongoDB, can I use only Next.js with API routes for that purpose? Is connecting and modifying the database safe from the API routes, or is it a security risk?
In other words, are the Next.js API routes exposed into the client browser where the end user would be able to modify the code?
Nextjs API routes are ran serverside. Per the docs,
They are server-side only bundles and won't increase your client-side bundle size
So the end user is unable to modify the code. Just make sure they are in the /pages/api folder. Read the docs for more info: https://nextjs.org/docs/api-routes/introduction

Next api and backend

In NEXT project, API Routes let you create an API endpoint inside a Next.js app. You can do so by creating a function inside the pages/api directory that has the following format:
// req = HTTP incoming message, res = HTTP server response
export default function handler(req, res) {
// ...
}
Then what is different between express backend and next api.
If I use next api, can I build all backend and frontend?
And how can I get access to database on next api?
Is that possible?
If I use database configuration on next api, then how will it be rendered in SSG?
I can only speak of what I know about the question. In my current project, we use an Express server with Next.js.
Reasons to Use Express With Next
Express has lots of middlewares available and the ecosystem around it is solid. In my case, we already have multiple Express apps in production. Adding the Express layer helps us keep the behaviors of different servers as similar as possible.
Reasons to Use Next API Route Directly
Next API routes are straightforward if you don't have many custom middlewares. Next.js already come with common middlewares to handle many common tasks. I think the decision comes down to where you are going to deploy your application. If you want to use Vercel with serverless functions, you can't use a custom server. You can find more information about serverless here
Can You Build Backend & Frontend with Next and its API Routes
Yes, you can absolutely do it. But you have to decide whether this is a more suitable solution.
Can You Access Database in API Routes
Yes
What About SSG
As far as I know, API routes are part of a server bundle. Next.js will not statically generate page/api/**/*. All your SSG pages should work as expected.
I hope I provided some useful information here.

Next.js Architecture

I am looking for some Next.js Architecture advise please šŸ™
I am in the middle of migrating a very large express NodeJS app which has a custom SSR setup over to a Next.js setup.
For the current NodeJS site I have:
A bunch of routes (which hook up controllers / apis, do fancy redirections etc)
Have a ton of middlewares
Ton of logic in a bunch of express controllers (these controllers do things like API calls, transforming data, validation and the SSR of some React components to form the application)
Most of the time the NodeJS server calls other Microservice APIs (on the same VPC) to fetch data within these controllers (eg: search api, auth api, location api etc - which are all seperate REST api servers) Note: when it fetches from these APIs its done so on an internal api address only
The React Website itself calls the same NodeJS server to fetch data via client side JS when there is a route change eg: The frontend URL would be: www.mywebsite.com.au
And any api call done from the frontend is done with route: www.mywebsite.com.au/api/*
Based on all the docs i have read so far, I figure the best setup is:
To keep my existing express setup for routes / middlewares (for which I have a ton of) this includes the /api/* ones
Migrate controller fetching logic to the publically accessible express apis /api/* (which I kind of already have but need to clean up)
For the existing express controller routes, route these to Next.js instead and use nextApp.render to specific next pages
Use getInitialProps in the Next.js pages to fetch data from those apis I mentioned in 2.
Also add the old prop transform logic that was in the express controllers to getInitialProps
This is so that the server and client share the same logic of whats in getInitialProps - and this will make the architecture clean and give me the ability to have smooth transition to use Link.
The thing im struggling with it is step 4.
It means now on SSR of a page request it needs to call out to the public api (www.mywebsite.com.au/api/*) on getInitialProps to fetch its data.
To me seems like a performance overhead to do this as it requires a network hop to public domain mywebsite.com.au to fetch data it could have got locally on that same request (by calling localhost:3000/api/* for instance)
Any advise on how to avoid the network hop outside for server render?
Can I detect if its a server render and then use an internal URL (eg: use localhost:3000/api/* on the request to the same web server) or is that not best practices when using Next.js?
The server needs to call out to itself to fetch its data, alot of the overhead involved with fetching data is around the delay (I.E Between the client and nearest datacenter) this will be less of a concern when its (datacenter -> datacenter).
If performance is still an issue, your next best bet will be to do SSR caching, of which there are many different methods alot you can find in a quick google search however it will depend on your hosting/setup.
I treat listing-page.jsx and handler for api/listing route to be the same. You may need to write 2 small functions to extract the parameters passed into the request and pass it down to your service module function like ListingService.getSingleListisng(id)

Can I use my own NodeJS server in between the client and Firebase and still use methods like "on()"?

I am creating a web application using Firebase. The client of the application communicates to my own NodeJS server which in turn communicates with Firebase app, if necessary.
Firebase offers some cool features, for example the on() function which automatically updates whenever data in Firebase is modified.
Is there any way for me to use this in my NodeJS app so that my server passes on the update to the client, without the client having to connect to Firebase directly?
I've tried including an on function like this, but I get an error when data is updated and the server crashes. Apparently, Node can't just send another response if there wasn't an explicit request. Any tips?
app.get('/project/save', function(req, res) {
var result = firebase_admin.database().ref().on('value', function(d){
console.log(d.val());
return res.status(200).json(d.val());
});
});
You can definitely put your own node.js server between your users and the Firebase Database. But by doing so, you'll be taking on the role of app server. And that means that you'll also have to provide your own implementation/proxy for Firebase features, such as the on() methods.
The approach in the linked answer is way easier and gets you most of the same benefits. It is also documented in this documentation:
So here both your users and your back-end code (in this case running on App Engine Flexible Environment, but it could run on any trusted environment) are essentially clients for the Firebase Database.
We recently gave a talk at the Firebase Dev Summit, where we covered this approach too: Develop mobile apps without infrastructure.

Node JS REST API, now how do I serve HTML files?

So I did a REST Api in Node JS and now I have a blocker.
app.use('/api', router);
This code makes sure that every url is prefixed with api. Now what If I want to serve an HTML file when the path is just "/"? Should I create another "express" application? I'm just working in localhost right now and I have to do "node server.js" to launch the server. I can't really launch 2 servers at the same time, or can I? One for the api: server.js and one for the rest of the code: client.js (that's a bad name but whatever.). I'm confused on how I have to setup things...
Thanks you for the help.
You can see that you use your api routes to, most likely, serve JSON content. Well, using the same mechanism you can configure your router to serve any other kind of content for a particular route.
So, if you would like to serve some HTML content for the root of your application, let's say a Wiki page or documentation of you API, it is as simple as:
app.get('/', function(req, res){
res.render('index.html');
});
Of course, if you are just rendering a static html page, you might just as well configure a middleware to define where you place all your static content.
app.use(express.static(path.join(__dirname, 'www')));
Where www is the directory where you chose to put your index.html page.
Having said that, if what you built was a REST API, chances are that it is intended to be reused by multiple other applications, and therefore, it is customary to that the client applications are running independently of the REST API. Some client applications may not even be Web applications (i.e. Android, iOS, desktop apps, etc). So you should take that into account before thinking in developing a Web client within the same project.
But nothing prevents your from providing a default implementation of UI that consumes your REST API within the same project/server. And yes, it is possible to run more than one HTTP server serving different applications. There are considerations you might need to take into account if you use separate servers for your API (i.e. CORS).
If you decide to serve everything within the same application, you may want to make sure there is a clear decoupling in the design in a such a way that the client application consumes and uses the rest layer as if it was independent. You should isolate the routes for the REST layer from those used for your client in such a way that if, later on, you want to make the client APP run independently you would not have a problem with that.
How about something like express-namespace to help you organize your routes?

Categories

Resources