国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

手寫一個CommonJS打包工具(一)

GHOST_349178 / 1230人閱讀

摘要:一原理與環(huán)境不同,瀏覽器中不支持的主要原因是缺少了以下幾個環(huán)境變量換句話說,打包器的原理就是模擬這四個變量的行為。

本文首發(fā)于知乎專欄:
http://zhuanlan.zhihu.com/starkwang

CommonJS 是一個流行的前端模塊化規(guī)范,也是目前 NodeJS 以及其模塊托管倉庫 npm 使用的規(guī)范,但目前暫無瀏覽器支持 CommonJS 。要想讓瀏覽器用上這些模塊,必須轉(zhuǎn)換格式。

這個系列的文章,我們會一步步完成一個基于 CommonJS 的打包工具,類似于一個簡單版的 Browserify 或者 Webpack 。

一、原理

與 NodeJS 環(huán)境不同,瀏覽器中不支持 CommonJS 的主要原因是缺少了以下幾個環(huán)境變量:

module

exports

require

global

換句話說,打包器的原理就是模擬這四個變量的行為。

比如我們有一個index.js文件,依賴了module1module2兩個模塊,并且module1依賴module2

//index.js
var module1 = require("./module1");
var module2 = require("./module2");

module1.foo();
module2.foo();

function hello(){
    console.log("Hello!");
}

module.exports = hello;
//module1.js
var module2 = require(module2);
console.log("initialize module1");

