LoginSignup
8
7

More than 5 years have passed since last update.

Node.jsで作ったライブラリをブラウザ上で使えるようにする

Posted at

この記事を書いたきっかけ

Node.jsとかでライブラリ作りたいなと思いまして
基本はnpmでインストールしてNode.js上で動作するだけでもいいけど
ブラウザ上でscriptタグで読み込むだけでも使えるようにもしたいな

つまり、こういうことをやりたい

index.html
<script src="mylib.js"></script>
<script>
  MyLib.init();
</script>

あれ、でもNode.jsで作ったライブラリって
どうやってブラウザ上で使えるようにするんだろう。
普通にwindow.<プロパティ>にぶち込むだけ?

というのを調べてみたお話。

この記事の結論

現時点ではブラウザ上で動作してるってことをなんらかで判定しつつ
最終的にwindow.<プロパティ>にぶち込むのが安定という気がしました。

const message = "Hello World";

if (typeof window  !== "undefined") {
  window.message = message;
}

あとは現在ECMAScriptにglobalThisというものが試験実装されてるようなので
この先のどこかのタイミングではglobalThisに統一される事になる?という妄想をしています。

普通のJavaScriptとscriptタグ

index.js
const message = "Hello World";
index.html
<script src="index.js"></script>
<script>
  console.log(message);
</script>
console
Hello World

通常のjsはindex.jsで定義されたmessageがそのファイルの外でも使える。

scriptタグにtype=moduleを設定する

scriptタグにtype="module"を指定するとJavaScriptファイルがモジュールとして扱われ
ESModule仕様でimport/exportが使える。(一部ブラウザは非対応)

index.js
const message = "Hello World";
index.html
<script type="module" src="index.js"></script>
<script>
  console.log(message);
</script>
console
Uncaught ReferenceError: message is not defined

結果はmessageが定義されてないとエラーになる。
エラーになる原因は2つ。

1. モジュール内の変数はファイル内スコープである

モジュールの外で使うにはそもそもexportしなきゃいけないし
使うときはimportしてやらないとだめ。

2. index.jsが読み込まれる前にconsole.logが実行されちゃう

そもそもconsole.logのタイミングでまだindex.jsがロードされてない。
(モジュールだと非同期読み込みになるから)

HTML上で変数(message)を使えるようにする

index.jsの変数をどうやってhtml側で利用するか

実験 その1

exportしてimportする

index.js
const message = "Hello World";
export default message;
index.html
<script type="module">
  import message from './index.js'; // ./とか.jsをちゃんと書かないと怒られた
  console.log(message);
</script>
console
Hello World

type="module"を指定し、Scriptをmoduleとして扱う事でimportすることができる。
(IE11が相変わらず対応してないが)

実験 その2

window.messageに突っ込む

index.js
const message = "Hello World";
window.message = message;
index.html
<script type="module" src="index.js"></script>
<script>
  // 上記のスクリプトは非同期で読み込まれるので、ロード後に処理する
  window.onload = function() {
    console.log(message)
  }
</script>
console
Hello World

これは昔ながらの方法なのでtype="module"だろうと
昔ながらのJavaScriptだろうと
どっちでもいけるパターン。

type="module"ってどうなの

色々とあるけど、type="module"を実用化するにはあともう少しという気がします。
(もうIE11もなくなるっぽいし、古いブラウザやニッチなブラウザを捨てちゃえばいいんだよもうって思う)
最終的にこれに統一される日は早くきて欲しい。

Node.jsのモジュールがcommonjs(亜種)仕様だったり
Node.jsでも拡張子を.mjsにすればESModule構文使えるけど、.mjsで作るのも微妙だったり

結局はwebpackやらparcelやらxxxxxfyなど何らかのバンドラーでバンドルしちゃうのが安定かなぁ。
そしてバンドルするなら`type="module"も直近ではいらないという結論に落ち着く

まとめ

諸々の状況を鑑みると、Node.jsで作ったクラスなり関数なりを
HTML上で使えるようにするには

必要なものをwindow.<プロパティ>にぶち込んで公開する。
という方法でいいという結論に落ち着きました。

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