この記事は Javascript のモジュール化について詳しく説明しています。必要な方は参考にしていただければ幸いです。
Web テクノロジーの精力的な発展と、それが依存するインフラストラクチャがますます完璧になるにつれて、フロントエンドの分野はブラウザーからサーバー (Node.js)、デスクトップ (PC、Android、iOS)、 JavaScript がこれらのアプリケーションの中核部分を担うモノのインターネット (IoT) でさえ、その規模と複雑さが指数関数的に増大するにつれて、ソフトウェア エンジニアリング システム (共同開発、単体テスト、要件と欠陥管理など) も確立されています。 )、モジュール式プログラミングの需要がますます高まっています。
JavaScript によるモジュール型プログラミングのサポートはまだ標準化されておらず、この重要な任務を担うのは困難ですが、一時は戦士たちが前進してすべての障害を克服し、焼き畑農業から未来志向のモジュール型ソリューションに移行しました。
モジュラープログラミングは、いくつかの __比較的独立した再利用可能なモジュール__ を組み合わせることによって機能を実現することです。モジュールの場合、各モジュール内の実行ロジックは外部からは認識されず、一部のメソッドとデータのみをエクスポート (公開) します
モジュールが導入されると、同期/非同期でロードされ、導入されるコードが実行されます。そして、その公開されたメソッドとデータが取得されます
焼き畑農業
モジュールが定義されるとき、そのコードはすでに実行プロセスを完了しており、オンデマンドでロードすることはできません。 ;
「焼き畑」時代の残りのニーズを解決するために、AMD および CMD のモジュラー仕様が登場しました。ブラウザ側での非同期モジュラー プログラミングの必要性を解決しました。 __other 基本原則は、スクリプトとイベント リスニングを動的にロードすることでモジュールを非同期にロードすることです。 __
実装
1. モジュール定義
。 2. モジュールをインポートします
組み込みモジュール、メモリから直接ロードされます。
外部モジュールは、最初にファイルのアドレス指定と配置を実行し、次にコンパイルして実行し、最後に対応するエクスポート値を取得します
コンパイルプロセス中に、Node は取得した JavaScript のコンテンツをラップします。ファイルの先頭と末尾は次のとおりです:
// Define a module var moduleA = (function ($, doc) { var methodA = function() {}; var dataA = {}; return { methodA: methodA, dataA: dataA }; })(jQuery, document); // Use a module var result = moduleA.mehodA();
同期モジュール宣言とインポートロジックを実行し、一部の複雑な依存関係参照(循環依存関係など)を分析する場合は注意してください。パフォーマンスが向上し、メモリ使用量が制限されます。
モジュールは柔軟に変更できます。高い精度で、一部のカスタマイズ要件を実現できます (ホット アップデート、あらゆるファイル タイプのモジュール サポートなど)。
ES Module 是语言层面的模块化方案,由 ES 2015 提出,其规范与 CommonJS 比之 ,导出的值都可以看成是一个具备多个属性或者方法的对象,可以实现互相兼容;但写法上 ES Module 更简洁,与 Python 接近;
import fs from 'fs'; import color from 'color'; import service, { getArticles } from '../service'; export default service; export const getArticles = getArticles;
主要差异在于:
ES Module 会对静态代码分析,即在代码编译时进行模块的加载,在运行时之前就已经确定了依赖关系(可解决循环引用的问题);
ES Module 关键字:import
export
以及独有的 default
关键字,确定默认的导出值;
ES Module 中导入模块的属性或者方法是强绑定的,包括基础类型;
通过一层自执行函数来兼容各种模块化规范的写法,兼容 AMD / CMD / CommonJS 等模块化规范,贴上代码胜过千言万语,需要特别注意的是 ES Module 由于会对静态代码进行分析,故这种运行时的方案无法使用,此时通过 CommonJS 进行兼容;
(function (global, factory) { if (typeof exports === 'object') { module.exports = factory(); } else if (typeof define === 'function' && define.amd) { define(factory); } else { this.eventUtil = factory(); } })(this, function (exports) { // Define Module Object.defineProperty(exports, "__esModule", { value: true }); exports.default = 42; });
为了在浏览器环境中运行模块化的代码,需要借助一些模块化打包的工具进行打包( 以 webpack 为例),定义了项目入口之后,会先快速地进行依赖的分析,然后将所有依赖的模块转换成浏览器兼容的对应模块化规范的实现;
从上面的介绍中,我们已经对其规范和实现有了一定的了解;在浏览器中,要实现 CommonJS 规范,只需要实现 module / exports / require / global 这几个属性,由于浏览器中是无法访问文件系统的,因此 require 过程中的文件定位需要改造为加载对应的 JS 片段(webpack 采用的方式为通过函数传参实现依赖的引入)。具体实现可以参考:tiny-browser-require。
webpack 打包出来的代码快照如下,注意看注释中的时序;
(function (modules) { // The module cache var installedModules = {}; // The require function function __webpack_require__(moduleId) {} return __webpack_require__(0); // ---> 0 }) ({ 0: function (module, exports, __webpack_require__) { // Define module A var moduleB = __webpack_require__(1); // ---> 1 }, 1: function (module, exports, __webpack_require__) { // Define module B exports = {}; // ---> 2 } });
实际上,ES Module 的处理同 CommonJS 相差无几,只是在定义模块和引入模块时会去处理 __esModule 标识,从而兼容其在语法上的差异。
1、浏览器环境下,网络资源受到较大的限制,因此打包出来的文件如果体积巨大,对页面性能的损耗极大,因此需要对构建的目标文件进行拆分,同时模块也需要支持动态加载;
webpack 提供了两个方法 require.ensure() 和 import() (推荐使用)进行模块的动态加载,至于其中的原理,跟上面提及的 AMD & CMD 所见略同,import() 执行后返回一个 Promise 对象,其中所做的工作无非也是动态新增 script 标签,然后通过 onload / onerror 事件进一步处理。
2、由于 require 函数是完全自定义的,我们可以在模块化中实现更多的特性,比如通过修改 require.resolve 或 Module._extensions 扩展支持的文件类型,使得 css / .jsx / .vue / 图片等文件也能为模块化所使用;
模块化规范 | 加载方式 | 加载时机 | 运行环境 | 备注 |
---|---|---|---|---|
AMD | 异步 | 运行时 | 浏览器 | |
CMD | 异步 | 运行时 | 浏览器 | |
CommonJS | 同步/异步 | 运行时 | 浏览器 / Node | |
ES Module | 同步/异步 | 编译阶段 | 浏览器 / Node | 通过 import() 实现异步加载 |
相关推荐:
javascript模块化编程(转载),javascript模块化
以上がJavascript のモジュール性の詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。