Skip to content

How to conditionally include packages on client but not server (and vice-versa)? #219

@evantahler

Description

@evantahler

Say you wanted to render some maps in your Next application. You chose the fairly popular react-leaflet project, which takes the very popular leaflet library... and React-izes it.

It turns out that Leaflet is in fact not ready for an isomorphic application, as it has things like window and navigator all over its codebase. This is turn causes Next to crash with a sad ReferenceError: window is not defined.

You can't use conditional logic in your map component because include statements need to happen at the top of the file, and at boot. You can change from include to require (and require conditionally), but that seems like a bad idea, and Next throws a warning (below). You can block rendering a map on the server, but not the inclusion of the react-leaflet => react libraries.

The warning Next throws when using a conditional required:

Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
 (client) react-empty: 27 --><!-- react-empty: 28 
 (server) react-empty: 27 --><p data-reactid="28">

It's fairly easy to check if you are running on the sever or client:

export default function isNode(){
  // http://stackoverflow.com/questions/4224606/how-to-check-whether-a-script-is-running-under-node-js
  return (typeof process !== 'undefined') && (process.release) && (process.release.name === 'node');
};

How should we handle something like this? I could imagine a try/catch scenario when rendering on the server looking for specifically window, navigator, etc and rendering a small ./pages/_unrenderable.js in those components.... but that seems... hacky.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions