电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

淺談JS前端模塊化的幾種規范

瀏覽:110日期:2024-03-29 11:25:44
前言

有這樣一個場景,客戶端運行很久,但是法務部和數據部需要收集用戶的一些信息,這些信息收集好之后需要進行相應的數據處理,之后上報到服務端。客戶端提供一個純粹的js執行引擎,不需要 WebView 容器。iOS 端有成熟的JavaScriptCore、Android 可以使用 V8 引擎。這樣一個引擎配套有一個 SDK,訪問 Native 的基礎能力和數據運算能力,可以看成是一個閹割版的 Hybrid SDK 額外增加了一些數據處理能力。

問題結束了嗎?處理邏輯的時候還需要用到2個庫:cheerio和sql。因為都是 Node 工程,所以純粹的js環境是沒辦法直接執行。所以需求就進行了轉變 ———— 將 Node 項目打包成 UMD 規范。這樣就可以在純粹的 JS 環境下運行。接下來的文章就分析下各種規范。其實也就是前端模塊化的幾種規范。

前端模塊化開發的價值

隨著互聯網的飛速發展,前端開發越來越復雜。本文將從實際項目中遇到的問題出發,講述模塊化能解決哪些問題,以及以 Sea.js 為例講解如何進行前端的模塊化開發。

惱人的命名沖突

我們從一個簡單的習慣出發。我做項目時,常常會將一些通用的、底層的功能抽象出來,獨立成一個個函數,比如

