Search code examples
javascriptnode.jsnext.jsisomorphic-javascript

How to best import "server-only" code in Next.js?


In the getServerSideProps function of my index page, I'd like to use a function foo, imported from another local file, which is dependent on a certain Node library. Said library can't be run in the browser, as it depends on "server-only" modules such as fs or request.

I've been using the following pattern, but would like to optimize it. Defining foo as mutable in order to have it be in scope is clunky and seems avoidable.

let foo;
if (typeof window === "undefined") {
  foo =  require("../clients/foo");
}

export default function Index({data}) {
  ...
}

export async function getServerSideProps() {
  return {
    props: {data: await foo()},
  }
}

What would be the best practice here? Is it somehow possible to leverage ES6's dynamic import function? What about dynamically importing within getServerSideProps?

I'm using Next.js version 9.3.6.

Thanks.

UPDATE:

It seems as if Next.js's own dynamic import solution is the answer to this. I'm still testing it and will update this post accordingly, when done. The docs seem quite confusing to me as they mentionn disabling imports for SSR, but not vice versa.

https://nextjs.org/docs/advanced-features/dynamic-import


Solution

  • When using getServerSideProps/getStaticProps, Next.js will automatically delete any code inside those functions, and imports used exclusively by them from the client bundle. There's no risk of running server code on the browser.

    However, there are a couple of considerations to take in order to ensure the code elimination works as intended.

    • Don't use imports meant for the server-side inside client-side code (like React components).
    • Ensure you don't have unused imports in those files. Next.js won't be able to tell if an import is only meant for the server, and will include it in both the server and client bundles.

    You can use the Next.js Code Elimination tool to verify what gets bundled for the client-side. You'll notice that getServerSideProps/getStaticProps gets removed as do the imports used by it.