5

i am trying to create a simple UI library using react for Nextjs 9.4, here what i am doing

// input.js in React UI Lib

import React from "react";
import styled from "./input.module.scss";

const Input = React.forwardRef((props, ref) => (
  <>
    {props.label && <label className={styled.label}>{props.label}</label>}
    <input className={styled.input} {...props} ref={ref} />
  </>
));

export default Input;

and made an index to export all modules for simplicity

// app.js the index file for the lib

import PrimaryButton from "./components/button/primaryButton";
import TextInput from "./components/input/input";
import PasswordInput from "./components/passwordInput/password";
import CheckBox from "./components/checkbox/checkbox";

export {
  PrimaryButton,
  TextInput,
  PasswordInput,
  CheckBox
};

also here is my webpack config to build for SSR Next

const path = require("path");
const autoprefixer = require("autoprefixer");
const nodeExternals = require("webpack-node-externals");

const CSSLoader = {
  loader: "css-loader",
  options: {
    modules: "global",
    importLoaders: 2,
    sourceMap: false,
  },
};

const CSSModlueLoader = {
  loader: "css-loader",
  options: {
    modules: true,
    importLoaders: 2,
    sourceMap: false,
  },
};

const PostCSSLoader = {
  loader: "postcss-loader",
  options: {
    ident: "postcss",
    sourceMap: false,
    plugins: () => [autoprefixer()],
  },
};

const SassLoader = {
  loader: "sass-loader",
  options: {
    // Prefer `dart-sass`
    implementation: require("sass"),
  },
};

module.exports = {
  target: "node",
  entry: "./src/app.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "bundle.js",
    chunkFilename: "[id].js",
    publicPath: "",
    library: "",
    libraryTarget: "commonjs",
  },
  externals: [nodeExternals()],
  resolve: {
    extensions: [".js", ".jsx"],
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        loader: "babel-loader",
        exclude: /node_modules/,
      },
      {
        test: /\.(sa|sc|c)ss$/i,
        exclude: [/node_modules/, /\.module\.(sa|sc|c)ss$/i],
        use: ["style-loader", CSSLoader, PostCSSLoader, SassLoader],
      },
      {
        test: /\.module\.(sa|sc|c)ss$/i,
        exclude: /node_modules/,
        use: ["style-loader", CSSModlueLoader, PostCSSLoader, SassLoader],
      },
      {
        test: /\.(png|jpe?g|gif)$/,
        loader: "url-loader?limit=10000&name=img/[name].[ext]",
      },
    ],
  },
};

1-i build

2-publush on npm

3-import in Nextjs

then everything works well , but the problem is when i try to refresh (F5) the page during development i get the error

Unhandled Runtime Error
ReferenceError: document is not defined

how can i fix that ?

4
  • 1
    you have not access window || document during SSR so try to prevent rendering during this time like , typeof window !=== 'undefined' ? <Component /> : null Commented Jun 12, 2020 at 9:32
  • @Mashiro i have changed component to typeof window !== 'undefined' ? <> {props.label && <label className={styled.label}>{props.label}</label>} <input className={styled.input} {...props} ref={ref} /> </> : null, still same error Commented Jun 12, 2020 at 9:49
  • can u provide a link to your bundled file Commented Jun 12, 2020 at 10:27
  • i figured out why it occurs check answer Commented Jun 12, 2020 at 10:34

4 Answers 4

4
  1. try to render component only in client side you can do with:

    typeof window !== 'undefined' ? <Component /> : null

  2. you are using style-loader in your webpack config, it will inject styles into head using document.createElement that is not availabe in SSR, you can choose other options like mini-css-extract-plugin

Sign up to request clarification or add additional context in comments.

1 Comment

typeof window !== 'undefined' && <Component /> works too
1
const Example = dynamic( () => import('example'), { ssr: false } )

https://github.com/elrumordelaluz/reactour/issues/130

Comments

1

try to check component in client side rendering ex:

const isBrowser = typeof window !== 'undefined';
isBrowser ? <Component/> : null;

another option is try to render using ssr false:

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

Thanks..

Comments

0

You may not always want to include a module on server-side. For example, when the module includes a library that only works in the browser.

Take a look at the following example:

import dynamic from 'next/dynamic'

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

function Home() {
return (
<div>
  <Header />
  <DynamicComponentWithNoSSR />
  <p>HOME PAGE is here!</p>
</div>
 )
}

export default Home

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.