Skip to content

Add streaming support for Next.js App Router #37

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

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

omidkazemi1
Copy link

This PR adds a new stream_nextjs_page function that enables streaming responses directly from Next.js to the client. This feature is particularly valuable for projects using Next.js 13+ with the App Router, supporting key Next.js features like instant loading states and streaming server components. Before this PR, the package couldn't properly support Next.js App Router's streaming capabilities, which are becoming increasingly important with Next.js 13+ and particularly Next.js 15. Features like loading UI, streaming, and suspense boundaries in Next.js require the ability to stream HTML rather than waiting for the full response.

Note: When using stream_nextjs_page, you cannot use a custom HTML template in Django, as the HTML is streamed directly from the Next.js server.

@omidkazemi1 omidkazemi1 added the enhancement New feature or request label Mar 31, 2025
@omidkazemi1 omidkazemi1 self-assigned this Mar 31, 2025
Copy link
Member

@mjnaderi mjnaderi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this valuable contribution! Streaming support is definitely crucial for modern Next.js applications, especially with the App Router becoming the standard.

Regarding the implementation, I have a few suggestions to streamline the API and documentation:

  • Prioritize Streaming in Docs: I think it would be best to present the new streaming approach as the primary method in the documentation. We can then introduce the older method afterward, clearly stating its limitations (no App Router or streaming support) but highlighting its advantage of allowing Django template customization. It might also be worth mentioning the possibility of future deprecation for the older method, or even formally deprecating it now to encourage adoption of the new approach.

  • Internal stream_nextjs_page (and the rationale behind it): Let's aim to keep the public API focused on nextjs_page and do not have stream_nextjs_page in the public API. The goal here isn't solely about having a cleaner API. By making the streaming functionality an internal part of nextjs_page, we actively encourage users to adopt the nextjs_page pattern for rendering Next.js pages. The key advantage of nextjs_page is that it avoids the need for users to write explicit Django views for their Next.js pages. If users write their own Django views and directly use a function like stream_nextjs_page within them, they might be tempted to include business logic (like database interactions or analytics tracking) directly in these views. This logic would then only execute when the page is initially loaded directly, but not during client-side navigation within the Next.js application. To ensure consistent behavior and leverage Next.js's client-side rendering capabilities effectively, we strongly recommend using nextjs_page as the way to serve Next.js content.

  • stream Parameter in nextjs_page: We could add a boolean stream parameter to the nextjs_page function, defaulting to False. If set to True, the view would be handled using the underlying streaming logic (currently in stream_nextjs_page).

  • Parameter Validation with Streaming: To avoid confusion and potential errors, if stream=True is passed to nextjs_page, we should raise an exception if any of template_name, context, or using are also provided. This clearly communicates that these parameters are incompatible with streaming.

By consolidating the functionality within nextjs_page and clearly documenting the new streaming capabilities as the recommended approach, we can provide a more intuitive and future-proof integration for django-nextjs users.

It's worth noting that this PR closes #22.

@mjnaderi
Copy link
Member

mjnaderi commented Apr 7, 2025

@danialkeimasi I'd also be really interested to hear your thoughts on this PR and these suggestions.

@danialkeimasi
Copy link
Contributor

I believe the default value of the stream argument in nextjs_page should be set to True. Our API should be designed with newer versions in mind, and most Next.js users now prefer streaming by default. I suggest we first make a backward-compatible release with stream=False, followed by a major release where stream=True becomes the default.

params = [(k, v) for k in request.GET.keys() for v in request.GET.getlist(k)]
next_url = f"{NEXTJS_SERVER_URL}/{page_path}"

session = aiohttp.ClientSession(
Copy link
Member

@mjnaderi mjnaderi Apr 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend using aiohttp.ClientSession and session.get as context manager (like the implementation of _render_nextjs_page_to_string).

From the documentation of aiohttp.ClientSession.request (link):

Returns a response object that should be used as an async context manager.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Customizing the HTML Response: Fix hydration error with Nextjs 13+ app router
3 participants