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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.