99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

編寫(xiě)自己的模塊加載器

2020-04-26 10:29 更新

自己實(shí)現(xiàn)一個(gè)模塊加載器——bodule.js

shut up, show me the code!

要想真正地了解一個(gè)加載器是如何工作的,就是自己實(shí)現(xiàn)一個(gè)!讓我們來(lái)一步一步地實(shí)現(xiàn)一個(gè)名為bodule.js的模塊加載器。

約定

一個(gè)模塊系統(tǒng),必然有一些約定,下面是bodule.js的規(guī)范。

模塊

bodule.js的模塊由以下幾個(gè)概念組成:

  • url,一個(gè)url地址對(duì)應(yīng)一個(gè)模塊;
  • meta module:如下形式為一個(gè)meta module:

define(id, dependancies?, factory)

id必須為完整的url,dependancies如果沒(méi)有依賴,則可以省略,factory包含兩種形式:

Function:function(require, [exports,] [module]):

非Function:直接作為該meta模塊的exports。

define('http://bodule.org/island205/venus/1.0.0/venus', ['./vango'], function (require, exports, module) {
  //CommonJS
})

// or

define('http://bodule.org/island205/venus/1.0.0/conststring', 'bodule.js')

// even or

define('http://bodule.org/island205/venus/1.0.0/undefined', undefined)

dependancies中的字符串以及CommonJS中的require的參數(shù),必須為url、相對(duì)路徑或頂級(jí)路徑的解析依賴于前面的id。

  • 一個(gè)模塊文件包含一個(gè)或多個(gè)meta module,但是,在該模塊文件中,必須包含一個(gè)該模塊文件url作為id的meta module,例如:

http://bodule.org/island205/venus/1.0.0/venus.js 對(duì)應(yīng)的模塊文件內(nèi)容為:

define('http://bodule.org/island205/venus/1.0.0/venus', ['./vango'], function (require, exports, module) {
  //CommonJS for venus
})

define('http://bodule.org/venus/1.0.0/vango', [], function (require, exports, module) {
  //CommonJS for vango
})

該模塊文件包含兩個(gè)meta module,而第一個(gè)是必須的。但這兩個(gè)meta模塊的順序不做要求。

簡(jiǎn)化

為了簡(jiǎn)化代碼,針對(duì)

define('http://bodule.org/island205/venus/1.0.0/venus', ['./vango'], function (require, exports, module) {
  //CommonJS for venus
})

這樣的代碼我們可以將其簡(jiǎn)化為:

define('./venus/1.0.0/venus', ['./vango'], function (require, exports, module) {
  //CommonJS for venus
})

或者:

define('/venus/1.0.0/venus', ['./vango'], function (require, exports, module) {
  //CommonJS for venus
})

這樣的形式,然相對(duì)路徑或者頂級(jí)路徑必須要由一個(gè)絕對(duì)路徑可參照,在bodule.js中,這個(gè)絕對(duì)路徑來(lái)自于當(dāng)前頁(yè)面的url地址,或者使用bodule.package進(jìn)行配置。

bodule cloud

在node中,可以使用require('underscore')來(lái)引用node_modules中的模塊,作為bodule.js的目標(biāo),將commonjs橋接到瀏覽器端來(lái)使用,所以允許使用類似的寫(xiě)法,這種模塊我們把它稱作bodule模塊,resovle后映射到http://bodule.org/underscore/stable,bodule.js會(huì)在bodule.org上提供一個(gè)云服務(wù),來(lái)支持你從這里加載這些bodule模塊。

如果你想使用自己的bodule服務(wù)器,可以使用bodule.package來(lái)配置boduleServer。

npm

npm非常流行,bodule.js將其作為模塊的源。我們采取與npm包一致的策略。典型的npm的package.json為(以u(píng)nderscore為例):

{
  "name"          : "underscore",
  "description"   : "JavaScript's functional programming helper library.",
  "homepage"      : "http://underscorejs.org",
  "keywords"      : ["util", "functional", "server", "client", "browser"],
  "author"        : "Jeremy Ashkenas <jeremy@documentcloud.org>",
  "repository"    : {"type": "git", "url": "git://github.com/jashkenas/underscore.git"},
  "main"          : "underscore.js",
  "version"       : "1.5.1",
  "devDependencies": {
    "phantomjs": "1.9.0-1"
  },
  "scripts": {
    "test": "phantomjs test/vendor/runner.js test/index.html?noglobals=true"
  },
  "licenses": [
    {
      "type": "MIT",
      "url": "https://raw.github.com/jashkenas/underscore/master/LICENSE"
    }
  ],
  "files"         : ["underscore.js", "LICENSE"]
}

bodule.js將會(huì)使用工具將其轉(zhuǎn)化為bodule模塊,最終會(huì)以http://bodule.org/underscore/1.5.1這樣的地址地提供出來(lái)。注意:該地址會(huì)根據(jù)package.json中的main,變?yōu)?code>http://bodule.org/underscore/1.5.1/underscore。

