@import
CSSに似たJavaScriptで、JavaScriptファイルを別のJavaScriptファイル内に含めることができるものはありますか?
script
タグを使用して、インポートされたファイルを、それを必要とする他のファイルの前に宣言してみませんか?
@import
CSSに似たJavaScriptで、JavaScriptファイルを別のJavaScriptファイル内に含めることができるものはありますか?
script
タグを使用して、インポートされたファイルを、それを必要とする他のファイルの前に宣言してみませんか?
回答:
古いバージョンのJavaScriptにはインポート、インクルード、または要求がなかったため、この問題に対するさまざまなアプローチが開発されてきました。
しかし、2015年(ES6)以降、JavaScriptには、Node.jsにモジュールをインポートするES6モジュール標準があり、ほとんどの最新のブラウザーでもサポートされています。。
古いブラウザとの互換性のために、WebpackやRollupなどのビルドツールやBabelなどのトランスパイレーションツールを使用できます。
ECMAScript(ES6)モジュールは、v8.5以降、フラグあり、および少なくともNode.js v13.8.0以降、フラグなしでNode.jsでサポートされています--experimental-modules
。"ESM"(vs. Node.jsの以前のCommonJSスタイルのモジュールシステム["CJS"])を有効にするには、で使用"type": "module"
するpackage.json
か、ファイルに拡張子を付け.mjs
ます。(同様に、.cjs
デフォルトがESMの場合、Node.jsの以前のCJSモジュールで作成されたモジュールに名前を付けることができます。)
使用package.json
:
{
"type": "module"
}
次にmodule.js
:
export function hello() {
return "Hello";
}
次にmain.js
:
import { hello } from './module.js';
let val = hello(); // val is "Hello";
を使用すると.mjs
、次のようになりますmodule.mjs
。
export function hello() {
return "Hello";
}
次にmain.mjs
:
import { hello } from './module.mjs';
let val = hello(); // val is "Hello";
ブラウザは、 Safari 10.1、Chrome 61、Firefox 60、およびEdge 16 以降、 ECMAScriptモジュールの直接ロードをサポートしています(Webpackなどのツールは不要)。caniuseで現在のサポートを確認してください。Node.jsの.mjs
拡張機能を使用する必要はありません。ブラウザはモジュール/スクリプトのファイル拡張子を完全に無視します。
<script type="module">
import { hello } from './hello.mjs'; // Or it could be simply `hello.js`
hello('world');
</script>
// hello.mjs -- or it could be simply `hello.js`
export function hello(text) {
const div = document.createElement('div');
div.textContent = `Hello ${text}`;
document.body.appendChild(div);
}
続きを読む https://jakearchibald.com/2017/es-modules-in-browsers/をご覧ください
動的インポートにより、スクリプトは必要に応じて他のスクリプトをロードできます。
<script type="module">
import('hello.mjs').then(module => {
module.hello('world');
});
</script>
続きを読む https://developers.google.com/web/updates/2017/11/dynamic-importをご覧ください。
Node.jsでまだ広く使用されている古いCJSモジュールスタイルはmodule.exports
/require
システムです。
// mymodule.js
module.exports = {
hello: function() {
return "Hello";
}
}
// server.js
const myModule = require('./mymodule');
let val = myModule.hello(); // val is "Hello"
JavaScriptが、前処理を必要としないブラウザーに外部JavaScriptコンテンツを組み込む他の方法があります。
AJAX呼び出しで追加のスクリプトをロードし、それを使用eval
してそれを実行できます。これは最も簡単な方法ですが、JavaScriptサンドボックスセキュリティモデルのため、ドメインに限定されます。を使用eval
すると、バグ、ハッキング、セキュリティの問題への扉も開きます。
ダイナミックインポートと同様にfetch
、Fetch Injectライブラリを使用してスクリプトの依存関係の実行順序を制御するpromiseを使用して、1つまたは複数のスクリプトを呼び出しでロードできます。
fetchInject([
'https://cdn.jsdelivr.net/momentjs/2.17.1/moment.min.js'
]).then(() => {
console.log(`Finish in less than ${moment().endOf('year').fromNow(true)}`)
})
$.getScript("my_lovely_script.js", function() {
alert("Script loaded but not necessarily executed.");
});
スクリプトURLを含むスクリプトタグをHTMLに追加できます。jQueryのオーバーヘッドを回避するために、これは理想的なソリューションです。
スクリプトは別のサーバーに置くこともできます。さらに、ブラウザはコードを評価します。<script>
タグは、Webページのいずれかに注入することができる<head>
、あるいは単に閉じる前に挿入</body>
タグ。
これがどのように機能するかの例を次に示します。
function dynamicallyLoadScript(url) {
var script = document.createElement("script"); // create a script DOM node
script.src = url; // set its src to the provided URL
document.head.appendChild(script); // add it to the end of the head section of the page (could change 'head' to 'body' to add it to the end of the body section instead)
}
この関数は<script>
、ページのヘッドセクションの最後に新しいタグを追加します。ここで、src
属性は、最初のパラメーターとして関数に指定されたURLに設定されます。
これらのソリューションは両方とも、「JavaScriptマッドネス:動的スクリプトロード」で説明および説明されています。
今、あなたが知っておくべき大きな問題があります。これは、コードをリモートでロードすることを意味します。最新のWebブラウザーはすべてを非同期でロードしてパフォーマンスを向上させるため、ファイルをロードして現在のスクリプトを実行し続けます。(これは、jQueryメソッドと手動の動的スクリプトロードメソッドの両方に適用されます。)
つまり、これらのトリックを直接使用する場合、新しくロードされたコードは、ロードするように要求した後、次の行を使用できなくなります。
次に例を示しmy_lovely_script.js
ますMySuperObject
。
var js = document.createElement("script");
js.type = "text/javascript";
js.src = jsFilePath;
document.body.appendChild(js);
var s = new MySuperObject();
Error : MySuperObject is undefined
次に、ページヒットをリロードします F5。そしてそれはうまくいきます!混乱しています...
それでそれについて何をすべきか?
まあ、あなたが私があなたに与えたリンクで著者が提案するハックを使うことができます。要約すると、急いでいる人のために、彼はスクリプトが読み込まれたときにイベントを使用してコールバック関数を実行します。したがって、リモートライブラリを使用するすべてのコードをコールバック関数に配置できます。例えば:
function loadScript(url, callback)
{
// Adding the script tag to the head as suggested before
var head = document.head;
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
// Then bind the event to the callback function.
// There are several events for cross browser compatibility.
script.onreadystatechange = callback;
script.onload = callback;
// Fire the loading
head.appendChild(script);
}
次に、スクリプトがラムダ関数に読み込まれた後で、使用するコードを記述します。
var myPrettyCode = function() {
// Here, do whatever you want
};
次に、すべてを実行します。
loadScript("my_lovely_script.js", myPrettyCode);
DOMが読み込まれた後、またはその前に、ブラウザと行を含めたかどうかによって、スクリプトが実行される場合があることに注意してくださいscript.async = false;
。これを説明する一般的なJavaScriptの読み込みに関する優れた記事があります。
この回答の冒頭で述べたように、多くの開発者はプロジェクトでParcel、Webpack、Babelなどのビルド/トランスパイレーションツールを使用して、今後のJavaScript構文の使用、古いブラウザーの下位互換性の提供、ファイルの結合、縮小、コード分割などを実行します
onreadystatechange
イベントとreadyState
プロパティ)の変更が必要です。また、動的なスクリプトの読み込みは、broswerのプリロードスキャナーの恩恵を受けません。このHTML5Rocksの記事をお勧めします:html5rocks.com/en/tutorials/speed/script-loading
誰かがより高度なものを探している場合は、RequireJSを試してください。依存関係の管理、同時実行性の向上、重複の回避(スクリプトの複数回の取得)などの追加のメリットが得られます。
JavaScriptファイルを「モジュール」で記述し、他のスクリプトで依存関係として参照できます。または、簡単な「このスクリプトを取得する」ソリューションとしてRequireJSを使用できます。
例:
依存関係をモジュールとして定義します。
some-dependency.js
define(['lib/dependency1', 'lib/dependency2'], function (d1, d2) {
//Your actual script goes here.
//The dependent scripts will be fetched if necessary.
return libraryObject; //For example, jQuery object
});
implementation.jsは、some-dependency.jsに依存する「メイン」のJavaScriptファイルです
require(['some-dependency'], function(dependency) {
//Your script goes here
//some-dependency.js is fetched.
//Then your script is executed
});
GitHub README からの抜粋:
RequireJSは、プレーンなJavaScriptファイルとより多くの定義されたモジュールをロードします。Webワーカーを含むブラウザー内での使用に最適化されていますが、RhinoやNodeなどの他のJavaScript環境で使用することもできます。非同期モジュールAPIを実装します。
RequireJSは、プレーンスクリプトタグを使用してモジュール/ファイルをロードするため、簡単にデバッグできるはずです。既存のJavaScriptファイルをロードするためだけに使用できるため、に使用できるため、JavaScriptファイルを書き直すことなく既存のプロジェクトに追加できます。
...
実際には、JavaScriptファイルを非同期ではなく読み込む方法があるため、新しく読み込んだファイルに含まれている関数を、読み込んだ直後に使用でき、すべてのブラウザーで動作すると思います。
あなたはあなたのページjQuery.append()
の<head>
要素で使用する必要があります、つまり:
$("head").append('<script type="text/javascript" src="' + script + '"></script>');
ただし、この方法には問題もあります。インポートされたJavaScriptファイルでエラーが発生すると、Firebug(およびFirefox Error ConsoleとChrome Developer Toolsも同様)がその場所を誤って報告します。これは、Firebugを使用して追跡する場合は大きな問題ですJavaScriptはかなりダウンします(私はそうします)。Firebugは、何らかの理由で新しくロードされたファイルを知らないだけなので、そのファイルでエラーが発生すると、メインのHTMLで発生したと報告されますファイルれ、エラーの実際の理由を見つけるのが困難になります。
しかし、それがあなたにとって問題でなければ、この方法はうまくいくはずです。
私は実際に呼ばれるjQueryプラグインを書いています このメソッドを使用する$ .import_js()。
(function($)
{
/*
* $.import_js() helper (for JavaScript importing within JavaScript code).
*/
var import_js_imported = [];
$.extend(true,
{
import_js : function(script)
{
var found = false;
for (var i = 0; i < import_js_imported.length; i++)
if (import_js_imported[i] == script) {
found = true;
break;
}
if (found == false) {
$("head").append('<script type="text/javascript" src="' + script + '"></script>');
import_js_imported.push(script);
}
}
});
})(jQuery);
したがって、JavaScriptをインポートするために必要なことは次のとおりです。
$.import_js('/path_to_project/scripts/somefunctions.js');
私はこれについて簡単なテストも行いました 例。
main.js
メインHTMLにファイルが含まれ、次にのスクリプトがをmain.js
使用$.import_js()
してincluded.js
、この関数を定義すると呼ばれる追加ファイルをインポートします。
function hello()
{
alert("Hello world!");
}
含めた直後 included.js
、hello()
関数が呼び出され、およびアラートを取得しています。
(この回答は、e-satisのコメントに対するものです)。
jQuery.getScript
と、プラグインの作成について心配する必要がありません...
"
、コードは壊れます
もう1つの方法は、私の意見ではよりクリーンで、<script>
タグを使用する代わりに同期Ajaxリクエストを作成することです。これは、Node.jsがインクルードを処理する方法でもあります。
jQueryを使用した例を次に示します。
function require(script) {
$.ajax({
url: script,
dataType: "script",
async: false, // <-- This is the key
success: function () {
// all good...
},
error: function () {
throw new Error("Could not load script " + script);
}
});
}
通常はインクルードを使用するので、コードで使用できます。
require("/scripts/subscript.js");
そして、次の行で必要なスクリプトから関数を呼び出すことができます:
subscript.doSomethingCool();
async: false
おそらく非推奨であると述べている以前のコメントを裏付けていないようです。そうではない!あなたの引用が言うように、jqXHR関連のものだけです。
良い知らせがあります。まもなく、JavaScriptコードを簡単にロードできるようになります。これは、JavaScriptコードのモジュールをインポートする標準的な方法となり、コアJavaScript自体の一部になります。
ファイルからimport cond from 'cond.js';
名前が付けられたマクロをロードするために書き込むだけcond
ですcond.js
。
したがって、JavaScriptフレームワークに依存する必要も、Ajax呼び出しを明示的に行う必要もありません。
参照する:
JavaScriptタグを動的に生成して、他のJavaScriptコード内からHTMLドキュメントに追加することが可能です。これにより、ターゲットのJavaScriptファイルが読み込まれます。
function includeJs(jsFilePath) {
var js = document.createElement("script");
js.type = "text/javascript";
js.src = jsFilePath;
document.body.appendChild(js);
}
includeJs("/path/to/some/file.js");
js.onload = callback;
ステートメント import
はECMAScript 6にあります。
構文
import name from "module-name";
import { member } from "module-name";
import { member as alias } from "module-name";
import { member1 , member2 } from "module-name";
import { member1 , member2 as alias2 , [...] } from "module-name";
import name , { member [ , [...] ] } from "module-name";
import "module-name" as name;
このページで見つけたこの関数を使用できますか?JavaScriptファイルをJavaScriptファイルに含めるにはどうすればよいですか?:
function include(filename)
{
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.src = filename;
script.type = 'text/javascript';
head.appendChild(script)
}
script.onload = callback;
var
、変数はグローバルになりますか?
ここにjQueryなしの同期バージョンがあります:
function myRequire( url ) {
var ajax = new XMLHttpRequest();
ajax.open( 'GET', url, false ); // <-- the 'false' makes it synchronous
ajax.onreadystatechange = function () {
var script = ajax.response || ajax.responseText;
if (ajax.readyState === 4) {
switch( ajax.status) {
case 200:
eval.apply( window, [script] );
console.log("script loaded: ", url);
break;
default:
console.log("ERROR: script not loaded: ", url);
}
}
};
ajax.send(null);
}
この動作するクロスドメインを取得するには、サーバーがallow-origin
応答にヘッダーを設定する必要があることに注意してください。
http://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStuff/userjs/aagmfunctions.js
)
<script>
タグを介してのみスクリプトをロードできますXMLHttpRequest
。
const XMLHttpRequest = Components.Constructor("@mozilla.org/xmlextras/xmlhttprequest;1");
私はこのJavaScriptコードを記述しました(DOM操作にPrototypeを使用)。
var require = (function() {
var _required = {};
return (function(url, callback) {
if (typeof url == 'object') {
// We've (hopefully) got an array: time to chain!
if (url.length > 1) {
// Load the nth file as soon as everything up to the
// n-1th one is done.
require(url.slice(0, url.length - 1), function() {
require(url[url.length - 1], callback);
});
} else if (url.length == 1) {
require(url[0], callback);
}
return;
}
if (typeof _required[url] == 'undefined') {
// Haven't loaded this URL yet; gogogo!
_required[url] = [];
var script = new Element('script', {
src: url,
type: 'text/javascript'
});
script.observe('load', function() {
console.log("script " + url + " loaded.");
_required[url].each(function(cb) {
cb.call(); // TODO: does this execute in the right context?
});
_required[url] = true;
});
$$('head')[0].insert(script);
} else if (typeof _required[url] == 'boolean') {
// We already loaded the thing, so go ahead.
if (callback) {
callback.call();
}
return;
}
if (callback) {
_required[url].push(callback);
}
});
})();
使用法:
<script src="prototype.js"></script>
<script src="require.js"></script>
<script>
require(['foo.js','bar.js'], function () {
/* Use foo.js and bar.js here */
});
</script>
要旨:http : //gist.github.com/284442。
Facebookがユビキタスの[いいね!]ボタンに対してどのように行うかを一般化したバージョンを次に示します。
<script>
var firstScript = document.getElementsByTagName('script')[0],
js = document.createElement('script');
js.src = 'https://cdnjs.cloudflare.com/ajax/libs/Snowstorm/20131208/snowstorm-min.js';
js.onload = function () {
// do stuff with your dynamically loaded script
snowStorm.snowColor = '#99ccff';
};
firstScript.parentNode.insertBefore(js, firstScript);
</script>
それがFacebookで機能する場合、それはあなたのために機能します。
またはのscript
代わりに最初の要素を探す理由は、一部のブラウザでは見つからない場合に要素を作成しないためですが、要素があることが保証されています-この要素。詳細については、http://www.jspatterns.com/the-ridiculous-case-of-adding-a-script-element/をご覧ください。head
body
script
純粋なJavaScriptを使用する場合は、を使用できますdocument.write
。
document.write('<script src="myscript.js" type="text/javascript"></script>');
jQueryライブラリを使用する場合は、この$.getScript
メソッドを使用できます。
$.getScript("another_script.js");
PHPを使用してスクリプトをアセンブルすることもできます。
ファイルmain.js.php
:
<?php
header('Content-type:text/javascript; charset=utf-8');
include_once("foo.js.php");
include_once("bar.js.php");
?>
// Main JavaScript code goes here
ここに示されているソリューションのほとんどは、動的なロードを意味しています。代わりに、依存するすべてのファイルを1つの出力ファイルにアセンブルするコンパイラを探していました。Less / SassプリプロセッサがCSS @import
at-ruleを処理するのと同じです。私はこの種のまともなものを見つけられなかったので、問題を解決する簡単なツールを書きました。
したがって、ここにコンパイラhttps://github.com/dsheiko/jsicがあります。これは$import("file-path")
、要求されたファイルコンテンツに安全に置き換えられます。対応するGruntプラグインは、https://github.com/dsheiko/grunt-jsicです。
jQueryマスターブランチでは、アトミックソースファイルを単にで始まり、intro.js
で終わる単一のファイルに連結しouttro.js
ます。ソースコードの設計に柔軟性がないため、これは私には適していません。jsicでどのように機能するかを確認してください。
src / main.js
var foo = $import("./Form/Input/Tel");
src / Form / Input / Tel.js
function() {
return {
prop: "",
method: function(){}
}
}
これでコンパイラを実行できます:
node jsic.js src/main.js build/mail.js
結合されたファイルを取得します
build / main.js
var foo = function() {
return {
prop: "",
method: function(){}
}
};
JavaScriptファイルをロードする意図が、インポート/インクルードされたファイルの関数を使用している場合場合は、グローバルオブジェクトを定義し、関数をオブジェクトアイテムとして設定することもできます。例えば:
A = {};
A.func1 = function() {
console.log("func1");
}
A.func2 = function() {
console.log("func2");
}
A.func1();
A.func2();
HTMLファイルにスクリプトを含める場合は注意が必要です。順序は次のようになります。
<head>
<script type="text/javascript" src="global.js"></script>
<script type="text/javascript" src="file1.js"></script>
<script type="text/javascript" src="file2.js"></script>
<script type="text/javascript" src="main.js"></script>
</head>
これは行う必要があります:
xhr = new XMLHttpRequest();
xhr.open("GET", "/soap/ajax/11.0/connection.js", false);
xhr.send();
eval(xhr.responseText);
eval
が問題です。Crockfordから、「eval
悪です。このeval
関数はJavaScriptの最も誤用されている機能です。回避してください。eval
エイリアスがあります。Function
コンストラクタを使用しないでください。文字列をsetTimeout
やに渡さないでくださいsetInterval
。」彼の「JavaScript:The Good Parts」を読んでいない場合は、今すぐ出かけましょう。あなたはしますそれを後悔していません。
http://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStuff/userjs/aagmfunctions.js
)
または、実行時に含めるのではなく、スクリプトを使用してアップロード前に連結します。
私はスプロケットを使用しています(他にあるかどうかはわかりません)。JavaScriptコードを個別のファイルで作成し、Sprocketsエンジンで処理されるコメントをインクルードとして含めます。開発の場合、ファイルを順番にインクルードし、本番の場合はマージすることができます...
以下も参照してください。
単純な問題がありましたが、この質問への回答に困惑しました。
あるJavaScriptファイル(myvariables.js)で定義された変数(myVar1)を別のJavaScriptファイル(main.js)で使用する必要がありました。
このために私は以下のようにしました:
JavaScriptコードをHTMLファイルに正しい順序でロードします。最初にmyvariables.js、次にmain.jsです。
<html>
<body onload="bodyReady();" >
<script src="myvariables.js" > </script>
<script src="main.js" > </script>
<!-- Some other code -->
</body>
</html>
ファイル:myvariables.js
var myVar1 = "I am variable from myvariables.js";
ファイル:main.js
// ...
function bodyReady() {
// ...
alert (myVar1); // This shows "I am variable from myvariables.js", which I needed
// ...
}
// ...
ご覧のとおり、あるJavaScriptファイルの変数を別のJavaScriptファイルで使用していましたが、別のJavaScriptファイルに含める必要はありませんでした。最初のJavaScriptファイルが2番目のJavaScriptファイルの前に読み込まれ、最初のJavaScriptファイルの変数が2番目のJavaScriptファイルで自動的にアクセスできることを確認する必要があるだけです。
これは私の日を救った。これがお役に立てば幸いです。
import
。あるjsファイルから別のjsファイルにデータを取得するには、HTMLファイルが必要です。
<script>
タグが1つだけになると便利です。これは組織化に役立ちます。この答えは単に質問が求めていたものではなく、この文脈では理想的ではありません。
Webワーカーを使用していて、ワーカーのスコープに追加のスクリプトを含めたい場合、head
タグへのスクリプトの追加などについて提供されている他の回答は機能しません。
幸い、Webワーカーには独自のimportScripts
機能があります。これはWebワーカーのスコープ内のグローバル関数であり、仕様の一部であるため、ブラウザー自体にネイティブです。
または、質問に対する2番目に投票数の多い回答がハイライトされているため、RequireJSはWebワーカー内にスクリプトを含めることも処理できます(importScripts
それ自体を呼び出す可能性がありますが、他のいくつかの便利な機能があります)。
スクリプトが既にロードされているかどうかを確認する最新の言語では、次のようになります。
function loadJs(url){
return new Promise( (resolve, reject) => {
if (document.querySelector(`head > script[src="${src}"]`) !== null) return resolve()
const script = document.createElement("script")
script.src = url
script.onload = resolve
script.onerror = reject
document.head.appendChild(script)
});
}
使用法(非同期/待機):
try { await loadJs("https://.../script.js") }
catch(error) {console.log(error)}
または
await loadJs("https://.../script.js").catch(err => {})
使用法(約束):
loadJs("https://.../script.js").then(res => {}).catch(err => {})
var pi = 3.14
。loadJS()関数を呼び出すloadJs("pi.js").then(function(){ console.log(pi); });
@import
CSSのようなJavaScriptインポートを実現するための構文は、特殊な.mix
ファイルタイプを介してMixtureなどのツールを使用して可能です(ここを参照)。私は知りませんが、アプリケーションは前述の方法の1つを内部的に使用するだけだと思います。
.mix
ファイルに関するMixtureドキュメントから:
ミックスファイルは、単純に.jsまたは.cssファイルで、.mixが付いています。ファイル名。ミックスファイルは、通常のスタイルまたはスクリプトファイルの機能を拡張するだけで、インポートおよび結合を可能にします。
.mix
複数の.js
ファイルを1つに結合するサンプルファイルを次に示します。
// scripts-global.mix.js
// Plugins - Global
@import "global-plugins/headroom.js";
@import "global-plugins/retina-1.1.0.js";
@import "global-plugins/isotope.js";
@import "global-plugins/jquery.fitvids.js";
Mixtureはこれをscripts-global.js
縮小バージョン(scripts-global.min.js
)として出力します。
注:フロントエンド開発ツールとして使用する以外は、私はMixtureとは一切関係ありません。私は見たときにこの質問に出くわしました.mix
は、(Mixtureボイラープレートの1つにある)JavaScriptファイルが動作て、少し混乱していました(「これは可能ですか?」と私は思いました)。それから、それはアプリケーション固有のファイルタイプであることに気付きました(やや残念、同意した)。それにもかかわらず、知識は他の人に役立つかもしれないと考えました。
更新:Mixtureは無料です(オフライン)。
更新:Mixtureは廃止されました。古い混合リリースはまだ利用可能です
var js = document.createElement("script");
js.type = "text/javascript";
js.src = jsFilePath;
document.body.appendChild(js);
body
ます。また、回答の説明にも役立ちます。
私の通常の方法は:
var require = function (src, cb) {
cb = cb || function () {};
var newScriptTag = document.createElement('script'),
firstScriptTag = document.getElementsByTagName('script')[0];
newScriptTag.src = src;
newScriptTag.async = true;
newScriptTag.onload = newScriptTag.onreadystatechange = function () {
(!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') && (cb());
};
firstScriptTag.parentNode.insertBefore(newScriptTag, firstScriptTag);
}
それはうまく機能し、ページの再読み込みを使用しません。私はAJAXメソッド(他の答えの1つ)を試しましたが、私にはうまく機能しないようです。
好奇心の強い人のためにコードがどのように機能するかを次に説明します。基本的に、URLの(最初のタグの後に)新しいスクリプトタグを作成します。残りのコードをブロックしないように非同期モードに設定しますが、readyState(ロードされるコンテンツの状態)が 'loaded'に変化するとコールバックを呼び出します。
これらの答えは素晴らしいですが、スクリプトのロードが存在して以来存在してきた簡単な「解決策」があり、ほとんどの人のユースケースの99.999%をカバーします。必要なスクリプトの前に、必要なスクリプトを含めてください。ほとんどのプロジェクトでは、必要なスクリプトとその順序を決定するのに時間がかかりません。
<!DOCTYPE HTML>
<html>
<head>
<script src="script1.js"></script>
<script src="script2.js"></script>
</head>
<body></body>
</html>
script2がscript1を必要とする場合、これは実際にこのようなことをする最も簡単な方法です。ほぼすべてのケースに当てはまる最も明白で単純な答えであるため、誰もこれを取り上げていないことに非常に驚いています。
JavaScriptでモジュールスクリプトをインポート/インクルードする作業を自動化する簡単なモジュールを書きました。コードの詳細な説明については、ブログ投稿JavaScript require / import / includeモジュールを参照してください。
// ----- USAGE -----
require('ivar.util.string');
require('ivar.net.*');
require('ivar/util/array.js');
require('http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js');
ready(function(){
//Do something when required scripts are loaded
});
//--------------------
var _rmod = _rmod || {}; //Require module namespace
_rmod.LOADED = false;
_rmod.on_ready_fn_stack = [];
_rmod.libpath = '';
_rmod.imported = {};
_rmod.loading = {
scripts: {},
length: 0
};
_rmod.findScriptPath = function(script_name) {
var script_elems = document.getElementsByTagName('script');
for (var i = 0; i < script_elems.length; i++) {
if (script_elems[i].src.endsWith(script_name)) {
var href = window.location.href;
href = href.substring(0, href.lastIndexOf('/'));
var url = script_elems[i].src.substring(0, script_elems[i].length - script_name.length);
return url.substring(href.length+1, url.length);
}
}
return '';
};
_rmod.libpath = _rmod.findScriptPath('script.js'); //Path of your main script used to mark
//the root directory of your library, any library.
_rmod.injectScript = function(script_name, uri, callback, prepare) {
if(!prepare)
prepare(script_name, uri);
var script_elem = document.createElement('script');
script_elem.type = 'text/javascript';
script_elem.title = script_name;
script_elem.src = uri;
script_elem.async = true;
script_elem.defer = false;
if(!callback)
script_elem.onload = function() {
callback(script_name, uri);
};
document.getElementsByTagName('head')[0].appendChild(script_elem);
};
_rmod.requirePrepare = function(script_name, uri) {
_rmod.loading.scripts[script_name] = uri;
_rmod.loading.length++;
};
_rmod.requireCallback = function(script_name, uri) {
_rmod.loading.length--;
delete _rmod.loading.scripts[script_name];
_rmod.imported[script_name] = uri;
if(_rmod.loading.length == 0)
_rmod.onReady();
};
_rmod.onReady = function() {
if (!_rmod.LOADED) {
for (var i = 0; i < _rmod.on_ready_fn_stack.length; i++){
_rmod.on_ready_fn_stack[i]();
});
_rmod.LOADED = true;
}
};
_.rmod = namespaceToUri = function(script_name, url) {
var np = script_name.split('.');
if (np.getLast() === '*') {
np.pop();
np.push('_all');
}
if(!url)
url = '';
script_name = np.join('.');
return url + np.join('/')+'.js';
};
//You can rename based on your liking. I chose require, but it
//can be called include or anything else that is easy for you
//to remember or write, except "import", because it is reserved
//for future use.
var require = function(script_name) {
var uri = '';
if (script_name.indexOf('/') > -1) {
uri = script_name;
var lastSlash = uri.lastIndexOf('/');
script_name = uri.substring(lastSlash+1, uri.length);
}
else {
uri = _rmod.namespaceToUri(script_name, ivar._private.libpath);
}
if (!_rmod.loading.scripts.hasOwnProperty(script_name)
&& !_rmod.imported.hasOwnProperty(script_name)) {
_rmod.injectScript(script_name, uri,
_rmod.requireCallback,
_rmod.requirePrepare);
}
};
var ready = function(fn) {
_rmod.on_ready_fn_stack.push(fn);
};
このスクリプトは、JavaScriptファイルを他の<script>
タグの先頭に追加します。
(function () {
var li = document.createElement('script');
li.type = 'text/javascript';
li.src= "http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js";
li.async=true;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(li, s);
})();
この質問には多くの潜在的な答えがあります。私の答えは明らかにそれらの数に基づいています。これは私がすべての答えを読んだ後に結局得たものです。
$.getScript
ロードが完了したときにコールバックを必要とする他のソリューションの問題は、それを使用して互いに依存している複数のファイルがある場合、すべてのスクリプトがいつロードされたかを知る方法がないことです(それらがネストされると)。複数のファイルで)。
file3.js
var f3obj = "file3";
// Define other stuff
file2.js:
var f2obj = "file2";
$.getScript("file3.js", function(){
alert(f3obj);
// Use anything defined in file3.
});
file1.js:
$.getScript("file2.js", function(){
alert(f3obj); //This will probably fail because file3 is only guaranteed to have loaded inside the callback in file2.
alert(f2obj);
// Use anything defined in the loaded script...
});
Ajaxを同期して実行するように指定したり、XMLHttpRequestを使用したりできると言ったのはあなたの言うとおりです。が、現在の傾向は同期リクエストを廃止する傾向にあるため、現在または将来、完全なブラウザーサポートが得られない可能性があります。
を使用$.when
して遅延オブジェクトの配列をチェックすることもできますが、これはすべてのファイルでこれを$.when
実行しており、コールバックが実行されたときではなくfile2 が実行されるとすぐにfile2がロードされたと見なされるため、file1はfile3がロードされる前に実行を継続します。これにはまだ同じ問題があります。
前進ではなく後退することにしました。ありがとうdocument.writeln
。私はそれがタブーであることを知っていますが、それが正しく使用されている限り、これはうまく機能します。簡単にデバッグでき、DOMに正しく表示され、依存関係が正しく読み込まれる順序を確認できるコードが作成されます。
もちろん$( "body")。append()を使用できますが、その後は正しくデバッグできなくなります。
注:これは、ページの読み込み中にのみ使用する必要があります。そうしないと、空白の画面が表示されます。つまり、常にdocument.readyの前/外に配置します。ページがクリックイベントなどで読み込まれた後、これを使用したテストはしていませんが、失敗することはほぼ間違いありません。
私はjQueryを拡張するアイデアが好きでしたが、明らかにそうする必要はありません。
を呼び出す前にdocument.writeln
、すべてのスクリプト要素を評価して、スクリプトがまだ読み込まれていないことを確認します。
document.ready
イベントが実行されるまで、スクリプトは完全には実行されないと思います。(使用document.ready
は必須ではないことはわかっていますが、多くの人が使用しており、これを扱うことは安全策です。)
追加のファイルがロードされると、document.ready
コールバックが間違った順序で実行されます。スクリプトが実際にロードされたときにこれに対処するために、スクリプトをインポートしたスクリプト自体が再インポートされ、実行が停止します。これにより、元のファイルは、document.ready
インポートするスクリプトからのコールバックが実行されるようになります。
このアプローチの代わりにjQueryを変更することもできますがreadyList
、これはより悪い解決策のように見えました。
解決:
$.extend(true,
{
import_js : function(scriptpath, reAddLast)
{
if (typeof reAddLast === "undefined" || reAddLast === null)
{
reAddLast = true; // Default this value to true. It is not used by the end user, only to facilitate recursion correctly.
}
var found = false;
if (reAddLast == true) // If we are re-adding the originating script we do not care if it has already been added.
{
found = $('script').filter(function () {
return ($(this).attr('src') == scriptpath);
}).length != 0; // jQuery to check if the script already exists. (replace it with straight JavaScript if you don't like jQuery.
}
if (found == false) {
var callingScriptPath = $('script').last().attr("src"); // Get the script that is currently loading. Again this creates a limitation where this should not be used in a button, and only before document.ready.
document.writeln("<script type='text/javascript' src='" + scriptpath + "'></script>"); // Add the script to the document using writeln
if (reAddLast)
{
$.import_js(callingScriptPath, false); // Call itself with the originating script to fix the order.
throw 'Readding script to correct order: ' + scriptpath + ' < ' + callingScriptPath; // This halts execution of the originating script since it is getting reloaded. If you put a try / catch around the call to $.import_js you results will vary.
}
return true;
}
return false;
}
});
使用法:
File3:
var f3obj = "file3";
// Define other stuff
$(function(){
f3obj = "file3docready";
});
ファイル2:
$.import_js('js/file3.js');
var f2obj = "file2";
$(function(){
f2obj = "file2docready";
});
ファイル1:
$.import_js('js/file2.js');
// Use objects from file2 or file3
alert(f3obj); // "file3"
alert(f2obj); // "file2"
$(function(){
// Use objects from file2 or file3 some more.
alert(f3obj); //"file3docready"
alert(f2obj); //"file2docready"
});
Javascriptでモジュールを実装する方法はいくつかあります。最も一般的なものを2つ示します。
ブラウザーはまだこの変調システムをサポートしていないため、この構文を使用するには、webpackなどのバンドラーを使用する必要があります。いずれにしても、バンドラーを使用する方が優れています。これにより、すべての異なるファイルを1つの(または関連する)ファイルに結合できるからです。これにより、各HTTPリクエストに付随するオーバーヘッドが伴うため、サーバーからクライアントへのファイルの配信が速くなります。したがって、全体的なHTTPリクエストを減らすことで、パフォーマンスが向上します。ES6モジュールの例を次に示します。
// main.js file
export function add (a, b) {
return a + b;
}
export default function multiply (a, b) {
return a * b;
}
// test.js file
import {add}, multiply from './main'; // for named exports between curly braces {export1, export2}
// for default exports without {}
console.log(multiply(2, 2)); // logs 4
console.log(add(1, 2)); // logs 3
この変調システムはNodeJSで使用されます。基本的には、と呼ばれるオブジェクトにエクスポートを追加しますmodule.exports
。その後、を介してこのオブジェクトにアクセスできますrequire('modulePath')
。ここで重要なのは、これらのモジュールがキャッシュされていることを認識することです。そのためrequire()
、特定のモジュールを2回実行すると、すでに作成されたモジュールが返されます。
// main.js file
function add (a, b) {
return a + b;
}
module.exports = add; // here we add our add function to the exports object
// test.js file
const add = require('./main');
console.log(add(1,2)); // logs 3
有用なJavaScriptプラグインのコレクションを維持する簡単な方法を探していたので、この質問に行きました。ここでいくつかの解決策を見た後、私はこれを思いつきました:
「plugins.js」(またはextensions.jsなどの任意のファイル)というファイルを設定します。プラグインファイルを1つのマスターファイルと一緒に保管します。
plugins.jsには、pluginNames[]
繰り返し処理されるというと呼ばれる配列があり、各プラグインのヘッドにタグをeach()
追加し<script>
ます
//set array to be updated when we add or remove plugin files
var pluginNames = ["lettering", "fittext", "butterjam", etc.];
//one script tag for each plugin
$.each(pluginNames, function(){
$('head').append('<script src="js/plugins/' + this + '.js"></script>');
});
<script src="js/plugins/plugins.js"></script>
だが:
すべてのプラグインが本来の方法でヘッドタグにドロップされますが、ページをクリックしたり更新したりしても、ブラウザによって常に実行されるわけではありません。
PHPインクルードでスクリプトタグを記述する方が信頼性が高いことがわかりました。あなたはそれを一度書くだけでよく、それはJavaScriptを使用してプラグインを呼び出すのと同じくらい多くの仕事です。