function each(arr) {// 實現代碼} function log(str) {// 實現代碼}

并像模像樣的將這些代碼抽取出來并統一到util.js中,在需要使用的地方引入該文件,看起來很棒,團隊內的同事很感激我提供了這么便利的工具包。

直到團隊越來越大,開始有人抱怨

小楊:我定義了一個 each 方法遍歷對象,但是 util.js 中已經存在一個 each 方法,每次都需要改方法名,我只能叫 eachObject 方法。<br>張三:我定義了一個 log 方法,可是王武的代碼出問題了,誰來看看?

抱怨越來越多,最后參照 Java 的方式,引入命名空間解決問題。于是 util.js 代碼變成了

var org = {};org.Utils = {};org.Utils.each = function (arr) {// 實現代碼};org.Utils.log = function (str) {// 實現代碼};

可能看上去的代碼很 low,其實命名空間在前端領域的布道者是 Yahoo!的 YUI2 項目,看看下面的代碼,是 Yahoo!的一個開源項目

if (org.cometd.Utils.isString(response)) {return org.cometd.JSON.fromJSON(response);}if (org.cometd.Utils.isArray(response)) {return response;}

通過命名空間雖然可以極大的解決沖突問題,但是每次在調用一個方法時都需要寫一大堆命名空間相關的代碼,剝奪了編碼樂趣。

另一種方式是一個自執行函數來實現。

(function (args) {//...})(this);繁瑣的文件依賴

繼續上述場景,很多情況下都需要開發 UI 層通用組件,這樣項目組就不需要重復造輪子。其中有一個高頻使用的組件就是 dialog.js

<script src='http://www.hdgsjgj.cn/bcjs/util.js'></script><script src='http://www.hdgsjgj.cn/bcjs/dialog.js'></script><script>org.Dialog.init({ /* 傳入配置 */ });</script>

雖然公共組做項目都會編寫使用文檔、發送郵件告知全員(項目地址、使用方式等),但是還是有人問「為什么 dialog.js 有問題」,最后排查的結果基本都是沒有引入 util.js

<script src='http://www.hdgsjgj.cn/bcjs/dialog.js'></script><script>org.Dialog.init({ /* 傳入配置 */ });</script>

命名沖突和文件依賴是前端開發中2個經典問題,經過開發者不斷的思考和研究,誕生了模塊化的解決方案,以 CMD 為例

define(function(require, exports) {exports.each = function (array) {// ...};exports.log = function(message) {// ...};});

通過 exports 就可以向外提供接口, dialog.js 代碼變成

define(function(require, exports) {var util = require(’./util.js’) exports.init = function () {// ...};});

使用的時候可以通過require(’./util.js’)獲取到 util.js 中通過 exports 暴露的接口。 require 的方式在其他很多語言中都有解決方案:include、

模塊化的好處

1.模塊的版本管理:通過別名等配置,配合構建工具,可以輕松實現模塊的版本管理

2.提高可維護性: 模塊化可以實現每個文件的職責單一,非常有利于代碼的維護。

3.前端性能優化: 對于前端開發來說,異步加載模塊對于頁面性能非常有益。

4.跨環境共享模塊: CMD 模塊定義規范與 NodeJS 的模塊規范非常相近,所以通過 Sea.JS 的 NodeJS 版本,可以方便的實現模塊的跨服務器和瀏覽器共享。

CommonJS 規范

CommonJS 是服務器端模塊的規范。NodeJS 采用了這個規范。CommonJS 加載模塊是同步的,所以只有加載完成后才能執行后面的操作。

因為服務器的特點,加載的模塊文件一般都存在在本地硬盤,所以加載起來比較快,不用考慮異步的方式。

CommonJS 模塊化的餓規范中,每個文件都是一個模塊,擁有獨立的作用域、變量、以及方法等,對其他模塊不可見。 CommonJS 規范規定,每個模塊內部,module變量表示當前模塊,它是一個對象,它的exports屬性是對外的接口,加載某個模塊,其實是加載該模塊的 module.exports 屬性,require 方法用于加載模塊。

// Person.jsfunction Person () {this.eat = function () {console.log(’eat something’)} this.sleep = function () {console.log(’sleep’)}} var person = new Person();exports.person = person;exports.name = name; // index.jslet person = require(’./Person’).person;person.eat()CommonJS 與 ES6 模塊的差異

1.CommonJS 模塊輸出的是值的拷貝,ES6 模塊輸出的是值的引用

2.CommonJS 模塊是運行時加載,ES6 模塊是編譯時輸出接口

CommonJS 模塊導出的是一個對象(module.exports 屬性),該對象只在腳本運行完才會生成。

ES6 的模塊機制是 JS 引擎對腳本進行靜態分析的時候,遇到模塊加載命令 import,就會生成一個只讀引用,等到腳本真正執行時,再根據這個只讀引用到被加載的模塊中取值,

AMD 規范

AMD(Asynchronous Module Definition) 是在 Require.JS 推廣的過程中對模塊定義的規范化產出。AMD 推崇依賴前置。它是 CommonJS 模塊化規范的超集,作用在瀏覽器上。它的特點是異步,利用了瀏覽器的并發能力,讓模塊的依賴阻塞變少。

AMD 的 API

define(id?, dependencyies?, factory);

id 是模塊的名字,是可選參數。 dependencies 指定了該模塊所依賴的模塊列表,是一個數組,也是可選參數。每個依賴的模塊的輸出都將作為參數依次傳入 factory 中。

require([module], callback)

AMD 規范允許輸出模塊兼容 CommonJS 規范,這時 define 方法如下

define([’module1’, ’module2’], function(module1, module2) {function foo () {// ...}return { foo: foo };});define(function(require, exports, module) {var requestedModule1 = require(’./module1’)var requestedModule2 = require(’./module2’)function foo () {// ...}return { foo: foo };});

優點: 適合在瀏覽器環境中加載模塊,可以實現并行加載多個模塊

缺點: 提高了開發成本,并不能按需加載,而是提前加載所有的依賴

CMD 規范

CMD 是 Sea.JS 推廣的過程中對模塊定義的規范化產出。CMD 推崇依賴就近。

CMD 規范盡量保持簡單,并與 CommonJS 規范中的 Module 保持兼容,通過 CMD 規范編寫的模塊,可以在 NodeJS 中運行。

CMD 模塊定義規范

CMD 中 require 依賴的描述用數組,則是異步加載,如果是單個依賴使用字符串,則是同步加載。

AMD 是 RequireJS 在推廣過程中對模塊定義的規范化產出,CMD是SeaJS 在推廣過程中被廣泛認知。SeaJS 出自國內螞蟻金服玉伯。二者的區別,玉伯在12年如是說:

RequireJS 和 SeaJS 都是很不錯的模塊加載器,兩者區別如下:

兩者定位有差異。RequireJS 想成為瀏覽器端的模塊加載器,同時也想成為 Rhino / Node 等環境的模塊加載器。SeaJS 則專注于 Web 瀏覽器端,同時通過 Node 擴展的方式可以很方便跑在 Node 服務器端 兩者遵循的標準有差異。RequireJS 遵循的是 AMD(異步模塊定義)規范,SeaJS 遵循的是 CMD (通用模塊定義)規范。規范的不同,導致了兩者API 的不同。SeaJS 更簡潔優雅,更貼近 CommonJS Modules/1.1 和 Node Modules 規范。 兩者社區理念有差異。RequireJS 在嘗試讓第三方類庫修改自身來支持 RequireJS,目前只有少數社區采納。SeaJS 不強推,而采用自主封裝的方式來“海納百川”,目前已有較成熟的封裝策略。 兩者代碼質量有差異。RequireJS 是沒有明顯的 bug,SeaJS 是明顯沒有 bug。 兩者對調試等的支持有差異。SeaJS 通過插件,可以實現 Fiddler 中自動映射的功能,還可以實現自動 combo 等功能,非常方便便捷。RequireJS無這方面的支持。 兩者的插件機制有差異。RequireJS 采取的是在源碼中預留接口的形式,源碼中留有為插件而寫的代碼。SeaJS 采取的插件機制則與 Node 的方式一致開放自身,讓插件開發者可直接訪問或修改,從而非常靈活,可以實現各種類型的插件。UMD 規范

UMD(Universal Module Definition)是隨著大前端的趨勢產生,希望提供一個前后端跨平臺的解決方案(支持 AMD、CMD、CommonJS 模塊方式)。

實現原理:

1.先判斷是否支持 Node.js 模塊格式(exports 是否存在),存在則使用 Node.js 模塊格式

2.再判斷是否支持 AMD 模塊格式(define 是否存在),存在則使用 AMD 模塊格式

3.前2個都不存在則將模塊公開到全局(window 或 global)

// if the module has no dependencies, the above pattern can be simplified to(function (root, factory) {if (typeof define === ’function’ && define.amd) {// AMD. Register as an anonymous module.define([], factory);} else if (typeof exports === ’object’) {// Node. Does not work with strict CommonJS, but// only CommonJS-like environments that support module.exports,// like Node.module.exports = factory();} else {// Browser globals (root is window)root.returnExports = factory();}}(this, function () { // Just return a value to define the module export.// This example returns an object, but the module// can return a function as the exported value.return {};}));

可能有些人就要問了,為什么在上面的判斷中寫了 AMD,怎么沒有 CMD?因為前端構建工具webpack不可識別 CMD 規范,使用 CMD 就需要引用工具,比如 Sea.JS

講道理,如果想判斷 CMD,那 UMD 代碼如何寫?

(function(root, factory) {if (typeof define === ’function’ && define.amd) {// AMD. Register as an anonymous module.define([], factory);} else if (typeof define === ’function’ && define.cmd) {// CMDdefine(function(require, exports, module) {module.exports = factory()})} else if (typeof exports === ’object’) {// Node. Does not work with strict CommonJS, but// only CommonJS-like environments that support module.exports,// like Node.module.exports = factory();} else {// Browser globals (root is window)root.returnExports = factory();}}(this, function() {// Just return a value to define the module export.// This example returns an object, but the module// can return a function as the exported value.return {};}))回到正題

Cheerio 如何打包到普通的 JS 執行環境中。

借助webpack可以方便的打出一個 umd 規范的包。

module.exports = {entry: ’./src/cheerio.js’,output: {filename: ’cheerio.js’,// export to AMD, CommonJS, or windowlibraryTarget: ’umd’,// the name exported to windowlibrary: ’cheerio’,globalObject: ’this’}}總結

手機端(無論 iOS 還是 Android)的底層渲染內核都是類 Chrome v8 引擎。v8 引擎在執行 JS 代碼時,是將代碼先以 MacroAssembler 匯編庫在內存中先編譯成機器碼再送往 CPU 執行的,并不是像其它 JS 引擎那樣解析一行執行一行。所以,靜態加載的 ES6 模塊規范,更有助于 v8 引擎發揮價值。而運行時加載的 CommonJS、AMD、CMD 規范等,均不利于 v8 引擎施展拳腳。

在 NodeJS 開發項目中,Node9 已經支持 ES6語法,完全可以使用 ES6 模塊規范。NodeJS 的誕生,本身就基于 Google 的 v8 引擎,沒有理由不考慮發揮 v8 的最大潛能。

在瀏覽器 JS 開發項目中,因為從服務器加載文件需要時間,使用 CommonJS 規范肯定是不合適了。至于是使用原生的 ES 模塊規范,還是使用 Sea.js,要看具體場景。如果想頁面盡快加載,Sea.js 適合;如果是單頁面網站,適合使用原生的 ES6 模塊規范。還有一點,瀏覽器并非只有 Chrome 一家,對于沒有使用 v8 引擎的瀏覽器,使用 ES6 原生規范的優勢就又減少了一點。

以上就是淺談JS前端模塊化的幾種規范的詳細內容,更多關于JS前端模塊化的資料請關注好吧啦網其它相關文章!

標簽: JavaScript
相關文章:
主站蜘蛛池模板: 健身器材-健身器材厂家专卖-上海七诚健身器材有限公司 | 广东成考网-广东成人高考网 | 氟塑料磁力泵-不锈钢离心泵-耐腐蚀化工泵厂家「皖金泵阀」 | TPE_TPE热塑性弹性体_TPE原料价格_TPE材料厂家-惠州市中塑王塑胶制品公司- 中塑王塑胶制品有限公司 | 吸污车_吸粪车_抽粪车_电动三轮吸粪车_真空吸污车_高压清洗吸污车-远大汽车制造有限公司 | PC阳光板-PC耐力板-阳光板雨棚-耐力板雨棚,厂家定制[优尼科板材] | 深圳快餐店设计-餐饮设计公司-餐饮空间品牌全案设计-深圳市勤蜂装饰工程 | 南京蜂窝纸箱_南京木托盘_南京纸托盘-南京博恒包装有限公司 | 济宁工业提升门|济宁电动防火门|济宁快速堆积门-济宁市统一电动门有限公司 | 交通信号灯生产厂家_红绿灯厂家_电子警察监控杆_标志杆厂家-沃霖电子科技 | 冲击式破碎机-冲击式制砂机-移动碎石机厂家_青州市富康机械有限公司 | 佛山市钱丰金属不锈钢蜂窝板定制厂家|不锈钢装饰线条|不锈钢屏风| 电梯装饰板|不锈钢蜂窝板不锈钢工艺板材厂家佛山市钱丰金属制品有限公司 | 冰雕-冰雪世界-大型冰雕展制作公司-赛北冰雕官网 | 湖南印刷厂|长沙印刷公司|画册印刷|挂历印刷|台历印刷|杂志印刷-乐成印刷 | 密集架|电动密集架|移动密集架|黑龙江档案密集架-大量现货厂家销售 | 在线钠离子分析仪-硅酸根离子浓度测定仪-油液水分测定仪价格-北京时代新维测控设备有限公司 | 水冷式工业冷水机组_风冷式工业冷水机_水冷螺杆冷冻机组-深圳市普威机械设备有限公司 | 红酒招商加盟-葡萄酒加盟-进口红酒代理-青岛枞木酒业有限公司 | 江门流水线|江门工作台|江门市伟涛行工业设备有限公司 | 香蕉筛|直线|等厚|弧形|振动筛|香蕉筛厂家-洛阳隆中重工 | 实验室pH计|电导率仪|溶解氧测定仪|离子浓度计|多参数水质分析仪|pH电极-上海般特仪器有限公司 | 耐高温电缆厂家-远洋高温电缆 | 精准猎取科技资讯,高效阅读科技新闻_科技猎 | 数显水浴恒温振荡器-分液漏斗萃取振荡器-常州市凯航仪器有限公司 | 威海防火彩钢板,威海岩棉复合板,威海彩钢瓦-文登区九龙岩棉复合板厂 | 泰国专线_泰国物流专线_广州到泰国物流公司-泰廊曼国际 | 药品仓库用除湿机-变电站用防爆空调-油漆房用防爆空调-杭州特奥环保科技有限公司 | 振动筛,震动筛,圆形振动筛,振动筛价格,振动筛厂家-新乡巨宝机电 蒸汽热收缩机_蒸汽发生器_塑封机_包膜机_封切收缩机_热收缩包装机_真空机_全自动打包机_捆扎机_封箱机-东莞市中堡智能科技有限公司 | 宝宝药浴-产后药浴-药浴加盟-艾裕-专注母婴调养泡浴 | 安全阀_弹簧式安全阀_美标安全阀_工业冷冻安全阀厂家-中国·阿司米阀门有限公司 | 杭州可当科技有限公司—流量卡_随身WiFi_AI摄像头一站式解决方案 | FFU_空气初效|中效|高效过滤器_空调过滤网-广州梓净净化设备有限公司 | 骨密度仪-骨密度测定仪-超声骨密度仪-骨龄测定仪-天津开发区圣鸿医疗器械有限公司 | 铝箔袋,铝箔袋厂家,东莞铝箔袋,防静电铝箔袋,防静电屏蔽袋,防静电真空袋,真空袋-东莞铭晋让您的产品与众不同 | 杭州顺源过滤机械有限公司官网-压滤机_板框压滤机_厢式隔膜压滤机厂家 | 沈阳缠绕膜价格_沈阳拉伸膜厂家_沈阳缠绕膜厂家直销 | 上海冠顶工业设备有限公司-隧道炉,烘箱,UV固化机,涂装设备,高温炉,工业机器人生产厂家 | 耐酸泵,耐腐蚀真空泵,耐酸真空泵-淄博华舜耐腐蚀真空泵有限公司 精密模具-双色注塑模具加工-深圳铭洋宇通 | 皮带机_移动皮带机_大倾角皮带机_皮带机厂家 - 新乡市国盛机械设备有限公司 | 水质传感器_水质监测站_雨量监测站_水文监测站-山东水境传感科技有限公司 | 矿用履带式平板车|探水钻机|气动架柱式钻机|架柱式液压回转钻机|履带式钻机-启睿探水钻机厂家 |