なにこれ
react-cytoscapeのようなwindowオブジェクトを前提としたライブラリをGatsbyで使おうとすると、gatsby develop
のときは正常動作するにもかかわらず、ビルド時にだけwindow is not defined
エラーがでます。今回はその対処法を備忘録として残しておきます。
原因と対処法
Gatsbyビルド時は、window
やdocument
といったブラウザのグローバルオブジェクトを参照しているとエラーになります。
この場合、それらがundefinedかチェックが必要です。
// (Before) 以下でビルド時にエラーが出る場合は...
const module = require("module")
// (After 1) このようにwindowオブジェクトの存在チェックをすることでエラーを免れます
if (typeof window !== `undefined`) {
const module = require("module")
}
// (After 2) このような形でもOKです
const module = typeof window !== `undefined` ? require("module") : null
またwebpackの設定で、ビルドエラーになるライブラリをダミーに置き換えることで、エラーを免れます。
exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
if (stage === 'build-html') {
actions.setWebpackConfig({
module: {
rules: [
{
test: /react-cytoscapejs/,
use: loaders.null(),
},
],
},
})
}
}
さらに、そのライブラリを使った処理をReactコンポーネントに記述している場合は、componentDidMount
かuseEffect
に移しましょう。そうすることで、その処理がブラウザでのみ実行されるようになるのでビルド時のエラーを免れます。
import CytoscapeComponent from 'react-cytoscapejs'
class PostRelationSection extends React.Component {
/*--中略--*/
componentDidMount() {
const { posts, allImage } = this.props
const nodes = createPostNode({ posts, allImage })
nodes.push(CYTOSCAPE_ZOOM_UP_ELEMENT)
nodes.push(CYTOSCAPE_ZOOM_DOWN_ELEMENT)
const edges = createPostEdges({posts})
const cytoscapeElements = CytoscapeComponent.normalizeElements({ nodes, edges })
this.setState({ cytoscapeElements })
}
/*--中略--*/
}
参考
関連記事
Gatsbyバージョンアップ(v2 to v5)
2023/04/06
Gatsbyビルドチューニング ビルド時間を15分から7分に短縮するためのTips 7選
Gatsby + Netlify + ZapierでRSSリーダーを作る
2019/06/18
Gatsbyにおける外部取得画像へのgatsby-image適用方法
2019/06/02
Gatsbyで2種類のマークダウンファイルの区別する方法
2019/06/02