談一下_前端模塊化
Module 前端模塊化
前端模塊化從來都是前端人員關注的問題,首先出現的有Common.js方案(CMD)、require.js方案(AMD)等等,以及最後收場的ES6 Module
Common.js
common.js順應了JavaScript在node上的發展,使用的是同步加載的方式,可以用在服務器端。當用在前端上,就會影響頁面的渲染(加載一個模塊就是一次網絡請求對吧),需要選擇異步加載的其它方案
特性:1、模塊可以多次加載,但是只會在第一次加載時運行一次,然後運行結果就被緩存了,以後再加載,就直接讀取緩存結果。要想讓模塊再次運行,必須清除緩存。
2、所有代碼都運行在模塊作用域,不會污染全局作用域
3、CommonJS模塊輸出的是一個值的拷貝。
4、CommonJS模塊是運行時加載。(與ES6Module相比)
AMD方案
模塊化的浪潮吹到了瀏覽器端,但因為Commonjs是同步加載的,就催生出了require.js、sea.js等方案。
講一下require.js(作用:1、防止全局污染,2、異步加載模塊)
<!--先導入require.js,使用defer async就可以不影響頁面渲染(或者直接在body最後導入)--> <script src="js/require.js" defer async="true" ></script>
require.js 用法與分析 不錯的文章
require.js 兼容性強,又易學
ES6 Module
能夠統一模塊化標準的,一定有它無可比擬的長處
1、它是編譯時加載的(這與AMD、CMD以及CommonJS有着明顯不同,ES6Module明顯效率更高)
2、ES6 Module 輸出的是值的引用,不會緩存值
3、ESModule 可以直接導入Commonjs模塊,
module.exports => export default exports.xxx => export xxx import * as xxx from 'xxx' // 全適應
對比CommonJS : CommonJS 加載的是一個對象(即module.exports屬性),該對象只有在腳本運行完才會生成。而 ES6 模塊不是對象,它的對外接口只是一種靜態定義,在代碼靜態解析階段就會生成。ES6 模塊之中,頂層的this指向undefined;CommonJS 模塊的頂層this指向當前模塊
缺點:由於是編譯時加載,所以無論怎樣,對應的運行時不支持,就無法時候用。通常的做法是轉化為其他方案:目前瀏覽器對ES6 Module兼容還不太好,我們平時在webpack中使用的
export
/import
,會被打包為exports
/require
。最終文件中的模塊實現是基於webpack自己實現的webpack_require(es5代碼)
UMD模塊
其實就是通用模塊寫法,集合了CommonJS、AMD和CMD,以及可以直接引用的global對象
(function(root, factory) { // 全局變量 module,識別方案 if (typeof module === 'object' && typeof module.exports === 'object') { console.log('是commonjs模塊規範,nodejs環境') var depModule = require('./umd-module-depended') // 模塊自身的依賴 。。。 module.exports = factory(depModule); } else if (typeof define === 'function' && define.amd) { console.log('是AMD模塊規範,如require.js') // 模塊自身的依賴 。。。 define(['depModule'], factory) } else if (typeof define === 'function' && define.cmd) { console.log('是CMD模塊規範,如sea.js') define(function(require, exports, module) { var depModule = require('depModule') // 模塊自身的依賴 。。。 module.exports = factory(depModule) }) } else { console.log('沒有模塊環境,直接掛載在全局對象上') // 模塊自身的依賴 。。。 root.umdModule = factory(root.depModule); } }(this, function(depModule) { console.log('我調用了依賴模塊', depModule) // ...省略了一些代碼,去代碼倉庫看吧 return { name: '我自己是一個umd模塊' } }))