Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Executing app.prepare() only once when exporting app instead of running a server (express) #3985

Closed
1 task done
Vadorequest opened this issue Mar 10, 2018 · 6 comments
Closed
1 task done

Comments

@Vadorequest
Copy link
Contributor

  • I have searched the issues of this repository and believe that this is not a duplicate.

Current Behavior

My app runs an infinite loop of webpack compilation, every action is therefore hyper slow.

Context

I'm running a Next.js app on top of Express, which is itself on top of serverless-offline, which is used to simulate the AWS lambda behavior.

Express is used by aws-serverless-express, which is a bridge between express and the Serverless framework. I therefore don't run an instance of express myself, but rather just configure the app and export it, as a module. This module is then used internally of aws-serverless-express to run the express server.

In this situation, I don't see how I can use app.prepare, which is async, because if I run it inside my lambda then it gets called at every call, including the HMR heartbeats.

@TomiTakussaari
Copy link

App.prepare() seems to be only necessary for develop mode (eg. HMR etc all), atleast with <=5.0.0.
So I avoided that problem in lambda with this:

#lambda.js
const serverless = require("serverless-http");

process.env.IN_LAMBDA = true;
process.env.NODE_ENV = "production";

...

const appServer = require("./server");

const handler = serverless(appServer);

exports.handler = (evt, ctx, callback) => handler(evt, ctx, callback);
#server.js
const express = require("express");
const next = require("next");
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();

function createServer() {
    const server = express();
    server.get("*", (req, res) => handle(req, res));
    return server;
}

if (process.env.IN_LAMBDA) {
    module.exports = createServer();
} else {
    app.prepare().then(() => {
        const server = createServer();
        server.listen(port);
    });
}

So app.prepare() is not called at all when running app in lambda.
Full source code here: https://github.com/TomiTakussaari/serverless-nextjs

@Vadorequest
Copy link
Contributor Author

Actually, my issue is somehow reversed @TomiTakussaari

My app works fine in production, but is "failing" in development. (local machine)

I don't run app.prepare either on AWS, using a similar trick to yours ;)

But I don't run app.prepare in dev mode either, because if I do then the app becomes completely unstable and keeps recompiling everything. I don't know what's the cause of this neither how to track/debug it.

I therefore have 2 servers running, one using Next directly, and another one using express. But the express one doesn't run app.prepare and doesn't get HMR (which is sad)

https://github.com/Vadorequest/serverless-with-next

@TomiTakussaari
Copy link

Ah I see.

At first I also attempted to use serverless-offline for dev mode too, but because serverless-offline seems to recreate lambda instance for every request (similar to how AWS Lambda could work in worst case), it would also start webpack process for every request, because app.prepare() is called for every request.

I could not see easy way out of this, so decided not to use serverless-offline in development mode, but just start my own custom server.js (expressjs) which calls app.prepare().

@Vadorequest
Copy link
Contributor Author

Yeah, that's exactly what I'm facing.

I think I need to split both, one part with Next + express for dev/local environment and one part with serverless-offline + bundle Next, for local testing

Or, get rid of serverless-offline, which wouldn't be a big issue for me since I only have one lambda in that case.

@sea129
Copy link

sea129 commented May 2, 2018

since v6.0.0 it moves defineRoutes into app.prepare. How do we avoid to call app.prepare?

@timneutkens
Copy link
Member

Solved in #5927

@lock lock bot locked as resolved and limited conversation to collaborators Jan 1, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants