LoginSignup
7
4

More than 3 years have passed since last update.

[Gatsby]SSR 部分で window オブジェクトを参照するとビルドできない問題(鬼滅風)

Last updated at Posted at 2020-06-16

SSR 部分で window を参照しているとビルドに失敗する

Gatsby はビルド時にページを生成するのですが、ページ内に window.innerwidthとか参照しているとエラーで落ちます。

"window" is not available during server side rendering.

See our docs page for more info on this error: https://gatsby.dev/debug-html



  ReferenceError: window is not defined

image.png

node でページ生成してるのだから window オブジェクトがないことは当然だ。

image.png

window の参照なんかでビルド失敗してんじゃねーよ!!あああ💢

怒っても 公式みても github みても解決しないので、この超めんどくさい問題の対応方法を考えてみました。

一回 state にいれるようにする

class Index extends Component {
  constructor(props) {
    super(props)
    this.state = {
      width: 0, // or your default width here
    }
  }
  componentDidMount() {
    this.handleWindowSizeChange() // Set width
    window.addEventListener('resize', this.handleWindowSizeChange)
  }

  componentWillMount() {
    // Don’t use this as the API is deprecated
  }

  // make sure to remove the listener
  // when the component is not mounted anymore
  componentWillUnmount() {
    window.removeEventListener('resize', this.handleWindowSizeChange)
  }

  handleWindowSizeChange = () => {
    this.setState({ width: window.innerWidth })
  }

  // rest of code
}

issue で議論されてました。
state にいれるの手間だし、おそくなるのでないなーって感じです。

SSR のときはそのコンポーネントをマウントしない。

MUI に NoSSR が用意されており、こちらを使うと、
SSR のときはそのコンポーネントをマウントしないとすることができます。

MUI 以外にも似たような仕組みがあると思います。

import { NoSsr, List, ListItem, Tooltip } from "@material-ui/core";

略
         <NoSsr>
          <Tooltip
            id="instagram-twitter"
            title="Follow us on twitter"
            placement={window && window.innerWidth > 959 ? "top" : "left"}
            classes={{ tooltip: classes.tooltip }}
          >
            <Button
              href="https://twitter.com/CreativeTim?ref=creativetim"
              target="_blank"
              color="transparent"
              className={classes.navLink}
            >
              <i className={classes.socialIcons + " fab fa-twitter"} />
            </Button>
          </Tooltip>
         </NoSsr>

これは window 以外の問題も解決できるのでこれはこれでありです。

そもそもコード書き換えない、Polyfill 的なもの

window の解決ぐらいもっと楽にできないの?!しっかりしてよ〜たんじろおお〜!

image.png

ありました。もっとベターなアプローチが。

こちらをimportすると window の参照で落ちないようようになります。
addEventListener も動作します。

import { window } from 'ssr-window';


      <ListItem className={classes.listItem}>
        <Tooltip
          id="instagram-tooltip"
          title="Follow us on instagram"
          placement={window && window.innerWidth > 959 ? "top" : "left"}
          classes={{ tooltip: classes.tooltip }}
        >
          <Button
            color="transparent"
            href="https://www.instagram.com/CreativeTimOfficial?ref=creativetim"
            target="_blank"
            className={classes.navLink}
          >
            <i className={classes.socialIcons + " fab fa-instagram"} />
          </Button>
        </Tooltip>

とかかいても落ちません。

最近ぜんいつのキャラがおもしすぎて

SSRのフレームワークの中でやってくれないの?!だめだよ!もっと楽させてよ!

とか思っちゃいました。

7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4