QueraTeam / django-nextjs

Next.js integration for Django projects
MIT License
341 stars 17 forks source link

ASGI Mode Causes Timeout Errors in Next.js Server-Side Rendering #23

Closed neuneed closed 1 year ago

neuneed commented 1 year ago

Hello, I've encountered an issue when trying to integrate django-nextjs into my Django project. The issue arises when using ASGI and channels to run the server.

I have a URL path like so: url(r'^content', views.nextjs_content, name='content'), and the associated view function is an asynchronous function:

async def nextjs_content(request):
    return await render_nextjs_page(request)

Everything works perfectly fine in this setup, including Fast Refresh. However, when I introduce Server-Side Rendering (SSR) into my Next.js page (src/pages/content/[id].tsx), I start to encounter timeout errors. Specifically, my getServerSideProps function times out:

export async function getServerSideProps(context) {
    const { id } = context.params
    const url = `content/${id}/`

    try {
        const res = await axiosInstance.get(url)
        return { props: { data: res?.data } }
    } catch (error) {
        return {
            notFound: true,
        }
    }
}

The error I get is: AxiosError: timeout of 20000ms exceeded.

Interestingly, if I switch back to WSGI mode using python manage.py runserver --noasgi and add path("", include("django_nextjs.urls")) to my URLs, everything works fine. However, in this setup, I lose the benefit of Fast Refresh.

Could you provide some guidance on this? It seems like there might be some issue with the interaction between ASGI, Django-Nextjs, and Next.js's SSR.

Thank you for your time!

danialkeimasi commented 1 year ago

Hi, There is two possibilities:

  1. Based on what you explain, it seems like you are requesting the same page in getServerSideProps and you are getting to a infinite loop. It is not required to make a request to Django within this function.

  2. Since WSGI mode was ok and ASGI mode was not, you may have an sync custom middleware that causes this problem. It will produce a deadlock because of this sequence:

    • User requests to Django to get HTML. in this request sycle, Django requests to Nextjs, and because there is one middleware that is not async capble and there is only one thread, it will wait be blocked and your Django server will not respond to new requests.
    • Nextjs requests to Django in getServerSideProps to get data.
    • Django is blocked since it was already waiting for HTML response from Nextjs.

I think the secound one is more likely.

neuneed commented 1 year ago
  • Django is blocked
  1. The api is different with the HTML urls. So that's should be fine.
  2. Django must been blocked in the same time waiting for HTML and return an api call. maybe thats why.

let me try this

If you're using django channels, make sure all your middlewares are async-capable.

Thank you!

neuneed commented 1 year ago

@danialkeimasi After spending some time converting all my middlewares to use @sync_and_async_middleware to support django middleware asynchronous, I managed to solve the issue!

Cheers!