vercel / next.js

The React Framework
https://nextjs.org
MIT License
127.03k stars 26.99k forks source link

Provide a mechanizm to disable SSR #4381

Closed cherniavskii closed 8 months ago

cherniavskii commented 6 years ago

Is your feature request related to a problem? Please describe. The problem is that sometimes server load is high because of SSR. Right now it can be optimized by turning off SSR for some components, but it doesn't solve the problem fully.

Describe the solution you'd like Ideally - to provide something like Electrode has: Server Side Rendering Modes.

Electrode constantly monitors the performance of your app and turns off server-side rendering if app performance is degrading.

Describe alternatives you've considered An alternative (and probably more elastic) solution would be to provide SSR Modes without any performance monitoring.

Additional context I know that right now next.js is tightly coupled with SSR, but SSR modes should help a lot at large scale.

P.S. Thanks you guys for working on such a great project ;)

mauvew commented 6 years ago

+1

soroushchehresa commented 5 years ago

+2 :)))

mzaidse commented 5 years ago

+1

Zertz commented 5 years ago

While not built in, react-no-ssr works quite well for that purpose!

gautamsi commented 5 years ago

proposal: Checking for a static property on default import with { ssr: false} should make this dynamic component without ssr.

This will greatly help in rapid development while I figure out if component can be dealt with ssr or not.

farhadniaz commented 5 years ago

We should provide a flag in Nextjs config to provide Universal and SPA mode. this is very important . After working with Nextjs in different projects i find out Nextjs has many powerful aspects but it suffers from community support .

timneutkens commented 5 years ago

@farhadniaz I'm not sure what you're asking for 🤔 You can already choose to not render the tree on the server using something like react-no-ssr or a React hook.

farhadniaz commented 5 years ago

@timneutkens react-no-ssr not the answer . I please look at the NUXT.js SPA mode and you will find out what i mean

timneutkens commented 5 years ago

I'm not going into this further as it's off-topic to this issue, this issue is related to backoff under load. Nuxt's SPA mode is quite the same as just opting out of SSR, except it's a flag, which in general you don't want, as you might want to prerender part of the skeleton.

farhadniaz commented 5 years ago

@timneutkens so you mean in _app.js we have to use react-no-ssr as root component?

nguyenvanhoang26041994 commented 5 years ago

I have the same problem and that what i resolve my.

// pages/_app.js
import dynamic from 'next/dynamic';

export default dynamic(() => import('./App'), { ssr: !process.env.APP_MODE === 'SPA' });
// getInitialProps function
export default async ({}) => {
  return {
    gotInitialProps: true,
  };
}
// if gotInitialProps = false, fetch API
useSPAMode(gotInitialProps, getInitialProps);
import React, { useEffect } from 'react';
import useStore from './useStore';

const useSPAMode = (gotInitialProps, getInitialProps) => {
// getInitialProps maybe using store. i using redux for nextjs
  const { dispatch, getState } = useStore();
  useEffect(() => {
    if (!gotInitialProps) {
      getInitialProps({
        reduxStore: {
          dispatch,
          getState,
        },
        isServer: false,
      });
    }
  }, []);
};

export default useSPAMode;
sophister commented 4 years ago

Does Next.js provide such mechanizm now? I can't find any document related to this.

benalexb commented 4 years ago

Bumping this issue up, as it has become quite common these days to use Next as a static site generator. Of course, one can always build, export, and serve the static website, but that comes at a cost (live-reloading and other development sugar).

There are other motivations too behind the ability to disabled SSR, such as to quash react's warning when the server-side rendered DOM does not match the client's, which is very common on a static website as there is no pre-loaded data.

Hubro commented 4 years ago

I want to be able to temporarily disable server side rendering so I can debug a crash in my browser with dev tools rather than trying to figure out from the dev server log what happened. Installing a new dependency and wrapping my code in a new element seems like an excessive requirement to achieve this :/

I just want something like next --no-ssr until I'm done debugging the error, then I remove the flag again. Why would something like that be problematic to implement? Couldn't you even just include react-no-ssr by default and wrap the topmost element in <NoSSR> if the flag is provided?

lostfictions commented 4 years ago

