前提・実現したいこと
Rails6にmo.jsを設定したい。
発生している問題・エラーメッセージ
Uncaught TypeError: Cannot read property 'appendChild' of null
実行した内容
新規アプリを準備し、mo.js公式に沿って下記を実行しました。
yarn add @mojs/core
の実行application.js
にimport mojs from '@mojs/core'
を追加
(application.jsのimportとrequireの違いがよく分かっていないのですが、2.をrequire("@mojs/core"
としてもエラーは変わりませんでした。)
試したこと
キーワードで検索してみるとJSの読み込み順または位置の問題のようですが、Rails6ででどのように設定すればよいのかの記事が見つからず、質問させていただきました。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
ベストアンサー
タイトルとは全く別問題のエラーです。
意外と上手く行っているのでは?
まず下記を元に修正した後にmo.jsが使えるかを試してみてください。
Uncaught TypeError: Cannot read property 'appendChild' of null
JavaScriptはオブジェクト指向言語なのでA.hoge
という風に
ほぼ全てのString型やNumber型、Object型といった値はプロパティやメソッドを所持しています。
しかし例外が2つだけあり、null
とundefined
だけはプロパティ値を所持できません。
しかもアクセスを試みた時点でエラーで落ちます。
Cannot read property 'appendChild' of null
は、
elm.appendChild(elm2)
と書いたが、elmが上手く取得出来ておらずnull値なので怒っています。
原因と対処法の解説
結論:
全てのscriptタグにdefer属性を引っ付けましょう
解説:
scriptタグを見つけたWebブラウザは
その場にHTMLコードを無理やり記述するdocument.writeという非推奨なコードがあるので
レンダリングを放棄してJavaScriptコードの実行を始めます。
それより前にHTML上に記述していた要素はdocument.querySelector()
等で探せますが、
scriptタグより下に記述されていると「そんなものはない!」とnullやundefinedで帰ってくるわけですね。
なのでJavaScriptの実行を遅延させる必要があります。
(探せば色々と出てきます)
今回のdefer属性を全てのscriptタグに付与という対策は最も手軽です。
JavaScriptコードのダウンロードはさっさと行うが、
JavaScriptの実行は全てのHTMLファイル上の要素を全て読み込み終わるまで遅延してくれます。
しかも実行順序はちゃんとscriptタグの上から順番。
なので、大昔はGoogleは閉じbodyタグの直前にscriptタグを宣言しなさいと勧告していましたが、
今はdefer属性を付与しなさいと勧告するようにしています。
参考記事:
<script> タグに async / defer を付けた場合のタイミング - Qiita
Google Maps API のヒント: ページの読み込み時間をスピードアップ - Google Developers
投稿2020/02/20 05:07
編集2020/02/20 06:53総合スコア21203
0
mojs
だけ<body>
内で読み込むようにすれば動作するようです。(非推奨、下により良い対処法を追記しました)
(参考)https://github.com/mojs/mojs/issues/110
js
1// app/javascript/packs/mojs.js 2import '@mojs/core'
erb
1<%# app/views/layouts/application.html.slim %> 2<body> 3 <%= javascript_pack_tag 'mojs', 'data-turbolinks-track': 'reload' %> 4</body>
console
1> mojs 2{revision: "0.288.2", isDebug: true, helpers: Helpers, Shape: ƒ, ShapeSwirl: ƒ, …}
miyabi-sun さんの回答を受けて追記します。
全てのscriptタグにdefer属性を引っ付けましょう
こちらの対処法の方がよさそうです。
js
1// app/javascript/packs/application.js 2import '@mojs/core'
erb
1<%# app/views/layouts/application.html.slim %> 2<head> 3 <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload', defer: true %> 4</head>
console
1> mojs 2{revision: "0.288.2", isDebug: true, helpers: Helpers, Shape: ƒ, ShapeSwirl: ƒ, …}
投稿2020/02/20 04:08
編集2020/02/20 07:18総合スコア2349
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/02/20 07:11
2020/02/20 07:13
2020/02/20 09:34
2020/02/20 09:36
2020/02/21 00:23
2020/02/21 00:25
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
関連した質問
Javascriptの読み込み順をずらしたい。Error:Uncaught TypeError: Cannot read property 'appendChild' of null
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/02/20 06:01
2020/02/20 09:26