ホームページ >ウェブフロントエンド >フロントエンドQ&A >なぜWebページをモジュール化する必要があるのでしょうか?
この記事では、Web モジュール化がなぜ有用であるかを説明し、Web モジュール化を今すぐ実装するために使用できるいくつかのメカニズムを紹介します。こちらは、RequireJS で使用される関数ラッピング形式の設計思想を説明した別の記事です。
問題§1
Webサイトは徐々にWebアプリに変わっていく
コードの複雑さは徐々に増加している
組み立てが困難になっている
開発者はJSファイル/モジュールを分離したい
リクエストのデプロイ時にコードを複数のHTTPに最適化できる
解決策 §2
フロントエンド開発者には次のような解決策が必要です:
そのような API #include/import/require
ネストされた依存関係を読み込む機能があります
開発者にとって使いやすく、その背後に最適化ツールがありますhelpdeploy
スクリプト読み込みAPI § 3
まずスクリプト読み込みAPIを整理します。ここにはいくつかのオプションがあります:
Dojo: dojo.require("some.module") LABjs: $LAB.script("some/module.js") CommonJS: require("some/module")
すべては some/path/some/module.js の読み込みにマップされます。 CommonJS の構文はより一般的になる可能性が高く、コードを再利用したいため、理想的には CommonJS の構文を選択します。
私たちは現在、既存のプレーンテキスト JavaScript ファイルをロードできる構文をいくつか用意したいと考えています。これにより、開発者はスクリプトのロードのメリットを得るためにすべての JavaScript を書き直す必要がなくなります。
しかし、ブラウザでもっとうまく動作するものが必要です。 CommonJS の require() は、モジュールがすぐに返されることを期待する同期呼び出しです。ただし、これはブラウザではうまく機能しません。
非同期と同期§ 4
次の例は、ブラウザの基本的な問題を示しています。 Employee オブジェクトがあり、Employee オブジェクトから派生した Manager オブジェクトが必要だとします。この例では、スクリプトを使用して API をロードし、次のようにコーディングします。
var Employee = require("types/Employee");function Manager () { this.reports = []; }//Error if require call is asyncManager.prototype = new Employee();
上記のコメントに示されているように、require() が非同期の場合、このコードは機能しません。ただし、ブラウザにスクリプトを同期的に読み込むと、パフォーマンスが低下します。じゃあ何をすればいいの?
スクリプトの読み込み: XHR§ 5
スクリプトの読み込みに XMLHttpRequest (XHR) を使用するのは非常に魅力的です。 XHR を使用する場合、上記のテキストに触れることができます。つまり、正規表現を使用して require() 呼び出しを見つけてこれらのスクリプトを確実にロードし、eval() または script 要素を使用してテキスト コンテンツをユーザーに渡すことができます。 XHR 読み込みスクリプト。
モジュールの評価に eval() を使用するのは良くありません:
開発者は、eval() を使用するのは良くないと言われています。
一部の環境では eval() がサポートされていません。
デバッグが難しい。 Firebug と WebKit のインスペクタには、評価されるテキストに名前を付けるための //@sourceURL= 規則がありますが、この機能はすべてのブラウザでサポートされているわけではありません。
ブラウザが異なればコンテキストの評価も異なります。 IE の execScript がそれを行う可能性がありますが、それはまた、より多くの可動部分を意味します。
テキストコンテンツを含むスクリプトタグを使用してファイルテキストとして設定することも良くありません:
デバッグ時に得られるエラー行番号がソースファイル番号と一致しません。
XHR には、クロスドメインリクエストを行う際に依然として問題があります。一部のブラウザーはクロスドメイン XHR をサポートしていますが、すべてではありません。そして IE は、クロスドメイン要求を実装するために、別の API オブジェクト XDomainRequest を作成することにしました。変更しなければならないことが増え、間違いを犯しやすくなります。特に、このクロスオリジン要求が確実に許可されるようにするには、非標準の HTTP ヘッダーを送信しないようにするか、別の「プリフライト」要求を要求しないようにする必要があります。
Dojo は eval() を通じて XHR ベースのローダーを使用しますが、それは機能しますが、開発者にとっては常に問題の原因でした。 Dojo には xdomain ローダーがありますが、関数ラッパーを使用して require モジュールを変更する必要があるため、script src="" タグを使用してモジュールをロードできます。プログラマにとって困難をもたらす特殊なケースやバリエーションも数多くあります。
新しいスクリプトローダーを作成すれば、もっとうまくできるでしょう。
スクリプトの読み込み: Web ワーカー § 6
Web ワーカーはスクリプトをロードする別の方法かもしれませんが、:
クロスプラットフォームではありません
メッセージング API であり、スクリプトは DOM を対話的に処理する必要があるかもしれません。ワーカーを使用してスクリプトのテキストを取得し、そのテキストをメイン ウィンドウに返し、その後 eval/script を使用してスクリプトを実行します。このアプローチには、上で述べた XHR のすべての問題が伴います。
スクリプトの読み込み: document.write()§ 7
Document.write() は、他のドメインからスクリプトを読み込み、ブラウザが通常どのようにスクリプトを使用するかをマッピングするために使用できるため、簡単なデバッグに使用できます。
ただし、非同期と同期の例では、スクリプトを直接実行することはできません。理想的には、スクリプトを実行する前に require() を介して関連する依存関係を把握し、これらの依存関係が最初に読み込まれるようにする必要があります。ただし、スクリプトが実行される前にアクセスすることはできません。
而且,document.write()在页面载入后就不工作了。对于你的网站,一个好的方法是在用户需要进行下一步操作时来载入脚本。
最后,通过document.write()载入脚本或阻塞页面的渲染。要让你的网站有最佳表现,这个方法是不可取的。
脚本载入:head.appendChild(script)§ 8
我们可以在需要时创建脚本并将它们添加到头部:
var head = document.getElementsByTagName('head')[0], script = document.createElement('script'); script.src = url; head.appendChild(script);
上面的脚本片段多了一点东西,不过那正是基本的思想。这种方法比document.write要好,因为它不会阻塞页面的渲染并且在页面载入后仍能工作。
但是,它仍然有同步VS异步例子的问题:理想情况下,在执行脚本前我们能够通过require()知道相关依赖项,并且确保这些依赖项被首先载入。
函数封装 § 9
在执行我们的脚本前,我们需要知道相关依赖项并确保已经将其载入。做这件事的最好方法是通过函数封装来构造我们的模块载入API。像这样:
define( //The name of this module "types/Manager", //The array of dependencies ["types/Employee"], //The function to execute when all dependencies have loaded. The //arguments to this function are the array of dependencies mentioned //above. function (Employee) { function Manager () { this.reports = []; } //This will now work Manager.prototype = new Employee(); //return the Manager constructor function so it can be used by //other modules. return Manager; } );
这是ReguireJS的句法。如果你想载入没有定义成模块的纯文本的JavaScript的话,有一种简单的句法:
require(["some/script.js"], function() { //This function is called after some/script.js has loaded. });
选择这种句法是因为,它足够简洁并且允许载入者使用head.appendChild(script)载入类型。
出于在浏览器中良好工作的需要,它有不同于普通的CommonJS句法。有建议说普通的CommonJS句法可以使用head.appendChild(script)的载入类型,如果服务器进程有封装的函数可以将模块转换成传输格式的话。
我相信不强制使用一个运行时服务器进程来转换代码是很重要的事:
一是调试变的很怪异,因为服务器在注入封装函数时会导致源文件的行号关闭。
二是需要做更多的工作。前端开发应该尽可能的使用静态文件。
关于设计的力量和功能封装格式的使用案例的更多细节,被叫做异步模块定义(Asynchronous Module Definition (AMD)),请前往为什么是AMD?
原文地址:http://www.php.cn/website-design-ask-340211.html
以上就是为什么要web网页模块化?的内容,更多相关内容请关注PHP中文网(www.php.cn)!