日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

淺談JS前端模塊化的幾種規(guī)范

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

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

問題結(jié)束了嗎?處理邏輯的時(shí)候還需要用到2個(gè)庫:cheerio和sql。因?yàn)槎际?Node 工程,所以純粹的js環(huán)境是沒辦法直接執(zhí)行。所以需求就進(jìn)行了轉(zhuǎn)變 ———— 將 Node 項(xiàng)目打包成 UMD 規(guī)范。這樣就可以在純粹的 JS 環(huán)境下運(yùn)行。接下來的文章就分析下各種規(guī)范。其實(shí)也就是前端模塊化的幾種規(guī)范。

前端模塊化開發(fā)的價(jià)值

隨著互聯(lián)網(wǎng)的飛速發(fā)展,前端開發(fā)越來越復(fù)雜。本文將從實(shí)際項(xiàng)目中遇到的問題出發(fā),講述模塊化能解決哪些問題,以及以 Sea.js 為例講解如何進(jìn)行前端的模塊化開發(fā)。

惱人的命名沖突

我們從一個(gè)簡單的習(xí)慣出發(fā)。我做項(xiàng)目時(shí),常常會(huì)將一些通用的、底層的功能抽象出來,獨(dú)立成一個(gè)個(gè)函數(shù),比如

function each(arr) {// 實(shí)現(xiàn)代碼} function log(str) {// 實(shí)現(xiàn)代碼}

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

直到團(tuán)隊(duì)越來越大,開始有人抱怨

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

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

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

可能看上去的代碼很 low,其實(shí)命名空間在前端領(lǐng)域的布道者是 Yahoo!的 YUI2 項(xiàng)目,看看下面的代碼,是 Yahoo!的一個(gè)開源項(xiàng)目

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

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

另一種方式是一個(gè)自執(zhí)行函數(shù)來實(shí)現(xiàn)。

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

繼續(xù)上述場(chǎng)景,很多情況下都需要開發(fā) UI 層通用組件,這樣項(xiàng)目組就不需要重復(fù)造輪子。其中有一個(gè)高頻使用的組件就是 dialog.js

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

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

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

命名沖突和文件依賴是前端開發(fā)中2個(gè)經(jīng)典問題,經(jīng)過開發(fā)者不斷的思考和研究,誕生了模塊化的解決方案,以 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 () {// ...};});

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

模塊化的好處

1.模塊的版本管理:通過別名等配置,配合構(gòu)建工具,可以輕松實(shí)現(xiàn)模塊的版本管理

2.提高可維護(hù)性: 模塊化可以實(shí)現(xiàn)每個(gè)文件的職責(zé)單一,非常有利于代碼的維護(hù)。

3.前端性能優(yōu)化: 對(duì)于前端開發(fā)來說,異步加載模塊對(duì)于頁面性能非常有益。

4.跨環(huán)境共享模塊: CMD 模塊定義規(guī)范與 NodeJS 的模塊規(guī)范非常相近,所以通過 Sea.JS 的 NodeJS 版本,可以方便的實(shí)現(xiàn)模塊的跨服務(wù)器和瀏覽器共享。

CommonJS 規(guī)范

CommonJS 是服務(wù)器端模塊的規(guī)范。NodeJS 采用了這個(gè)規(guī)范。CommonJS 加載模塊是同步的,所以只有加載完成后才能執(zhí)行后面的操作。

因?yàn)榉?wù)器的特點(diǎn),加載的模塊文件一般都存在在本地硬盤,所以加載起來比較快,不用考慮異步的方式。

CommonJS 模塊化的餓規(guī)范中,每個(gè)文件都是一個(gè)模塊,擁有獨(dú)立的作用域、變量、以及方法等,對(duì)其他模塊不可見。 CommonJS 規(guī)范規(guī)定,每個(gè)模塊內(nèi)部,module變量表示當(dāng)前模塊,它是一個(gè)對(duì)象,它的exports屬性是對(duì)外的接口,加載某個(gè)模塊,其實(shí)是加載該模塊的 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 模塊是運(yùn)行時(shí)加載,ES6 模塊是編譯時(shí)輸出接口

CommonJS 模塊導(dǎo)出的是一個(gè)對(duì)象(module.exports 屬性),該對(duì)象只在腳本運(yùn)行完才會(huì)生成。

