Can you please add an example here:
https://github.com/zeit/next.js/tree/master/examples
that uses API routes to handle POST requests with also a custom Express server to serve the application? I feel like there are conflicts between routes provided by the Express server, the file system routing of Next and the API routes within the api
folder. The following are related issues:
https://github.com/zeit/next.js/issues/7960
https://github.com/zeit/next.js/issues/8178
https://github.com/zeit/next.js/issues/8120
In order to make it work now I have to do something that seems pretty crazy:
pages/api/signin.js
'use strict';
module.exports = require('../../src/apiHandlers').postSignIn;
````
`server.js`
```js
expressApp.post('/api/signin', require('./pages/api/signin'))
Sorry for interfering... But why do you people need API routes? Having a separate server that handles API is more performant, more stable, more extensible and more comfortable to configure. You will be able to deploy them separately as well. No idea why someone decided to add this feature...
@ivan-kleshnin Why being sorry? Thank you instead. Here:
https://zeit.co/blog/now-node-helpers
they say Micro is actually 18% faster than the old way with Express, and also I see this new method as a way to save some duplication and project management efforts (instead of having two folders, two package.json, etc.). The really ideal way would have been giving the possibility to create the API and serve the application in a single custom server file like they explain here:
https://nextjs.org/docs#custom-server-and-routing
But at least today, it turns out that the custom server examples don't even work, if you try them out by deploying them. It seems like the server.js file is completely ignored even with the start script changed, whatever you put in there doesn't make any difference.
they say Micro is actually 18% faster than the old way with Express, and also I see this new method as a way to save some duplication and project management efforts (instead of having two folders, two package.json, etc.).
I went this road two times with real products and now I'm totally convinced that two separate projects (one for API and one for client/SSR) are MUCH better for most real-world cases. Exceptions are possible of course.
Code duplication turned out to be a minor issue in comparison. I had plenty of problems with configuration, deployment, QA, and scaling... stemming from the fact I merged and coupled two different projects into one. You can always solve duplication by extracting and publishing an NPM package (public or private). The problems of monolite hovewer are basically impenetrable.
they say Micro is actually 18% faster than the old way with Express, and also I see this new method as a way to save some duplication and project management efforts (instead of having two folders, two package.json, etc.).
I went this road two times with real products and now I'm totally convinced that two separate projects (one for API and one for client/SSR) are MUCH better for most real-world cases. Exceptions are possible of course.
Code duplication turned out to be a minor issue in comparison. I had plenty of problems with configuration, deployment, QA, and scaling... stemming from the fact I merged and coupled two different projects into one. You can always solve duplication by extracting and publishing an NPM package (public or private). The problems of monolite hovewer are basically impenetrable.
I am also facing so many problems that I am constantly thinking if I should also do what you are saying... But are you talking about doing a "monorepo" with www
and api
folders or two completely different projects with different deployments as well?
Monorepo is a single VCS (e.g. Git) repo. That's all it is i.m.o.
It's totally possible and valid to put N different projects (with M deployment pipelines) into a monorepo.
The way we handle it currently is:
Monorepo. It's easier to handle users, permissions and workflow with monorepo.
It's easier to share non-web scripts with monorepo. It's easier to make team members see what others are doing with monorepo.
Multiple projects. It's easier to decouple dependencies with multiple projects. It's easier to apply QA, linting, gradually add static types, etc. with multiple projects. You don't have to fight against nested folders and overcomplicate. Most tools work the best when it's a single simple folder and fail in some way when you start to introduce multiple environments (like Node + Browser).
So, in terms of filesystem we have
projectfolder/
api/
node_modules/
package.json
client/
node_modules/
pages/ (e.g. NextJS)
components/ (e.g. React)
package.json
scripts/
.git/
.gitignore
Just my 2 cents. We tried different approaches through years and this works the best for us.
As for deployments, with monorepo + multiprojects you can technically do it in both ways:
1) Deploy all projects at once
2) Deploy a single project (client or API)
And we use both approaches frequently. Sorry for offtopic. This is all I've got to say.
I am also missing a way to have both, api routes and a custom server.js. The api routes are ignored once you use a custom server.js. The reason why I use a custom server.js currently is only to force SSL redirection in production mode. I know some people would recommend handling this in a load balancer - but there is no way to do this on a standard heroku instance.
My workaround is basically not using API routes and do everything with express.
I have not tried, but maybe it does not work because there is no handler for POST in the examples..
so maybe something like this would work and if it does work, examples should probably be updated:
app.prepare().then(() => {
const server = express()
// ... custom express middlewares
server.get('*', (req, res) => {
return handle(req, res)
})
// Does this fix it? Also fallback for POST.. ?
server.post('*', (req, res) => {
return handle(req, res)
})
server.listen(port, err => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
@peec thank you for your comment. Even if I wanted to have a single Express server I can't. When you deploy on Zeit Now you are forced to use serverless mode even if you specify target: server
in the Next.js config.
Most helpful comment
Sorry for interfering... But why do you people need API routes? Having a separate server that handles API is more performant, more stable, more extensible and more comfortable to configure. You will be able to deploy them separately as well. No idea why someone decided to add this feature...