澳门新莆京手机网站-新蒲京娱乐场 > 联系我们 > webpack Code Splitting浅析

webpack Code Splitting浅析

图片 1

图片 2

参照他事他说加以考察来源:

畅所欲言

Code Splitting是webpack的三个主要特点,他允许你将代码打包生成七个bundle。对多页应用来讲,它是必需的,因为必定要陈设多少个入口生成八个bundle;对于单页应用来讲,假使只打包成贰个bundle或然体量非常大,招致无可奈何利用浏览器并行下载的力量,且白屏时间长,也会促成下载很多恐怕用不到的代码,每回上线客商都得下载全体代码,Code Splitting能够将代码分割,达成按需加载或相互加载七个bundle,可应用并发下载技能,减少第叁次访谈白屏时间,能够只上线供给的公文。

在平常支付中我们平常会用到Webpack这一个时下最风靡的前端打包工具。它包裹开采代码,输出能在种种浏览器运转的代码,提高了支出至发表进程的功效。

前面包车型客车代码:

1.打包单一模块

webpack.config.js

module.exports = {
    entry:"./chunk1.js",
    output: {
        path: __dirname + '/dist',
        filename: '[name].js'
    },
};

chunk1.js

var chunk1=1;
exports.chunk1=chunk1;

包裹后,main.js(webpack生成的生龙活虎部分注明已经去掉卡塔尔(قطر‎

 (function(modules) { // webpackBootstrap
    // The module cache
    var installedModules = {};
    // The require function
    function __webpack_require__(moduleId) {
        // Check if module is in cache
        if(installedModules[moduleId])
            return installedModules[moduleId].exports;
        // Create a new module (and put it into the cache)
        var module = installedModules[moduleId] = {
            exports: {},
            id: moduleId,
            loaded: false
        };
        // Execute the module function
        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
        // Flag the module as loaded
        module.loaded = true;
        // Return the exports of the module
        return module.exports;
    }


    // expose the modules object (__webpack_modules__)
    __webpack_require__.m = modules;
    // expose the module cache
    __webpack_require__.c = installedModules;
    // __webpack_public_path__
    __webpack_require__.p = "";
    // Load entry module and return exports
    return __webpack_require__(0);
 })([function(module, exports) {
    var chunk1=1;
    exports.chunk1=chunk1;
}]);

那实际上正是一个马上实践函数,简化一下就是:

(function(module){})([function(){},function(){}]);

OK,看一下自运行的无名氏函数里面干了何等:

function(modules) { // webpackBootstrap
    // modules就是一个数组,元素就是一个个函数体,就是我们声明的模块
    var installedModules = {};
    // The require function
    function __webpack_require__(moduleId) {
        ...
    }
    // expose the modules object (__webpack_modules__)
    __webpack_require__.m = modules;
    // expose the module cache
    __webpack_require__.c = installedModules;
    // __webpack_public_path__
    __webpack_require__.p = "";
    // Load entry module and return exports
    return __webpack_require__(0);
 }

任何函数里就宣称了叁个变量installedModules 和函数__webpack_require__,并在函数上增添了二个m,c,p属性,m属性保存的是传播的模块数组,c属性保存的是installedModules变量,P是二个空字符串。最终推行__webpack_require__函数,参数为零,并将其进行结果重临。上面看一下__webpack_require__干了怎么着:

function __webpack_require__(moduleId) {
        //moduleId就是调用是传入的0
        // installedModules[0]是undefined,继续往下
        if(installedModules[moduleId])
            return installedModules[moduleId].exports;
        // module就是{exports: {},id: 0,loaded: false}
        var module = installedModules[moduleId] = {
            exports: {},
            id: moduleId,
            loaded: false
        };
        // 下面接着分析这个
        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
        // 表明模块已经载入
        module.loaded = true;
        // 返回module.exports(注意modules[moduleId].call的时候module.exports会被修改)
        return module.exports;
    }

紧接着看一下modules[moduleId].call(module.exports, module, module.exports, webpack_requireState of Qatar,其实正是

modules[moduleId].call({}, module, module.exports, __webpack_require__)

对call不打听当然也得以认为是这么(不过并非杰出,call能承保当模块中动用this的时候,this是指向module.exports的卡塔尔:

function  a(module, exports) {
    var chunk1=1;
    exports.chunk1=chunk1;
}
a(module, exports,__webpack_require__);

传入的module就是{exports: {},id: 0,loaded: false},exports就是{},__webpack_require__正是宣称的__webpack_require__函数(传入这些函数有怎么样用吗,首节将会介绍卡塔尔;
运作后module.exports就是{chunk1:1}。所以当大家使用chunk1以此模块的时候(譬喻var chunk1=require("chunk1"State of Qatar,拿到的正是二个对象{chunk1:1})。假使模块里未有exports.chunk1=chunk1可能module.exports=chunk1到手的就是三个空对象{}

三种Code Splitting方式

大家明白生龙活虎份Webpack配置文件根本包蕴入口、输出文件、格局、加载器、插件等多少个部分。但假设只要求组织JS 文件的话,钦赐入口和出口文件路径就可以完毕贰个精密项目的卷入。下边大家来通过二个简约的类型来看一下Webpack是何许运维的。

打包AMD和commonJS模块

webpack暗许扶植那三种模块的卷入

amd.js

define('amd',function(){
    return {
       data:'content from amd module'
    }
});

commonJS.js

module.exports = {
    data:'content from commonjs module'
}

配备文件

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  }
};

入口文件

var amd = require('./js-module/amd');
var com = require('./js-module/commomJS');

console.log(amd);
console.log(com);

运作结果:可平常输出那四个模块,网络诉求唯有一个bundle.js,可知那七个模块的剧情都打包进了二个js文件中

图片 3

2.利用模块

地点大家曾经解析了webpack是怎么打包二个模块的(入口文件就是二个模块),今后我们来看一下接收二个模块,然后选取模块的文件作为入口文件
webpack.config.js

module.exports = {
    entry:"./main.js",
    output: {
        path: __dirname + '/dist',
        filename: '[name].js'
    }
};

main.js

var chunk1=require("./chunk1");
console.log(chunk1);

打包后

(function (modules) { // webpackBootstrap
    // The module cache
    var installedModules = {};
    // The require function
    function __webpack_require__(moduleId) {
        // Check if module is in cache
        if (installedModules[moduleId])
            return installedModules[moduleId].exports;
        // Create a new module (and put it into the cache)
        var module = installedModules[moduleId] = {
            exports: {},
            id: moduleId,
            loaded: false
        };
        // Execute the module function
        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
        // Flag the module as loaded
        module.loaded = true;
        // Return the exports of the module
        return module.exports;
    }
    // expose the modules object (__webpack_modules__)
    __webpack_require__.m = modules;
    // expose the module cache
    __webpack_require__.c = installedModules;
    // __webpack_public_path__
    __webpack_require__.p = "";
    // Load entry module and return exports
    return __webpack_require__(0);
})([function (module, exports, __webpack_require__) {
    var chunk1=__webpack_require__(1);
    console.log(chunk1);
}, function (module, exports) {
    var chunk1 = 1;
    exports.chunk1 = chunk1;
}]);

不风姿洒脱致的地点正是自实行函数的参数由

[function(module, exports) { var chunk1=1; exports.chunk1=chunk1;}]

变为

[function (module, exports, __webpack_require__) {
    var chunk1=__webpack_require__(1);
    console.log(chunk1);
}, function (module, exports) {
    var chunk1 = 1;
    exports.chunk1 = chunk1;
}]

事实上正是多了一个main模块,但是那一个模块未有导出项,并且以此模块依赖于chunk1模块。所以当运营__webpack_require__(0State of Qatar的时候,main模块缓存到installedModules[0]上,modules[0].call(也正是调用main模块卡塔尔(قطر‎的时候,chunk1被缓存到installedModules[1]上,况兼导出对象{chunk1:1}给模块main使用

webpack提供了二种艺术来切割代码,分别是:

一块加载

chunk(这里的知晓偏颇)

entry chunk :包含了 webpackJsonp、__webpack_require__ 的定义 ,__webpack_require__.e用于以promise格局加载重视后实行组件的代码(入口文件的代码),如:

 图片 4

normal chunk:包括了进口文件所需的模块的代码,里面调用了webpackJsonp来注册信任,如:

图片 5

 

3.重复使用模块

webpack.config.js

module.exports = {
    entry:"./main.js",
    output: {
        path: __dirname + '/dist',
        filename: '[name].js'
    }
};

main.js

var chunk1=require("./chunk1");
var chunk2=require(".chunlk2");
console.log(chunk1);
console.log(chunk2);

chunk1.js

var chunk2=require("./chunk2");
var chunk1=1;
exports.chunk1=chunk1;

chunk2.js

var chunk2=1;
exports.chunk2=chunk2;

打包后

(function (modules) { // webpackBootstrap
    // The module cache
    var installedModules = {};
    // The require function
    function __webpack_require__(moduleId) {
        // Check if module is in cache
        if (installedModules[moduleId])
            return installedModules[moduleId].exports;
        // Create a new module (and put it into the cache)
        var module = installedModules[moduleId] = {
            exports: {},
            id: moduleId,
            loaded: false
        };
        // Execute the module function
        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
        // Flag the module as loaded
        module.loaded = true;
        // Return the exports of the module
        return module.exports;
    }
    // expose the modules object (__webpack_modules__)
    __webpack_require__.m = modules;
    // expose the module cache
    __webpack_require__.c = installedModules;
    // __webpack_public_path__
    __webpack_require__.p = "";
    // Load entry module and return exports
    return __webpack_require__(0);
})([function (module, exports, __webpack_require__) {

    var chunk1 = __webpack_require__(1);
    var chunk2 = __webpack_require__(2);
    console.log(chunk1);
    console.log(chunk2);
}, function (module, exports, __webpack_require__) {

    __webpack_require__(2);
    var chunk1 = 1;
    exports.chunk1 = chunk1;
}, function (module, exports) {

    var chunk2 = 1;
    exports.chunk2 = chunk2;
}]);

轻松察觉,当须求重复使用模块的时候,缓存变量installedModules 就起效果了

多entry形式公共提取动态加载本文将简介多entry格局和公共提取方法,珍视介绍的是动态加载。这两种格局能够依据须求整合起来使用。这里是合英文档,汉语英语多entry形式

本文使用 webpack ^4.30.0 作示例.为了越来越好地洞察产出的文件,我们将方式设置为 development 关闭代码压缩,再展开 source-map 扶植原始源代码调节和测验。除外。大家还简要的写了三个插件MyPlugin来去除源码中的注释。

多组件代码收取

假诺四个构件中有同样的代码,每种组件都都像上个例子那样完全打包豆蔻梢头份,那即使减弱了网络访谈次数,但或然变成无谓的流量消耗,因为多个模块是能够共用代码的

全局JS:

  把要复用的局地抽出到三个外加的大局js中,然后手动引进那几个js,别的零件中一直利用这几个js就能够,如:

module.exports = {
  entry: {
    bundle1:'./main1.js',
    bundle2:'./main2.js'
  },
  output: {
    filename: '[name].js'
  }
};

// main1.js
console.log('组件1获取数据' + data);

//main2.js
console.log('组件2获取数据' + data);

//commonData.js:
var data = 'this is common data';

index.html:
<html>
<script src="commonData.js"></script>
  <body>
    <script type="text/javascript" src="bundle1.js"></script>
    <script type="text/javascript" src="bundle2.js"></script>
  </body>
</html>

有未有主意不全局,并且能够使两个零构件共用吧?那个供给可独一预计出只能接收js模块,不过如上测量检验中,开掘采用模块的话,会完全打包进去,以致于无法贯彻代码复用。别的webpack提供贰个require.ensure能够兑现模块的不打包,从而到达复用的指标

4.多个打包入口

甭管是纯粹模块照旧再次模块,和上述三种同等

这种措施就是钦赐八个打包入口,从进口开头将有所信任打包进二个bundle,种种入口打包成多个bundle。此措施特别相符多页应用,大家得以每种页面钦点叁个进口,进而各种页面生成三个js。此方法的为主配置代码如下:

新建src/index.js

require.ensure

对以上代码进行改建:

// commonData.js
exports.data = 'this is common data';

// mian1.js
require.ensure(['./commonData'], function(require) {
    var m = require('./commonData');
    console.log('组件1获取数据' + m.data);
});

//main2.js
require.ensure(['./commonData'], function(require) {
    var m = require('./commonData');
    console.log('组件2获取数据' + m.data);
});

//index.html
<html>
  <body>
    <script type="text/javascript" src="bundle1.js"></script>
    <script type="text/javascript" src="bundle2.js"></script>
  </body>
</html>

运作结果同样。只可是此次达成了代码复用:

图片 6

  以上效果的其它意气风发种完成格局,是应用 bundle-loader ,语法分裂但作用等同就不再比方了

源码深入分析:

  bundle1、2.js中隐含了webpackJsonp、__webpack_require__以至那么些函数对象的一形形色色措施,以至对应进口文件的推行代码

  __webpack_require__.e 函数:用于依照模块id来得到模块,再次来到一个promise。往header上写叁个script标签,这一个标签onload的时候,相当于这么些新扩张script中的webpackJsonp函数实施完了,就触发promise的resolve方法(实践了对应进口文件的代码)

抵补测量检验:

  模块1和2ensure了八个文书,模块3ensure了另多个文书。则会额外生成0.js和1.js。约等于说几个公文被ensure,就能额外生成多少个文件(名字从0开头思谋),重复ensure不会额外生成文件,而是复用在此之前的

  与ensure具有形似效果的是import。这两个都用来动态代码分割,假诺利用import的话须要在意promise的相称,能够行使响应的垫片库来拍卖,轻巧的import使用,能够参照旅馆中的demo5

5.入口参数为数组

webpack.config.js

module.exports = {
    entry:['./main.js','./main1.js'],
    output: {
        path: __dirname + '/dist',
        filename: '[name].js'
    }
};

打包后

[
/* 0 */
/***/ function(module, exports, __webpack_require__) {
    __webpack_require__(1);
    module.exports = __webpack_require__(3);
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
    var chunk1=__webpack_require__(2);
    console.log(chunk1);
/***/ },
/* 2 */
/***/ function(module, exports) {
    var chunk1=1;
    exports.chunk1=chunk1;
/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {
    var chunk1=__webpack_require__(2);
/***/ }
/******/ ]

此地只截取自实行无名氏函数的参数,因为别的代码与以前同样。能够看出1便是main默模块,2正是chunk1模块,3正是mian1模块,0的效应正是运维模块mian,mian1,然后将main1模块导出(main1中平素不导出项,所以到导出{}),总计一下:入口参数是字符串不管是多入口还是单入口,最终都会将进口模块的导出项导出,未有导出项就导出{},而进口参数是数组,就能够将最后一个模块导出(webpackg官方网站有证实)

const path = require('path');module.exports = { mode: 'development', entry: { page1: './src/page1.js', page2: './src/page2.js' }, output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist') }};
console.log('Hello webpack!');

CommonsChunkPlugin

代码收取还足以用这么些插件来得以完毕,测验代码如下:

抽取信赖

// 配置文件
var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
module.exports = {
  entry: {
    bundle1: './main1.js',
    bundle2: './main2.js'
  },
  output: {
    filename: '[name].js'
  },
  plugins: [
    new CommonsChunkPlugin('chunkInit')
  ]
}

// main1.js
require('./com');
require('./comm2');

var data = 'this is differenet1 ';

//main2.js
require('./com');
require('./comm2');

var data = 'this is differenet2 ';

//com.js
exports.data = '这里存放的是公共代码'

//comm2.js
exports.data = '这里存放的是公共代码2'

//index.html
<html>
  <body>
    <script src="chunkInit.js"></script>
    <script src="bundle1.js"></script>
    <script src="bundle2.js"></script>
  </body>
</html>

运营结果:

  会生成叁个chunkinit.js文件(那些名字是大家在new 插件的时候内定的),那些文件中包括了webpackJsonp、__webpack_require__以致这么些函数对象的生机勃勃雨后春笋措施以致被信任的模块的代码,也正是说require进来的事物并非动态加载的,并且一直写到了那么些chunkinit.js文件中。而八个bundle文件调用了webpackjsonP函数,里面包车型大巴回调函数中施行了对应进口文件的代码

  可以见到,那个插件达成的魔法和require.ensure都以代码抽出,但两个本质上差异:

零部件的起头化定义:包涵了webpackJsonp、__webpack_require__以致那么些函数对象的生机勃勃层层措施

ensure:动态加载代码,收取的是被重视的代码,多少个构件的初始化定义也仍旧再一次的

插件:非动态加载代码,收取的是五个零器件的初叶化定义到一个文本中,况兼此中写好了被重视的模块代码

  以上八个零零件都引用了五个相通的依附,所以那五个依附都放到了chuninit中。测量试验开采,多少个零器件中雷同的依据会被安置chunkinti中,而差距的部分则停放对应的bundle中,也正是说bundle中或许还要现身现身被重视的模块代码以至相应的入口文件的代码

6.使用CommonsChunkPlugin插件

webpack.config.js

var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
module.exports = {
    entry: {
        main: './main.js',
        main1: './main1.js',
    },
    output: {
        path: __dirname + '/dist',
        filename: '[name].js'
    },
    plugins: [
        new CommonsChunkPlugin({
        name: "common"
        })
    ]
};

main mian1中都require了chunk1,所以chunk1会被打包到common。
打包后,common.js

(function (modules) { // webpackBootstrap
    // install a JSONP callback for chunk loading
    var parentJsonpFunction = window["webpackJsonp"];
    window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules) {
        // add "moreModules" to the modules object,
        // then flag all "chunkIds" as loaded and fire callback
        var moduleId, chunkId, i = 0, callbacks = [];
        for (; i < chunkIds.length; i++) {
            chunkId = chunkIds[i];
            if (installedChunks[chunkId])
                callbacks.push.apply(callbacks, installedChunks[chunkId]);
            installedChunks[chunkId] = 0;
        }
        for (moduleId in moreModules) {
            modules[moduleId] = moreModules[moduleId];
        }
        if (parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules);
        while (callbacks.length)
            callbacks.shift().call(null, __webpack_require__);
        if (moreModules[0]) {
            installedModules[0] = 0;
            return __webpack_require__(0);
        }
    };
    // The module cache
    var installedModules = {};
    // object to store loaded and loading chunks
    // "0" means "already loaded"
    // Array means "loading", array contains callbacks
    var installedChunks = {
        2: 0
    };
    // The require function
    function __webpack_require__(moduleId) {
        // Check if module is in cache
        if (installedModules[moduleId])
            return installedModules[moduleId].exports;
        // Create a new module (and put it into the cache)
        var module = installedModules[moduleId] = {
            exports: {},
            id: moduleId,
            loaded: false
        };
        // Execute the module function
        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
        // Flag the module as loaded
        module.loaded = true;
        // Return the exports of the module
        return module.exports;
    }
    // This file contains only the entry chunk.
    // The chunk loading function for additional chunks
    __webpack_require__.e = function requireEnsure(chunkId, callback) {
        // "0" is the signal for "already loaded"
        if (installedChunks[chunkId] === 0)
            return callback.call(null, __webpack_require__);
        // an array means "currently loading".
        if (installedChunks[chunkId] !== undefined) {
            installedChunks[chunkId].push(callback);
        } else {
            // start chunk loading
            installedChunks[chunkId] = [callback];
            var head = document.getElementsByTagName('head')[0];
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.charset = 'utf-8';
            script.async = true;
            script.src = __webpack_require__.p + "" + chunkId + "." + ({ "0": "main", "1": "main1" }[chunkId] || chunkId) + ".js";
            head.appendChild(script);
        }
    };
    // expose the modules object (__webpack_modules__)
    __webpack_require__.m = modules;
    // expose the module cache
    __webpack_require__.c = installedModules;
    // __webpack_public_path__
    __webpack_require__.p = "";
})([, function (module, exports) {

    var chunk1 = 1;
    exports.chunk1 = chunk1;

}]);

main.js

webpackJsonp([0],[function(module, exports, __webpack_require__) {

    var chunk1=__webpack_require__(1);
    console.log(chunk1);
 }]);

main1.js

webpackJsonp([1],[function(module, exports, __webpack_require__) {
    var chunk1=__webpack_require__(1);
    console.log(chunk1);
}]);

与事前相比较,多了webpackJsonp函数,立时施行的无名氏函数未有及时调用__webpack_require__(0)。看一下webpackJsonp:

var parentJsonpFunction = window["webpackJsonp"];
    window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules) {
        //moreModules为独立chunk代码,chunkIds标记独立chunk唯一性避免按需加载时重复加载
        //以main.js中代码为例,chunkIds为[0],moreModules为
        //[function(module, exports, __webpack_require__) {
        //  var chunk1=__webpack_require__(1);
        //  console.log(chunk1);
        //}]
        var moduleId, chunkId, i = 0, callbacks = [];
        for (; i < chunkIds.length; i++) {
            chunkId = chunkIds[i];//chunkId=0
            if (installedChunks[chunkId])
                callbacks.push.apply(callbacks,installedChunks[chunkId]);//0 push入callbacks(使用requireEnsure不再是0)
            //赋值为0表明chunk已经loaded
            installedChunks[chunkId] = 0;
        }
        for (moduleId in moreModules) {
            //modules[0]会被覆盖
            modules[moduleId] = moreModules[moduleId];
        }
        //按当前情况parentJsonpFunction一直未undefined
        if (parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules);
        //按当前情况callbacks=[]
        while (callbacks.length)
            callbacks.shift().call(null, __webpack_require__);
        if (moreModules[0]) {
            installedModules[0] = 0;
            return __webpack_require__(0);
        }
    };
    // 缓存模块,通过闭包引用(window["webpackJsonp"]可以访问到)
    var installedModules = {};
    //2为公共chunck唯一ID,0表示已经loaded
    var installedChunks = {
        2: 0
    };
    // The require function
    function __webpack_require__(moduleId) {
        // Check if module is in cache
        if (installedModules[moduleId])
            return installedModules[moduleId].exports;
        // Create a new module (and put it into the cache)
        var module = installedModules[moduleId] = {
            exports: {},
            id: moduleId,
            loaded: false
        };
        // Execute the module function
        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
        // Flag the module as loaded
        module.loaded = true;
        // Return the exports of the module
        return module.exports;
    }
    //按需加载
    __webpack_require__.e = function requireEnsure(chunkId, callback) {
        // "0" is the signal for "already loaded"
        if (installedChunks[chunkId] === 0)
            return callback.call(null, __webpack_require__);
        // an array means "currently loading".
        if (installedChunks[chunkId] !== undefined) {
            installedChunks[chunkId].push(callback);
        } else {
            // start chunk loading
            installedChunks[chunkId] = [callback];
            var head = document.getElementsByTagName('head')[0];
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.charset = 'utf-8';
            script.async = true;
            script.src = __webpack_require__.p + "" + chunkId + "." + ({ "0": "main", "1": "main1" }[chunkId] || chunkId) + ".js";
            head.appendChild(script);
        }
    };

近似看不出什么。。。,改正一下
webpack.config.js

var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
module.exports = {
    entry: {
        main: './main.js',
        main1: './main1.js',
        chunk1:["./chunk1"]
    },
    output: {
        path: __dirname + '/dist2',
        filename: '[name].js'
    },
    plugins: [
        new CommonsChunkPlugin({
        name: ["chunk1"],
        filename:"common.js",
        minChunks:3,
        })
    ]
};

main,main1都分别require chunk1,chunk2,然后将chunk1打包到集体模块(minChunks:3,chunk2不会被打包到国有模块)。自运维无名氏函数最终多了

   return __webpack_require__(0);

则installedModules[0]为已经loaded,看common.js,installedModules[1]也会loaded。
main.js

webpackJsonp([1], [function (module, exports, __webpack_require__) {

    var chunk1 = __webpack_require__(1);
    var chunk2 = __webpack_require__(2);
    exports.a = 1;
    console.log(chunk1);
}, , function (module, exports) {
    var chunk2 = 1;
    exports.chunk2 = chunk2;

}
]);

main1.js

webpackJsonp([2], [function (module, exports, __webpack_require__) {

    var chunk1 = __webpack_require__(1);
    var chunk2 = __webpack_require__(2);
    exports.a = 1;
    console.log(chunk1);
}, , function (module, exports) {
    var chunk2 = 1;
    exports.chunk2 = chunk2;
}
]);

common.js modules:

[function (module, exports, __webpack_require__) {

    module.exports = __webpack_require__(1);
}, function (module, exports) {

    var chunk1 = 1;
    exports.chunk1 = chunk1;
}]

以main.js的代码为例,调用webpackJsonp,传入的参数chunkIds为[1],moreModules为

[function (module, exports, __webpack_require__) {

    var chunk1 = __webpack_require__(1);
    var chunk2 = __webpack_require__(2);
    exports.a = 1;
    console.log(chunk1);
}, , function (module, exports) {
    var chunk2 = 1;
    exports.chunk2 = chunk2;

}]

var moduleId, chunkId, i = 0, callbacks = [];
        for (; i < chunkIds.length; i++) {
            chunkId = chunkIds[i];//1
            //false,赋值为0后还是false
            if (installedChunks[chunkId])
                callbacks.push.apply(callbacks, installedChunks[chunkId]);
            installedChunks[chunkId] = 0;
        }
        //三个模块
        for (moduleId in moreModules) {
            //moduleId:0,1,2  moreModules[1]为空模块,自执行函数的参数(公共模块)会被覆盖,但是参数中的相应模块已经loaded并且缓存
            modules[moduleId] = moreModules[moduleId];
        }
        if (parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules);
        while (callbacks.length)
            callbacks.shift().call(null, __webpack_require__);
        if (moreModules[0]) {
            //installedModules[0]会重新load,但是load的是moreModules[0],因为modules[0]已经被覆盖,moreModules[0]依赖于
            //modules[1]、modules[2],modules[1]已经loaded
            installedModules[0] = 0;
            return __webpack_require__(0);
        }

再看上面包车型客车意况:
common.js 自实行函数参数(公共模块)(未有return webpack_require(0))

[,function(module, exports, __webpack_require__) {

    var chunk1=1;
    var chunk2=__webpack_require__(2);
    exports.chunk1=chunk1;
},function(module, exports) {

    var chunk2=1;
    exports.chunk2=chunk2;
}]

main.js

webpackJsonp([0],[
/* 0 */
/***/ function(module, exports, __webpack_require__) {

    var chunk1=__webpack_require__(1);
    var chunk2=__webpack_require__(2);
    exports.a=1;
    console.log(chunk1);
    //main
/***/ }
]);

以main调用深入分析

         var moduleId, chunkId, i = 0, callbacks = [];
        for(;i < chunkIds.length; i++) {
            chunkId = chunkIds[i];//0
            if(installedChunks[chunkId])
                callbacks.push.apply(callbacks, installedChunks[chunkId]);
            installedChunks[chunkId] = 0;//表明唯一索引为0的chunk已经loaded
        }
        for(moduleId in moreModules) {
            //moreModules只有一个元素,所以modules[1]、modules[2]不会被覆盖
            modules[moduleId] = moreModules[moduleId];
        }
        if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules);
        while(callbacks.length)
            callbacks.shift().call(null, __webpack_require__);
        if(moreModules[0]) {
            installedModules[0] = 0;
            //moreModules[0]即modules[0]依赖modules[1]、即modules[2](没有被覆盖很关键)
            return __webpack_require__(0);
        }

还应该有这种打包情形:
common.js不带有公共模块,即自实践函数参数为[]。
main.js

webpackJsonp([0,1],[
function(module, exports, __webpack_require__) {

    var chunk1=__webpack_require__(1);
    var chunk2=__webpack_require__(2);
    exports.a=1;
    console.log(chunk1);
},function(module, exports) {
    var chunk1=1;
    exports.chunk1=chunk1;
},function(module, exports) {
    var chunk2=1;
    exports.chunk2=chunk2;
}]);

以main调用解析

     var moduleId, chunkId, i = 0, callbacks = [];
        for(;i < chunkIds.length; i++) {
            chunkId = chunkIds[i];//0,1
            if(installedChunks[chunkId])
                callbacks.push.apply(callbacks, installedChunks[chunkId]);
            installedChunks[chunkId] = 0;
        }
        for(moduleId in moreModules) {
            //moreModules全部转移到modules
            modules[moduleId] = moreModules[moduleId];
        }
        if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules);
        while(callbacks.length)
            callbacks.shift().call(null, __webpack_require__);
        if(moreModules[0]) {
            //modules[0]是chunk文件运行代码
            installedModules[0] = 0;
            return __webpack_require__(0);
        }

上边的计划最后将生成八个bundle, 即page1.bundle.js和page2.bundle.js。

新建webpack配置文件webpack.config.js

使用jquery

抚今悼昔以下:jq那些库包容amd和commonJS的导入方式,require.ensure能够以不打包的样式导入一个库

有了上述的通晓,怎么使用jq就很好想象了,以下使用ensure来导入,相似的知情使用方面包车型地铁插件来导入应该也是实用的

require.ensure(['./jquery-3.2.1.min'], function(require) {
    var jq = require('./jquery-3.2.1.min');
    jq('body').attr('c2','true');
});

运营结果符合规律。

7.按需加载

webpack.config.json

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  }
};

main.js

require.ensure(['./a'], function(require) {
  var content = require('./a');
  document.open();
  document.write('<h1>' + content + '</h1>');
  document.close();
});

a.js

module.exports = 'Hello World';

打包后

图片 7

bundle.js

/******/ (function(modules) { // webpackBootstrap
/******/    // install a JSONP callback for chunk loading
/******/    var parentJsonpFunction = window["webpackJsonp"];
/******/    window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules) {
/******/        // add "moreModules" to the modules object,
/******/        // then flag all "chunkIds" as loaded and fire callback
/******/        var moduleId, chunkId, i = 0, callbacks = [];
/******/        for(;i < chunkIds.length; i++) {
/******/            chunkId = chunkIds[i];
/******/            if(installedChunks[chunkId])
/******/                callbacks.push.apply(callbacks, installedChunks[chunkId]);
/******/            installedChunks[chunkId] = 0;
/******/        }
/******/        for(moduleId in moreModules) {
/******/            modules[moduleId] = moreModules[moduleId];
/******/        }
/******/        if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules);
/******/        while(callbacks.length)
/******/            callbacks.shift().call(null, __webpack_require__);

/******/    };

/******/    // The module cache
/******/    var installedModules = {};

/******/    // object to store loaded and loading chunks
/******/    // "0" means "already loaded"
/******/    // Array means "loading", array contains callbacks
/******/    var installedChunks = {
/******/        0:0
/******/    };

/******/    // The require function
/******/    function __webpack_require__(moduleId) {

/******/        // Check if module is in cache
/******/        if(installedModules[moduleId])
/******/            return installedModules[moduleId].exports;

/******/        // Create a new module (and put it into the cache)
/******/        var module = installedModules[moduleId] = {
/******/            exports: {},
/******/            id: moduleId,
/******/            loaded: false
/******/        };

/******/        // Execute the module function
/******/        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/        // Flag the module as loaded
/******/        module.loaded = true;

/******/        // Return the exports of the module
/******/        return module.exports;
/******/    }

/******/    // This file contains only the entry chunk.
/******/    // The chunk loading function for additional chunks
/******/    __webpack_require__.e = function requireEnsure(chunkId, callback) {
/******/        // "0" is the signal for "already loaded"
/******/        if(installedChunks[chunkId] === 0)
/******/            return callback.call(null, __webpack_require__);

/******/        // an array means "currently loading".
/******/        if(installedChunks[chunkId] !== undefined) {
/******/            installedChunks[chunkId].push(callback);
/******/        } else {
/******/            // start chunk loading
/******/            installedChunks[chunkId] = [callback];
/******/            var head = document.getElementsByTagName('head')[0];
/******/            var script = document.createElement('script');
/******/            script.type = 'text/javascript';
/******/            script.charset = 'utf-8';
/******/            script.async = true;

/******/            script.src = __webpack_require__.p + "" + chunkId + ".bundle.js";
/******/            head.appendChild(script);
/******/        }
/******/    };

/******/    // expose the modules object (__webpack_modules__)
/******/    __webpack_require__.m = modules;

/******/    // expose the module cache
/******/    __webpack_require__.c = installedModules;

/******/    // __webpack_public_path__
/******/    __webpack_require__.p = "";

/******/    // Load entry module and return exports
/******/    return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

    __webpack_require__.e/* nsure */(1, function(require) {
      var content = __webpack_require__(1);
      document.open();
      document.write('<h1>' + content + '</h1>');
      document.close();
    });


/***/ }
/******/ ]);