ES6 的模塊機(jī)制是 JS 引擎對(duì)腳本進(jìn)行靜態(tài)分析的時(shí)候,遇到模塊加載命令 import,就會(huì)生成一個(gè)只讀引用,等到腳本真正執(zhí)行時(shí),再根據(jù)這個(gè)只讀引用到被加載的模塊中取值,

AMD 規(guī)范

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

AMD 的 API

define(id?, dependencyies?, factory);

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

require([module], callback)

AMD 規(guī)范允許輸出模塊兼容 CommonJS 規(guī)范,這時(shí) 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 };});

優(yōu)點(diǎn): 適合在瀏覽器環(huán)境中加載模塊,可以實(shí)現(xiàn)并行加載多個(gè)模塊

缺點(diǎn): 提高了開發(fā)成本,并不能按需加載,而是提前加載所有的依賴

CMD 規(guī)范

CMD 是 Sea.JS 推廣的過程中對(duì)模塊定義的規(guī)范化產(chǎn)出。CMD 推崇依賴就近。

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

CMD 模塊定義規(guī)范

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

AMD 是 RequireJS 在推廣過程中對(duì)模塊定義的規(guī)范化產(chǎn)出,CMD是SeaJS 在推廣過程中被廣泛認(rèn)知。SeaJS 出自國內(nèi)螞蟻金服玉伯。二者的區(qū)別,玉伯在12年如是說:

RequireJS 和 SeaJS 都是很不錯(cuò)的模塊加載器,兩者區(qū)別如下:

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

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

實(shí)現(xiàn)原理:

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

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

3.前2個(gè)都不存在則將模塊公開到全局(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?因?yàn)榍岸藰?gòu)建工具webpack不可識(shí)別 CMD 規(guī)范,使用 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 執(zhí)行環(huán)境中。

借助webpack可以方便的打出一個(gè) umd 規(guī)范的包。

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’}}總結(jié)

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

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

在瀏覽器 JS 開發(fā)項(xiàng)目中,因?yàn)閺姆?wù)器加載文件需要時(shí)間,使用 CommonJS 規(guī)范肯定是不合適了。至于是使用原生的 ES 模塊規(guī)范,還是使用 Sea.js,要看具體場(chǎng)景。如果想頁面盡快加載,Sea.js 適合;如果是單頁面網(wǎng)站,適合使用原生的 ES6 模塊規(guī)范。還有一點(diǎn),瀏覽器并非只有 Chrome 一家,對(duì)于沒有使用 v8 引擎的瀏覽器,使用 ES6 原生規(guī)范的優(yōu)勢(shì)就又減少了一點(diǎn)。

