0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

React(typescript)で外部scriptを遅延ロードする方法

Last updated at Posted at 2021-01-02

#今回陥った内容の概要

React(typescript)で外部scriptを使用するだけなのだがかなりの時間と調査を要して解決したのでのでナレッジの共有をしたいと思います。
ただベストプラクティスではないと思っており、実装内容も少しレガシーの方法となっております。
今回は外部scriptになるが古いライブラリを使用する場合、React(typescript)ですが、@typeに対応していないものを使用する内容となっております。

#今回の用件

  • 実装はReactでのSPA
  • 外部scriptはbody内に任意の箇所
  • headerにはプロパティを追加する外部scriptなし
  • innerHtmlはサニタイズを考慮して使用不可
  • 外部script内にdocument.writeが使用されている()
  • 外部script内にさらなる外部scriptが使用されている

#試したアプローチ

##1.scriptタグの生成

useEffectで以下のコードを実装

logic.tsx
const script = document.createElement("script");
script.asyc = true;
script.src = "url";

const currentElem = document.getElementById("current");
currentElem?.appendChild(script);

build結果としては

<div id="current">
    <scirpt async src="url"></script>
</div>

っとなってしまいました。

望む結果としては外部scriptの実行結果(document.write)が行われDOM要素を生成して欲しいのでこちらでは望む結果とはなりませんでした。

#解決したアプローチ

postscribeを使用しました。

npm i postscribe

ただこちらのライブラリは@typeが作成されていなさそうなので、

import postscribe from "postscribe";

ではエディタ上ではErrorとなってしまいます。

そのため、ベストプラクティスではないと思いつつ以下のような実装で対応しました。

logic.tsx
// eslint-disable-next-line @typescript-eslint/no-var-requires
const postscribe = require("postscribe");
postscribe(
  "#current",
  "<script src='url'></script>"
);

上記実装でbuildを実行しますと


<div id="current">
    <!-- ここに上記外部scriptのdocument.writeで追加されたDOMが追加 -->
</div>

となり、任意のコンテンツが表示されました。

#まとめ
今回に関してはこのような対応で実現させました。
実現できた時は安堵の方がかなり多かったですが、個人的には満足いく実装が出来なかったです。
自分以外にも似たような内容で困っている方がいれば一度試してみてはいかがでしょうか?
また、他にもっと良い実装があるよって方は残していただければ試してみようかと思います。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?