1.bundle.js

webpackJsonp([1],[
/* 0 */,
/* 1 */
/***/ function(module, exports) {

    module.exports = 'Hello World';


/***/ }
]);

和动用CommonsChunkPlugin打包的差异在于

/******/    // This file contains only the entry chunk.
/******/    // The chunk loading function for additional chunks
/******/    __webpack_require__.e = function requireEnsure(chunkId, callback) {
/******/        // "0" is the signal for "already loaded"
/******/        if(installedChunks[chunkId] === 0)
/******/            return callback.call(null, __webpack_require__);

/******/        // an array means "currently loading".
/******/        if(installedChunks[chunkId] !== undefined) {
/******/            installedChunks[chunkId].push(callback);
/******/        } else {
/******/            // start chunk loading
/******/            installedChunks[chunkId] = [callback];
/******/            var head = document.getElementsByTagName('head')[0];
/******/            var script = document.createElement('script');
/******/            script.type = 'text/javascript';
/******/            script.charset = 'utf-8';
/******/            script.async = true;

/******/            script.src = __webpack_require__.p + "" + chunkId + ".bundle.js";
/******/            head.appendChild(script);
/******/        }
/******/    };

模块main的id为0,模块a的id为1。return webpack_require(0),则加载main模块,
modules[0].call(module.exports, module, module.exports, webpack_requireState of Qatar则调用函数

function(module, exports, __webpack_require__) {

    __webpack_require__.e/* nsure */(1, function(require) {
      var content = __webpack_require__(1);
      document.open();
      document.write('<h1>' + content + '</h1>');
      document.close();
    }

/******/    // This file contains only the entry chunk.
/******/    // The chunk loading function for additional chunks
/******/    __webpack_require__.e = function requireEnsure(chunkId, callback) {
                //installedChunks[1]为undefined
/******/        // "0" is the signal for "already loaded"
/******/        if(installedChunks[chunkId] === 0)
/******/            return callback.call(null, __webpack_require__);

/******/        // an array means "currently loading".
/******/        if(installedChunks[chunkId] !== undefined) {
/******/            installedChunks[chunkId].push(callback);
/******/        } else {
/******/            // start chunk loading
/******/            installedChunks[chunkId] = [callback];//installedChunks[1]为数组,表明currently loading
/******/            var head = document.getElementsByTagName('head')[0];
/******/            var script = document.createElement('script');
/******/            script.type = 'text/javascript';
/******/            script.charset = 'utf-8';
/******/            script.async = true;

/******/            script.src = __webpack_require__.p + "" + chunkId + ".bundle.js";
/******/            head.appendChild(script);
                    //加载完后直接调用
                    /******/webpackJsonp([1],[
                    /******//* 0 */,
                    /******//* 1 */
                    /******//***/ function(module, exports) {
                    /******/
                    /******/    module.exports = 'Hello World';
                    /******/
                    /******/
                    /******//***/ }
                    /******/]);
                    /******/        }
                    /******/    };
                    //installedChunks[1]在webpackJsonp得到调用

installedChunks[1]为数组,成分为main模块的实行代码

/******/    window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules) {
                //moreModules为模块a的代码
/******/        // add "moreModules" to the modules object,
/******/        // then flag all "chunkIds" as loaded and fire callback
/******/        var moduleId, chunkId, i = 0, callbacks = [];
/******/        for(;i < chunkIds.length; i++) {
/******/            chunkId = chunkIds[i];
/******/            if(installedChunks[chunkId])//installedChunks[0]==0,installedChunks[1]为数组
/******/                callbacks.push.apply(callbacks, installedChunks[chunkId]);//callbacks为模块main执行代码,不为数组
/******/            installedChunks[chunkId] = 0;//installedChunks[1]不为数组,表明已经加载
/******/        }
/******/        for(moduleId in moreModules) {
/******/            modules[moduleId] = moreModules[moduleId];
/******/        }
/******/        if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules);
/******/        while(callbacks.length)
/******/            callbacks.shift().call(null, __webpack_require__);

/******/    };

公共提取

const path = require('path');const MyPlugin = require('./src/MyPlugin.js')module.exports = { mode: 'development', devtool: 'source-map', entry: './src/index.js', output: { path: path.resolve(__dirname, 'dist') }, plugins:[ new MyPlugin() ]};

这种方式将国有模块提收取来生成二个bundle,公共模块意味着有希望有比很多地方选用,恐怕招致每一种生成的bundle都包罗公共模块打包生成的代码,产生浪费,将国有模块提抽出来单独生成四个bundle可有效解决那一个题目。这里贴七个法定文档给出的安插示范:

新建src/MyPlugin.js。驾驭webpack插件越来越多音信

 const path = require('path'); module.exports = { mode: 'development', entry: { index: './src/index.js', another: './src/another-module.js' }, output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist') }, // 关键 optimization: { splitChunks: { chunks: 'all' } } };
class MyPlugin { constructor(options) { this.options = options this.externalModules = {} } apply(compiler) { var reg = /("([^\"]*(\.)?)*")|('([^\']*(\.)?)*')|(/{2,}.*?(r|n))|(/*(n|.)*?*/)|(/******/)/g compiler.hooks.emit.tap('CodeBeautify', (compilation)= { Object.keys(compilation.assets).forEach((data)= { let content = compilation.assets[data].source() // 欲处理的文本 content = content.replace(reg, function (word) { // 去除注释后的文本 return /^/{2,}/.test(word) || /^/*!/.test(word) || /^/*{3,}//.test(word) ? "" : word; }); compilation.assets[data] = { source(){ return content }, size(){ return content.length } } }) }) }}module.exports = MyPlugin

本条示例中index.js和another-module.js中都import了loadsh,若是不配备optimization,将生成五个bundle, 多个bundle都饱含loadsh的代码。配置optimization后,loadsh代码被单独提取到七个vendors~another~index.bundle.js。

当今大家运维命令webpack --config webpack.config.js,打包完毕后会多出贰个输出目录dist:dist/main.js。main是webpack暗中同意设置的出口文件名,大家一点也不慢瞄一眼这几个文件:

动态加载

(function(modules){ // ...})({ "./src/index.js": (function(){ // ... })});

动态加载的意义就是讲代码打包成多少个bundle, 须求用到哪个bundle时在加载他。那样做的裨益是足以让客户下载需求使用的代码,防止无用代码下载。明确是操作体验大概变差,因为操作之后只怕还也许有贰个下载代码的经过。关于动态加载,后边安详严整。

全方位文件只含三个应声推行函数,大家称它为webpackBootstrap,它仅接到二个目标—— 未加载的 模块会集,那个modules对象的key是三个门路,value是二个函数。你恐怕会问,这里的模块是怎样?它们又是怎么着加载的吧?在审美产出代码前,我们先丰盛一下源代码:新文件src/utils/math.js:

落实二个简易的动态加载

export const plus = (a, b) = { return a + b;};

动态加载正是要得以达成能够在代码里边去加载其余js,这一个太轻巧了,新建script标签插入dom就足以了,如下:

修改src/index.js:

function loadScript(url) { const script = document.createElement('script'); script.src = url; document.head.appendChild(script);}
import { plus } from './utils/math.js';console.log('Hello webpack!');console.log('1 + 2: ', plus(1, 2));

只供给在需求加载有些js时调用就能够,举例要求点击按键时加载js大概就如上面那样。

我们依据 ES 典型的模块化语法写了叁个简单易行的模块 src/utils/math.js,给 src/index.js 援引。Webpack 用本身的主意帮忙了 ES6 Module 标准,后面提到的 module 正是和 ES6 module 对应的定义。

btn.onClick = function() { console.log('1'); loadScript('');}

接下去大家看一下那些模块是何许通 ES5 代码完成的。再度运维命令webpack --config webpack.config.js后翻看输出文件:

上一篇:在线运营编制程序网站 下一篇:没有了

Copyright © 2015-2019 http://www.carrefourstation.com. 澳门新莆京手机网站-新蒲京娱乐场有限公司 版权所有