以上就是淺談JS前端模塊化的幾種規(guī)范的詳細(xì)內(nèi)容,更多關(guān)于JS前端模塊化的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: JavaScript
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
黑人精品一区| 日韩精品一区第一页| 三级亚洲高清视频| 日韩欧美另类中文字幕| 欧美精品羞羞答答| 喷白浆一区二区| 成人台湾亚洲精品一区二区| 99国产精品免费视频观看| 视频一区中文字幕精品| 国产中文欧美日韩在线| 精品午夜久久| 欧美午夜精彩| 免费在线欧美视频| 日欧美一区二区| 婷婷综合一区| 高清精品久久| 久久av影视| 久久国产主播| 国产精品一区二区99| 国产传媒在线观看| 亚洲专区视频| 成人日韩在线观看| 国产福利一区二区精品秒拍 | 亚洲91在线| 麻豆91在线播放| 亚洲一二av| 高清av一区| 日韩国产一区二| 亚洲精品乱码久久久久久蜜桃麻豆| 久久天堂影院| 91精品国产自产精品男人的天堂| 亚洲成人精品| 国产日产精品_国产精品毛片| 激情欧美亚洲| 99久久精品国产亚洲精品| 欧美色图一区| 美女在线视频一区| 国产日韩欧美三区| 亚洲一区观看| 欧美日韩高清| 久久国产99| 亚洲伦乱视频| 日韩欧美少妇| 国产精品22p| 美女视频免费精品| 美女久久久久久| 久久av超碰| 国产精品久久久久久久免费软件 | 老司机精品久久| 国产一区欧美| 国产一区白浆| 国产亚洲亚洲| 麻豆亚洲精品| 亚洲理论在线| 欧美另类中文字幕| 亚洲激情欧美| 麻豆亚洲精品| 精品久久电影| 亚洲欧美一区在线| 亚洲免费精品| 国产资源在线观看入口av| 亚洲一区二区日韩| 国产精品久久久久久久久久妞妞| 精品一区二区三区亚洲| 亚洲另类视频| 97欧美在线视频| 99在线|亚洲一区二区| 午夜日韩福利| 日韩精品三级| 中文字幕日韩亚洲| 久久精品三级| 日韩天堂在线| 日韩动漫一区| 日韩.com| 亚洲精品麻豆| 亚洲不卡系列| 日本成人中文字幕在线视频| 欧美aⅴ一区二区三区视频| 亚洲v天堂v手机在线| 性欧美长视频| 蜜桃av在线播放| 午夜欧美巨大性欧美巨大| 精品一区免费| 国产精品v日韩精品v欧美精品网站 | 欧美日韩在线观看视频小说| 四虎精品永久免费| 国产精品2区| 四虎精品一区二区免费| 久久99久久久精品欧美| 国产精品日本欧美一区二区三区| 精品网站999| 一区二区精品| 亚洲精品一区三区三区在线观看| 国产伦久视频在线观看| 日本va欧美va精品发布| 99久久亚洲精品| 老司机精品在线| 亚洲久久在线| 日韩高清中文字幕一区| 国产精品久久久久久久久久齐齐 | 999精品色在线播放| 精品三级久久久| 国产精品免费大片| 亚洲v天堂v手机在线| 亚洲欧美日韩在线观看a三区| 久久视频国产| 欧美日韩精品一区二区三区视频 | 麻豆91小视频| 狠狠久久婷婷| 午夜久久av | 国产精品白丝av嫩草影院| 国产极品嫩模在线观看91精品| 成人精品高清在线视频| 成人亚洲一区| 老司机精品视频网| 久久精品国产久精国产爱| 日本精品国产| 国产探花一区二区| 一区二区91| 久久精品五月| 国产精品蜜芽在线观看| 波多野结衣久久精品| 色婷婷久久久| 久久人人精品| 欧美在线看片| 久久99精品久久久野外观看| 亚洲国内欧美| 欧美91福利在线观看| 亚洲调教视频在线观看| 日韩亚洲一区在线| 综合精品一区| 亚洲深爱激情| 久久九九精品| 久久99精品久久久久久园产越南 | 国产精品视频一区二区三区 | 女主播福利一区| 国产日韩免费| 精品一区二区三区免费看| 亚洲国产专区| 亚洲欧美日韩精品一区二区| 亚洲精品系列| 久久一二三区| 欧美在线精品一区| 青青在线精品| 亚洲精品亚洲人成在线观看| 樱桃成人精品视频在线播放| 日韩国产专区| 欧美va天堂在线| 日韩av字幕| 国产精品一区二区三区www| 国产精品扒开腿做爽爽爽软件| 国产一区二区三区探花| 日本一二区不卡| 国产国产精品| 91精品国产经典在线观看| 精品国产99| 日韩电影免费网址| 最近国产精品视频| 精品国产亚洲一区二区三区在线 | 国产精品99视频| 欧美网站在线| 欧美激情aⅴ一区二区三区| 99久久久久国产精品| 欧美一级网址| 99久久九九| 蜜臀av一区二区在线免费观看| 久久av资源| 热久久免费视频| 黄色aa久久| 国产欧美激情| 亚洲欧美日韩视频二区| 高清日韩欧美| 欧美一级一区| 亚洲一区二区免费看| 成人国产精品一区二区免费麻豆| 国产精品久久久久久久久久齐齐| 一区在线免费观看| 欧美亚洲tv| 羞羞答答国产精品www一本 | 精品淫伦v久久水蜜桃| 欧美香蕉视频| 亚洲激情五月| 日本成人中文字幕| 日日夜夜免费精品视频| 国产精品一区高清| 日韩成人亚洲| 高清一区二区三区av| 国产精品videossex久久发布| 亚洲tv在线| 视频一区在线视频| 在线国产一区| 一区福利视频| 日韩在线观看一区二区| 欧美成人日韩| 激情综合自拍| 亚洲午夜91| 亚洲涩涩av| 国产精品激情电影| 久久精品毛片| 久久精品导航|