console.log("this is module2.foo() in module1:");
module2.foo();
console.log("
")

module.exports = {
    foo: function(){
        console.log("module1 foo !!!");
    }
};
//module2.js
console.log("initialize module2");
module.exports = {
    foo: function(){
        console.log("module2 foo !!!");
    }
};

把它放入一個匿名函數(shù)內(nèi),通過這個匿名函數(shù)注入 requiremodulesexportglobal變量(我們暫時不實現(xiàn)global)

function(module, exports, require, global){
    var module1 = require("./module1");
    var module2 = require("./module2");

    module1.foo();
    module2.foo();

    function hello(){
        console.log("Hello!");
    }
    
    module.exports = hello;
}

現(xiàn)在我們用一個 modules 對象來存入這些匿名函數(shù):

//modules
{
    "entry": function(module, exports, require, global){
        //index.js
        var module1 = require("./module1");
        var module2 = require("./module2");
        module1.foo();
        module2.foo();
        function hello(){
            console.log("Hello!");
        }
        module.exports = hello;
    },
    "./module1": function(module, exports, require, global){
        var module2 = require("./module2");
        console.log("initialize module1");

        console.log("this is module2.foo() in module1:");
        module2.foo();
        console.log("
")

        module.exports = {
            foo: function(){
                console.log("module1 foo !!!");
            }
        };
    },
    "./module2": function(module, exports, require, global){
        console.log("initialize module2");
        module.exports = {
            foo: function(){
                console.log("module2 foo !!!");
            }
        };
    }
}

下面我們實現(xiàn)一個簡單的 require 函數(shù):

//這個對象用于儲存已導入的模塊
var installedModules = {};

function require(moduleName) {
    //如果模塊已經(jīng)導入,那么直接返回它的exports
    if(installedModules[moduleName]){
        return installedModules[moduleName].exports;
    }
    //模塊初始化
    var module = installedModules[moduleName] = {
        exports: {},
        name: moduleName,
        loaded: false
    };
    //執(zhí)行模塊內(nèi)部的代碼,這里的 modules 變量即為我們在上面寫好的 modules 對象
    modules[moduleName].call(module.exports, module, module.exports,require);
    //模塊導入完成
    module.loaded = true;
    //將模塊的exports返回
    return module.exports;
}

最后只要把我們上面寫好的 modules 對象以立即執(zhí)行函數(shù)的形式傳入這個 require 函數(shù)就可以了,以下是完整的代碼:

(function(modules){
    //這個對象用于儲存已導入的模塊
    var installedModules = {};
    function require(moduleName) {
        //如果模塊已經(jīng)導入,那么直接返回它的exports
        if(installedModules[moduleName]){
            return installedModules[moduleName].exports;
        }
        //模塊初始化
        var module = installedModules[moduleName] = {
            exports: {},
            name: moduleName,
            loaded: false
        };
        //執(zhí)行模塊內(nèi)部的代碼,這里的 modules 變量即為我們在上面寫好的 modules 對象
        modules[moduleName].call(module.exports, module,         module.exports,require);
        //模塊導入完成
        module.loaded = true;
        //將模塊的exports返回
        return module.exports;
    }
    //入口函數(shù)
    return require("entry");
})({
    "entry": function(module, exports, require, global){
        //index.js
        var module1 = require("./module1");
        var module2 = require("./module2");
        module1.foo();
        module2.foo();
        function hello(){
            console.log("Hello!");
        }
        module.exports = hello;
    },
    "./module1": function(module, exports, require, global){
        var module2 = require("./module2");
        console.log("initialize module1");

        console.log("this is module2.foo() in module1:");
        module2.foo();
        console.log("
")

        module.exports = {
            foo: function(){
                console.log("module1 foo !!!");
            }
        };
    },
    "./module2": function(module, exports, require, global){
        console.log("initialize module2");
        module.exports = {
            foo: function(){
                console.log("module2 foo !!!");
            }
        };
    }
});

事實上,我們短短的這幾十行代碼模仿了 Webpack 的部分實現(xiàn)。但我們依然在使用諸如 "./module1" 這樣的字符串作為模塊的唯一識別碼,這是一個明顯的缺陷,存在多層級文件時,這個名稱很容易沖突。

在 Browserify 或 Webpack 這樣的生產(chǎn)級工具里,一般使用數(shù)字作為函數(shù)的唯一識別碼,例如它可能會把(以 Webpack 為例):

var module1 = require("./module1");

編譯成:

var module1 = __webpack_require__(1);
二、小結

我們在這里實現(xiàn)了一個最簡單的 CommonJS 標準的執(zhí)行器,接下來的文章中我們會做以下事情:

1、實現(xiàn) global 變量

2、用 moduleID 替代 moduleName

3、寫一個命令行小工具

4、支持 node_modules 和多層級文件

文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/79155.html

相關文章

  • ES6 系列之模塊加載方案

    摘要:感謝感謝和在推動模塊化發(fā)展方面做出的貢獻。與引用阮一峰老師的標準參考教程規(guī)范加載模塊是同步的,也就是說,只有加載完成,才能執(zhí)行后面的操作。規(guī)定了新的模塊加載方案。與引用阮一峰老師的入門它們有兩個重大差異。 前言 本篇我們重點介紹以下四種模塊加載規(guī)范: AMD CMD CommonJS ES6 模塊 最后再延伸講下 Babel 的編譯和 webpack 的打包原理。 require....

    pinecone 評論0 收藏0
  • 預告:JavaScript模塊全覽

    摘要:之前寫的文章急速全棧教程得到了不錯的閱讀量,霸屏掘金頭條天,點贊過千,閱讀近萬,甚至還有人在評論區(qū)打廣告,可見也是一個小小的生態(tài)了。今天看到的霸屏的,也是講全棧的,見參考文章接下來要寫的是模塊。全局命名污染和命名沖突依賴管理。 之前寫的文章急速Js全棧教程得到了不錯的閱讀量,霸屏掘金頭條3天,點贊過千,閱讀近萬,甚至還有人在評論區(qū)打廣告,可見也是一個小小的生態(tài)了;)。看來和JS全棧有關...

    focusj 評論0 收藏0
  • 2019-我的前端面試題

    摘要:先說下我面試情況,我一共面試了家公司。篇在我面試的眾多公司里,只有同城的面問到相關問題,其他公司壓根沒問。我自己回答的是自己開發(fā)組件面臨的問題。完全不用擔心對方到時候打電話核對的問題。 2019的5月9號,離發(fā)工資還有1天的時候,我的領導親切把我叫到辦公室跟我說:阿郭,我們公司要倒閉了,錢是沒有的啦,為了不耽誤你,你趕緊出去找工作吧。聽到這話,我虎軀一震,這已經(jīng)是第2個月沒工資了。 公...

    iKcamp 評論0 收藏0
  • 我他喵的到底要怎樣才能在生產(chǎn)環(huán)境中用上 ES6 模塊化?

    摘要:因此,你還是需要各種各樣雜七雜八的工具來轉(zhuǎn)換你的代碼噢,我可去你媽的吧,這些東西都是干嘛的我就是想用個模塊化,我到底該用啥子本文正旨在列出幾種可用的在生產(chǎn)環(huán)境中放心使用模塊化的方法,希望能幫到諸位后來者這方面的中文資源實在是忒少了。 原文發(fā)表在我的博客上。最近搗鼓了一下 ES6 的模塊化,分享一些經(jīng)驗 :) Python3 已經(jīng)發(fā)布了九年了,Python 社區(qū)卻還在用 Python 2...

    KaltZK 評論0 收藏0
  • Javascript 打包工具

    摘要:所以,打包工具就出現(xiàn)了,它可以幫助做這些繁瑣的工作。打包工具介紹僅介紹款主流的打包工具,,,,以發(fā)布時間為順序。它定位是模塊打包器,而屬于構建工具。而且在其他的打包工具在處理非網(wǎng)頁文件比如等基本還是需要借助它來實現(xiàn)。 本文當時寫在本地,發(fā)現(xiàn)換電腦很不是方便,在這里記錄下。 前端的打包工具 打包工具可以更好的管理html,css,javascript,使用可以錦上添花,不使用也沒關系...

    Sleepy 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<