react-no-ssr won't help if you have side-effectful imports that rely on the DOM. But you can use next's built-in dynamic import functionality instead, and move your page root (or whatever subset of it can't run on the server) into a different file:

import dynamic from 'next/dynamic'
const App = dynamic(() => import('../components/App'), { ssr: false })
export default () => <App />

This works well enough for me as someone making a static site that relies on eg. WebGL and DOM APIs, but who still wants to take advantage of Next's sensible defaults and configurability (rather than, say, trying to puzzle out which variant of create-react-app override packages is still maintained).


This maybe also suggests a sketch for folks who want to toggle SSR with a switch on the command line or disable it in development and enable it during build for static export:

import dynamic from 'next/dynamic'
const App = dynamic(() => import('../components/App'), {
  ssr: process.env.NEXT_PUBLIC_SSR_ENABLED
})
export default () => <App />

Then, on the command-line:

NEXT_PUBLIC_SSR_ENABLED=false npm run dev

That said, I personally think it would still be great if Next added better support for non-SSR scenarios -- as mentioned in this thread, there's still lots of idiosyncrasies for people using Next for fully static (non-hybrid) static site generation, etc.

renatodex commented 4 years ago

Dynamic imports really make our life easier, but if you think about Canvas integration, there are a few issues using the SSR approach. I've tried to use PhaserJS before, which relies on Dom at the very moment it is imported, and I never could make it load as a component.

Of course, Canvas frameworks like Phaser don't really play well with React and Virtual Dom, but even a loose abstraction is hard to assemble with SSR.

timneutkens commented 4 years ago

@renatodex you can dynamically import files on client-side using import()

renatodex commented 4 years ago

Hey @timneutkens ! I don't want to distort the main goal of this Issue, so I've posted my failed experiment with Phaser as a new Issue in the Issues of NextJS. https://github.com/zeit/next.js/issues/13417 Take a look when you have time!

eric-burel commented 4 years ago

Not sure if it has been mentioned before, but easy and global disable of SSR is useful in the context of e2e/integration testing.

Cypress provides mock for requests triggered by the browser, but it's much more difficult to mock server side queries, especially when they hit the same origin. There's not much recipe to handle this on the web, so the easiest path is to disable SSR when running e2e tests.

jgoux commented 4 years ago

react-no-ssr won't help if you have side-effectful imports that rely on the DOM. But you can use next's built-in dynamic import functionality instead, and move your page root (or whatever subset of it can't run on the server) into a different file:

import dynamic from 'next/dynamic'
const App = dynamic(() => import('../components/App'), { ssr: false })
export default () => <App />

This works well enough for me as someone making a static site that relies on eg. WebGL and DOM APIs, but who still wants to take advantage of Next's sensible defaults and configurability (rather than, say, trying to puzzle out which variant of create-react-app override packages is still maintained).

This maybe also suggests a sketch for folks who want to toggle SSR with a switch on the command line or disable it in development and enable it during build for static export:

import dynamic from 'next/dynamic'
const App = dynamic(() => import('../components/App'), {
  ssr: process.env.NEXT_PUBLIC_SSR_ENABLED
})
export default () => <App />

Then, on the command-line:

NEXT_PUBLIC_SSR_ENABLED=false npm run dev

That said, I personally think it would still be great if Next added better support for non-SSR scenarios -- as mentioned in this thread, there's still lots of idiosyncrasies for people using Next for fully static (non-hybrid) static site generation, etc.

@lostfictions @timneutkens Does this strategy allows to use something like React-router and being able to export the app as a single index.html + multiple js files (code-splitted)? I'm in the same boat as you @lostfictions , I want to take advantage of Next.js extendable configuration in place of CRA, but I don't want to have a server coupled with my SPA. I'm aware of next export but I need a single html entry point to my app (in order to wrap it with capacitor for mobile distribution).

verekia commented 4 years ago

It would be very convenient for debugging purposes to have this mode option, similar to what Nuxt has. But to go even further, it would also be convenient to have an ssr-only mode. This is very useful to debug universal authentication for instance. You can make sure everything works during client navigation only, and during server navigation only. I used to do this when I made my own isomorphic apps without Next and I really miss being able to do that.

Something like that.

It was not that complicated when I was doing it by hand. For SPA-only I simply rendered an empty main app root element for every page, with no server data, and for SSR-only, I didn't include any JS file in the HTML. Now of course it's a bit more complicated in the Next architecture, but both are quite simple in theory.

Edit: I just realized that for development purposes, SSR-only can be achieved by just disabling JavaScript in the browser.

eric-burel commented 4 years ago

Another use case I have for SSR disabling is education. It would be very cool to be able to first learn Next without SSR, then activate SSR and show what it breaks, and then learn how to handle client-only code gracefully.

I strongly felt this need while trying to teach Next to data science students that are used to heavy client-only libraries like Chartjs, D3, leaflet etc. In the future I would probably favour Create React App for this reason, but I'd prefer keeping Next.

johot commented 4 years ago

I have created a web app that I host inside a React Native WebView. I love the developer experience of Next.js but in this case I have no use for SSR it just makes thing more complicated, gives me layout issues for non SSR supported hooks etc etc. In this case I want to use react router for the routing because of the support for nested routes that don't loose state and so on.

I would love an easy and official way of disabling SSR, right now I am following this guide by @tannerlinsley which is great: https://gist.github.com/tannerlinsley/65ac1f0175d79d19762cf06650707830

I definately see a lot of use cases for a "SPA mode / no SSR mode".

Thank you for an awesome product @timneutkens !

amirhbakan commented 2 years ago

next export + next/router and a nginx that points for example / can work like SPA but it’s not the best solution, because next export generates many htmls and also if we accept multi htmls there is no way to point pages like product/[id] with nginx but it handled clientside with next/router. I think next export + next/router could be a good solution for SPA mode with some features, 1- really generate one html or a solution for pointing dynamic routes pages with nginx. 2- handle 404 clientside in next/router with a flag.

eric-burel commented 2 years ago

next export + next/router and a nginx that points for example / can work like SPA but it’s not the best solution, because next export generates many htmls and also if we accept multi htmls there is no way to point pages like product/[id] with nginx but it handled clientside with next/router. I think next export + next/router could be a good solution for SPA mode with some features, 1- really generate one html or a solution for pointing dynamic routes pages with nginx. 2- handle 404 clientside in next/router with a flag.

That's the point of the proxy here. Last time I tested (a while ago), Next would produce a [id].html in fallback mode. You only get many HTML, eg one per post of your blog, if you don't use fallback. Your Nginx can point to this [id].html which would then be able to do client-side fetching to get the right content. This is faster than an SPA because your code is split per page.

I agree that a pure SPA mode could be interesting as well, as it is the simplest way to export. However I've kinda dropped this idea a while ago, because I prefer the way Next uses the presence of the server intelligently. If you really need an SPA, then Create React App might be a simpler alternative.

amirhbakan commented 2 years ago

next export + next/router and a nginx that points for example / can work like SPA but it’s not the best solution, because next export generates many htmls and also if we accept multi htmls there is no way to point pages like product/[id] with nginx but it handled clientside with next/router. I think next export + next/router could be a good solution for SPA mode with some features, 1- really generate one html or a solution for pointing dynamic routes pages with nginx. 2- handle 404 clientside in next/router with a flag.

That's the point of the proxy here. Last time I tested (a while ago), Next would produce a [id].html in fallback mode. You only get many HTML, eg one per post of your blog, if you don't use fallback. Your Nginx can point to this [id].html which would then be able to do client-side fetching to get the right content. This is faster than an SPA because your code is split per page.

I agree that a pure SPA mode could be interesting as well, as it is the simplest way to export. However I've kinda dropped this idea a while ago, because I prefer the way Next uses the presence of the server intelligently. If you really need an SPA, then Create React App might be a simpler alternative.

Thanks for the reply, but I need this because I have implemented the Dynamic rendering with NextJS, I want to have one codebase with an SSR build and a CSR build, my SSR side is just SSR, not SSG. we implemented it with some tricks, but I want a good solution for CSR build to really have a SPA. I think if these features implement, the Dynamic Rendering with NextJS is a robust technique for websites.

habovh commented 2 years ago

For anyone looking for a simple and zero additional dependency solution, I suggest wrapping your app in a component that you can import using Next dynamic() import. Then you can check the router for a set query parameter, allowing you to easily debug issues on a one-off basis.

Something like this would "disable" SSR for any component below the <Main /> node when the URL contains the query string ?disable-ssr=1.

// _app.js
import dynamic from 'next/dynamic'

import MainSSR from '../components/main'

const MainNoSSR = dynamic(() => import('../components/main'), { ssr: false })

class MyApp extends App {
  render() {
    const { Component, router } = this.props
    const disableSSR = router.query['disable-ssr'] === '1'
    const Main = disableSSR ? MainNoSSR : MainSSR
    return (
      <>
        <Head>
          {...}
        </Head>
        <Main>
          <Component />
        </Main>
      </>
    )
  }
}
verekia commented 2 years ago

@habovh This is really great. What's in MainSSR? Just something like const Main = ({ children }) => <>{children}</>?

habovh commented 2 years ago

@verekia yup exactly. It's also handy to add content that must be present on every page —such as the cookie banner alongside the children.

Edit: just to be precise, I'm referring to the component exported in components/main that is being imported by both MainSSR and MainNoSSR using two different import methods.

paulogaspar7 commented 2 years ago

New version of Ant Design's Pro-Components also not supporting SSR. (Node complains with a "SyntaxError: Cannot use import statement outside a module".)

remorses commented 1 year ago

I just created a Next.js plugin to disable SSR and remove all the React components from your server bundle.

This plugin will transform your pages to only return null in the server, causing dead code elimination to remove all the React components and libraries from your server output code. On the client, the pages will return null until mounted.

To use it simply add the skip ssr directive at the top of your pages:

// pages/index.js
'skip ssr'

export default function Home() {
    return <div>hello world</div>
}

Read more in the Elacca repository

samcx commented 8 months ago

Hi everyone!

Since this is a feature request, I will be moving this over to :nextjs: discussions. :loading: