Javascriptで動的にファイルを読み込む


#はじめに

ウェブサイトで外部ライブラリを読み込むというのはよくやる行為だが、それが多くなってきたり、外部ライブラリを踏み台に自作ライブラリを作る(＆同じサイト内で使い回す）となると読み込みの管理も大変になってくる。
ので、その辺を自動化する関数を作ってみた。

#headに読み込みリンクを生成する
二重読み込みの防止装置もつけてある。

```javascript:javascript

function insert_link(tagname, obj, raw_url){

	// 差し込む要素の生成
	var target_tag = document.createElement(tagname);
	var keylist = Object.keys(obj);
	var currentkey;
	for(let int = 0; int < keylist.length; int++){
		currentkey = keylist[int];
		target_tag[currentkey] = obj[currentkey];
	}

	// その要素がhead内にすでに存在するかどうかチェックし、存在しない場合のみ読み込みを行う
	var head = document.querySelector('head');
	var headtext = head.innerHTML;
	var processed_url = raw_url.replace(/\//g, '\\/');
	processed_url = processed_url.replace(/\./g, '\\.');
	var regexstr = new RegExp( '=["\']' + processed_url + '["\']', 'g');
	if(!regexstr.test(headtext)){
		head.appendChild(target_tag);
	}
	return target_tag;
}

```

###使用例

```html:html

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="utf-8">
	<title>無題</title>
</head>
<body>

<script type="text/javascript">
(function(){

function insert_link(tagname, obj, raw_url){

	// 差し込む要素の生成
	var target_tag = document.createElement(tagname);
	var keylist = Object.keys(obj);
	var currentkey;
	for(let int = 0; int < keylist.length; int++){
		currentkey = keylist[int];
		target_tag[currentkey] = obj[currentkey];
	}

	// その要素がhead内にすでに存在するかどうかチェックし、存在しない場合のみ読み込みを行う
	var head = document.querySelector('head');
	var headtext = head.innerHTML;
	var processed_url = raw_url.replace(/\//g, '\\/');
	processed_url = processed_url.replace(/\./g, '\\.');
	var regexstr = new RegExp( '=["\']' + processed_url + '["\']', 'g');
	if(!regexstr.test(headtext)){
		head.appendChild(target_tag);
	}
	return target_tag;
}

// 使うときは、キーを属性名、値を属性値としたオブジェクト（下のやつ）に設定を書き込みます
// CSSファイルの場合
var list01 = {
	rel: "stylesheet",
	href: "https://example.com/css/style.css",
}

// Jsファイルの場合
var list02 = {
	type: "text/javascript",
	charset: "UTF-8",
	src: "https://example.com/js/testscript.js",
}


// 引数は左から順にタグ名、設定オブジェクト名、読込先です。
insert_link('link', list01, list01.href);

// 上で挙げた通り、既に読み込まれているときは自動で処理中止してくれます。
insert_link('link', list01, list01.href);


// Jsの場合
insert_link('script', list02, list02.src);

// 上で挙げた通り、既に読み込まれているときは自動で処理中止してくれます。
insert_link('script', list02, list02.src);


})();
</script>
</body>
</html>

```

###実行例

![1581988906989.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416995/c130243b-735f-20fa-ea41-6b9c41d3be00.jpeg)


#読み込みが完了したのを確認してから処理を実行

実は、上のコードだけだとある問題が発生する。
**ライブラリの読み込みが、本命のjavascriptよりも後になってしまう**のだ。
これでは、せっかく読み込んだライブラリを利用したコードを書いてもエラーになってしまう。

これを防ぐため、実際のコードでは以下の文を付け足して使う。

```javascript:javascript

// insert_linkが実行された時点で、ライブラリの読み込み処理は終わっています。
var madedom = insert_link('script', list02, list02.src);

madedom.onload = function(){

	/* ~~ライブラリの読み込み完了後に行いたい処理をここに書く~~ */

}

```

onloadを使うことで、読込みの完了を待つことができるのだ。
多少速度は落ちるが、エラーが出るよりかはマシだろう。


#全体のコード

```html:html

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="utf-8">
	<title>無題</title>
</head>
<body>

<script type="text/javascript">
(function(){

function insert_link(tagname, obj, raw_url){

	// 差し込む要素の生成
	var target_tag = document.createElement(tagname);
	var keylist = Object.keys(obj);
	var currentkey;
	for(let int = 0; int < keylist.length; int++){
		currentkey = keylist[int];
		target_tag[currentkey] = obj[currentkey];
	}

	// その要素がhead内にすでに存在するかどうかチェックし、存在しない場合のみ読み込みを行う
	var head = document.querySelector('head');
	var headtext = head.innerHTML;
	var processed_url = raw_url.replace(/\//g, '\\/');
	processed_url = processed_url.replace(/\./g, '\\.');
	var regexstr = new RegExp( '=["\']' + processed_url + '["\']', 'g');
	if(!regexstr.test(headtext)){
		head.appendChild(target_tag);
	}
	return target_tag;
}

// Jsファイルの場合
var list02 = {
	type: "text/javascript",
	charset: "UTF-8",
	src: "https://example.com/js/testscript.js",
}

// Js
var madedom = insert_link('script', list02, list02.src);

madedom.onload = function(){

	/* ~~ライブラリの読み込み完了後に行いたい処理をここに書く~~ */

}

})();
</script>
</body>
</html>

```

#おわりに

間違いなどありましたら編集リクエストおねがいします。


#参考文献

https://qiita.com/ykob/items/6e4d0b07bed57881a2bd