资讯专栏INFORMATION COLUMN

webpack源码分析之二:code-splitting

wudengzan / 3298人阅读

摘要:前言是最引人瞩目的特性之一此特性将代码分离到不同的文件中。功能分析官网上有三种方式实现入口起点使用选项手动分离代码。防止重复使用去重和分离。本质则是多个入口的,则在以为入口文件将多入口的切分为按切割文件通过加载。

前言

code-splitting是webpack最引人瞩目的特性之一,此特性将代码分离到不同的bundle文件中。详细介绍官网code-split,这次实现则在笔者上次文件打包之上做开发。

功能分析

官网上有三种方式实现

入口起点:使用 entry 选项手动分离代码。

防止重复:使用 CommonsChunkPlugin 去重和分离 chunk。

动态导入:通过模块的内联函数调用来分离代码。

1本质则是多个入口的chunk,2则在以common.js为入口文件,将多入口的chunk切分为按切割文件,通过jsonp加载。在这里笔者则介绍最为复杂的3的实现,

对于webpack 的切割文件的引入本质就是jsonp,动态引入一个约定好格式的js,并运行。

__webpack_require__.e = function requireEnsure(chunkId) {
....
    var head = document.getElementsByTagName("head")[0];
    var script = document.createElement("script");
    script.src = __webpack_require__.p + "" + chunkId + ".bundle.js";
    head.appendChild(script);
....
}

切割文件去除注释如下:

webpackJsonp([1],[function(){},function(){}])

而在入口文件的webpackJsonpCallback函数内,则是将切割的文件包含的modules依次放入存储在modules内

function webpackJsonpCallback(chunkIds, moreModules){
....
for(moduleId in moreModules) {
             if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
                 modules[moduleId] = moreModules[moduleId];
             }
         }
}     
....    

所以实现以上功能需求如下:

parse模块:定位切割点并组装异步加载文件所需要的依赖。

chunks模块:各个chunk包含module模块的集合,通过文件树里面模块的依赖关系生成。

writeChunks模块:根据chunks,通过文件流写入文件。

例子

require("d");

function a() {
    require.ensure(["./a"], function () {
        require("c");
    });
}

require.ensure(["./b"], function () {
    require("./m");
});

require("./e");
实现 parse模块

实现思路:

通过递归,以及文件树的特征定位到require.ensure

将arguments第一个参数的数组,第二个参数的函数内递归搜索require,存入数组asyncs内,并递归下去

数据结构如下:

{
    filename: "/Users/zhujian/Documents/workspace/webpack/simple-webpack/example/main.js",
    id: 0,
    requires: [{
            name: "d",
            range: [8, 11],
            id: 1
        }],
    rangeRequires: [[0, 7]],
    asyncs: [{
            requires: [{
                    name: "./a",
                    id: 2
                }, {
                    name: "c",
                    range: [88, 91],
                    id: 3
                }],
            asyncs: [],
            rangeRequires: [80, 87],
            ensureRequires: [34, 58]
        },
        {
            requires: [{
                    name: "./b",
                    id: 4
                }, {
                    name: "./m",
                    range: [156, 161],
                    id: 5
                }],
            asyncs: [],
            rangeRequires: [148, 155],
            ensureRequires: [106, 130]
        }],
}
chunks模块

由于各个依赖文件的源码都包含在modlues内,所以chunks包含的是具体各个切割文件所包需module的moduleId。

实现思路:

通过入口mainPath 找到modules的入口mainModule

将mainModule 的requires遍历,将值归入本chunk的modules内,将asyncs遍历,依次新建chunk,并关联父chunk,以上两个依次递归遍历。

最终生成完了之后,将各个非根节点的chunk遍历,将依赖的modules遍历对比父节点的chunk,如有重复标记"in-parent"

数据结构如下

{ "0": 
   { id: 0,
     modules: { "0": "include", "1": "include", "2": "include" } },
  "1": 
   { id: 1,
     modules: 
      { "1": "in-parent",
        "3": "include",
        "4": "include",
        "5": "include",
        "6": "include" },
     parentId: 0 },
  "2": 
   { id: 2,
     modules: { "5": "include", "6": "include" },
     parentId: 0 
     }
}

writeChunks模块

实现思路:

判断是否有多个chunk,来区分引入的模版。如果chunks的个数超过1,入口chunk则加载包含webpackJsonp,__webpack_require__.e等支持jsonp函数的模版,未超过则加载简单的仅包含__webpack_require__的模版

区分入口chunk,入口/非入口chunk加载不同的头部。

webpackJsonp的入参有两种,一种数组,一种以moduleId为key的对象。为数组时候则需要将以[,,modlue]等方式保证顺序

如:

代码实现

本人的简易版webpack实现simple-webpack

(完)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95266.html

相关文章

  • JavaScript - 收藏集 - 掘金

    摘要:插件开发前端掘金作者原文地址译者插件是为应用添加全局功能的一种强大而且简单的方式。提供了与使用掌控异步前端掘金教你使用在行代码内优雅的实现文件分片断点续传。 Vue.js 插件开发 - 前端 - 掘金作者:Joshua Bemenderfer原文地址: creating-custom-plugins译者:jeneser Vue.js插件是为应用添加全局功能的一种强大而且简单的方式。插....

    izhuhaodev 评论0 收藏0
  • 【回顾九月份第三周】 最近JavaScript的资讯集合

    摘要:投射剧中人物对车祸妻子偷情肇事者死亡的真相听而不闻视而不见闭嘴不言。想方设法把自己培养成工程师而不是最后成为了码农查看更多列表回顾九月份第一周为什么你的前端工作经验不值钱回顾九月份第二周前端你该知道的事儿回顾九月份第三周最近的资讯集合 原链接:http://bluezhan.me/weekly/#/9-3 1、web前端 JavaScript实现H5游戏断线自动重连的技术 前端日报:...

    iKcamp 评论0 收藏0
  • 【回顾九月份第三周】 最近JavaScript的资讯集合

    摘要:投射剧中人物对车祸妻子偷情肇事者死亡的真相听而不闻视而不见闭嘴不言。想方设法把自己培养成工程师而不是最后成为了码农查看更多列表回顾九月份第一周为什么你的前端工作经验不值钱回顾九月份第二周前端你该知道的事儿回顾九月份第三周最近的资讯集合 原链接:http://bluezhan.me/weekly/#/9-3 1、web前端 JavaScript实现H5游戏断线自动重连的技术 前端日报:...

    vvpvvp 评论0 收藏0
  • webpack源码分析之三:loader

    摘要:本次介绍的则是用来解决这类问题的。实现模块实现思路将配置内的命令的的内联从前至后组成一个数组。所有字符串内部又可以截取,获取完整的。分析并解析该数组内的字符串,获取各个的绝对路径。 前言 在webpack特性里面,它可以支持将非javaScript文件打包,但前面写到webpack的模块化打包只能应用于含有特定规范的JavaScript文件。本次介绍的loader则是用来解决这类问题的...

    laznrbfe 评论0 收藏0

发表评论

0条评论

wudengzan

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<