bodule.js的API

.use

.use(id)

在頁(yè)面中使用一個(gè)模塊,相當(dāng)于node id.js。

.use(dependancies, factory)

在頁(yè)面上定義一個(gè)即時(shí)的模塊,該模塊依賴于dependancies,并use該模塊。等價(jià)于:

define('a-random-id', dependencies, factory)
Bodule.use('a-random-id')

.use比較簡(jiǎn)單的例子,simplest.html

<script type="text/javascript">
    Bodule.use('./a.js')
    Bodule.use('/b.js')
    Bodule.use(['./c.js', './d'], function (require, exports, module) {
        var c = require('./c.js')
        var d = require('./d')
        console.log(c + d)
    })
    Bodule.use(['./e'], function (require) {
        var e = require('./e')
        console.log(e)
    })
</script>

define

define(id, dependencies, factory)

定義一個(gè)meta module;

define(id, anythingNotFunction)

定義一個(gè)meta module,該模塊的exports即為anythingNotFunction;

幾個(gè)例子:d.jse.js,backbone.js

.package(config)

配置模塊和bodule模塊的位置,還可以配置依賴的bodule模塊的版本號(hào)。

Bodule.package({
  cwd: 'http://bodule.org:8080/',
  path: '/bodule.org/',
  bodule_modules:{
    cwd: 'http://bodule.org:3000/',
    path: '/bower_components/',
    dependencies: {
      'backbone': '1.0.0'
    }
  }
})

完整的例子可以參考bodule.org.html。

讓我們開(kāi)始吧!

coffeescript

coffeescript是一門非常有趣的語(yǔ)言,敲起代碼來(lái)很舒服,不會(huì)被JavaScript各種繁瑣的細(xì)節(jié)所煩擾。所以我打算使用它來(lái)實(shí)現(xiàn)bodule.js。訪問(wèn)[coffeescript.org],上面有簡(jiǎn)潔文檔,如果你熟悉JavaScript,我相信你能很快掌握CoffeeScript的。

commonjs運(yùn)行時(shí)

從bodule的規(guī)范中,可以看出,它其實(shí)commonjs,或者說(shuō)是commonjs wrapping的一個(gè)實(shí)現(xiàn)。因此,我們將直接使用commonjs的方式來(lái)組織我們的代碼,你會(huì)發(fā)現(xiàn),這樣的代碼非常清晰易讀。

# This is a **private** CommonJS runtime for `bodule.js`.

# `__modules` for store private module like `util`,`path`, and so on.
modules = {}

# `__require` is used for getting module's API: `exports` property.
require = (id)->
    module = modules[id]
    module.exports or module.exports = use [], module.factory

# Define a module, save module in `__modules`. use `id` to refer them.
define = (id, deps, factory)->
    modules[id] =
        id: id
        deps: deps
        factory:factory

# `__use` to start a CommonJS runtime, or get a module's exports.
use = (deps, factory)->
    module = {}
    exports = module.exports = {}

    # In factory `call`, `this` is global
    factory require, exports, module
    module.exports

上面這段代碼是commonjs規(guī)范一種精簡(jiǎn)的表達(dá),出自node項(xiàng)目中的module.js。module.js比這復(fù)雜多了,包含了多native module、讀取、執(zhí)行module文件、以及支持多種格式的module的事情。而我們上面這段代碼就是commonjs最精簡(jiǎn)的表達(dá),有了它,我們就可以使用common.js的方式來(lái)組織代碼了。

注意,代碼中的deps變量完全就是無(wú)用的,只是我覺(jué)得這樣寫(xiě)的話,似乎更清晰一點(diǎn)。

define 'add', [], (require, exports, module)->
    module.exports = (a, b)->
        a + b

define 'addTwice', ['add'], (require, exports, module)->
    add = require 'add'
    exports.addTwice = (a, b)->
        add add(a, b), b

use ['addTwice'], (require, exports, module)->
    addTwice = require 'addTwice'
    cosnole.log "#{2} + #{3} + #{3} = #{addTwice 2, 3}"

上面的代碼展示了如何使用這個(gè)commonjs運(yùn)行時(shí),很簡(jiǎn)單,有木有?

很簡(jiǎn)陋?確實(shí),我們只是用用它來(lái)組織代碼,最終實(shí)現(xiàn)bodule.js這個(gè)復(fù)雜的commonjs運(yùn)行時(shí)。

bodule API

我們改從何入手編寫(xiě)一個(gè)加載器呢,既然已經(jīng)有了規(guī)范和接口,那我們從接口寫(xiě)起吧。

define 'bodule', [], (require, exports, module)->
    Bodule = 
        use: (deps, factory)->
        define: (id, deps, factory)->
        package: (conf)->

    module.exports = Bodule

use ['bodule'], (require, exports, module)->

    Bodule = require 'bodule'
    window.Bodule = Bodule
    window.define = ->
      Bodule.define.apply Bodule, arguments


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)