webpack 俨然已经成为前端最主流的构建工具,其功能多种多样,我们今天就来分析下关于代码分割这部分的一点事,并在最后讲述如何实现在webpack编译出的代码里手动添加一个异步chunk。

什么是chunkId与moduleId?

每个chunkId对应的是一个js文件,每个moduleId对应的是一个个js文件的内容的模块(一个js文件里面可以require多个资源,每个资源分配一个moduleId),所以它两的关系就是一个chunkId可能由很多个moduleId组成。

在webpack 编译出来的代码有定义了一个名称为__webpack_require__的函数,这个函数就是用来加载模块的,所以它的参数自然就是moduleId,如下:

/******/ 	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] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }

  

这里我们要讲代码分割,那自然也要看看webpack编译出来的代码是通过什么方法进行异步加载js文件的,从代码中我们可以找到一个名为requireEnsure的函数,这个函数便是来做这个事情的,那自然而然它的参数就是chunkId了,如下:

/******/ 	__webpack_require__.e = function requireEnsure(chunkId) {
/******/ var installedChunkData = installedChunks[chunkId];
/******/ if(installedChunkData === 0) {
/******/ return new Promise(function(resolve) { resolve(); });
/******/ }
/******/
/******/ // a Promise means "currently loading".
/******/ if(installedChunkData) {
/******/ return installedChunkData[2];
/******/ }
/******/
/******/ // setup Promise in chunk cache
/******/ var promise = new Promise(function(resolve, reject) {
/******/ installedChunkData = installedChunks[chunkId] = [resolve, reject];
/******/ });
/******/ installedChunkData[2] = promise;
/******/
/******/ // start chunk loading
/******/ var head = document.getElementsByTagName('head')[0];
/******/ var script = document.createElement('script');
/******/ script.type = 'text/javascript';
/******/ script.charset = 'utf-8';
/******/ script.async = true;
/******/ script.timeout = 120000;
/******/
/******/ if (__webpack_require__.nc) {
/******/ script.setAttribute("nonce", __webpack_require__.nc);
/******/ }
/******/ script.src = __webpack_require__.p + "" + ({"0":"home-chunk","1":"users-chunk","2":"about-chunk"}[chunkId]||chunkId) + ".js";
/******/ var timeout = setTimeout(onScriptComplete, 120000);
/******/ script.onerror = script.onload = onScriptComplete;
/******/ function onScriptComplete() {
/******/ // avoid mem leaks in IE.
/******/ script.onerror = script.onload = null;
/******/ clearTimeout(timeout);
/******/ var chunk = installedChunks[chunkId];
/******/ if(chunk !== 0) {
/******/ if(chunk) {
/******/ chunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));
/******/ }
/******/ installedChunks[chunkId] = undefined;
/******/ }
/******/ };
/******/ head.appendChild(script);
/******/
/******/ return promise;
/******/ };

从上面代码我们可以看出requireEnsure其实就是通过动态创建script标签来加载js文件的,但是这里不是每次访问这个js文件,都进行创建script请求的,在创建script前,requireEnsure会先通过installedChunks读取下是否已经有缓存了,如果有缓存直接使用便可。

一个Demo

干说原理,都抽象啊,还是从一个demo来分析,你轻松我也轻松

webpack 代码分割一点事的更多相关文章

  1. webpack优化之玩转代码分割和公共代码提取

    前言 开发多页应用的时候,如果不对webpack打包进行优化,当某个模块被多个入口模块引用时,它就会被打包多次(在最终打包出来的某几个文件里,它们都会有一份相同的代码).当项目业务越来越复杂,打包出来 ...

  2. webpack练手项目之easySlide(二):代码分割(转)

    在上一篇 webpack练手项目之easySlide(一):初探webpack  中我们一起为大家介绍了webpack的基本用法,使用webpack对前端代码进行模块化打包. 但是乍一看webpack ...

  3. React配合Webpack实现代码分割与异步加载

    这是Webpack+React系列配置过程记录的第四篇.其他内容请参考: 第一篇:使用webpack.babel.react.antdesign配置单页面应用开发环境 第二篇:使用react-rout ...

  4. webpack:代码分割与按需加载

    代码分割就是我们根据实际业务需求将代码进行分割,然后在合适的时候在将其加载进入文档中. 代码中总有些东西我们希望拆分开来,比如: 使用概率较低的模块,希望后期使用的时候异步加载 框架代码,希望能利用浏 ...

  5. webpack的代码分割/离

    两种方法: 1.webpack的methods----require.ensure 2.ES 2015的Loader spec //require.ensure语法 require.ensure [] ...

  6. webpack练手项目之easySlide(二):代码分割

    Hello,大家好. 在上一篇 webpack练手项目之easySlide(一):初探webpack  中我们一起为大家介绍了webpack的基本用法,使用webpack对前端代码进行模块化打包. 但 ...

  7. webpack中css文件的代码分割

    module.exports = { output: { filename: '[name].js', chunkFilename: '[name].chunk.js', path: path.res ...

  8. Webpack之optimization.splitChunks代码分割插件的配置

    SplitChunkPlugin插件配置参数详解 对引入的库代码(例如:lodash.jQuery等)进行代码的分割进行优化 若配置时只写chunks:"all",其余则为默认配置 ...

  9. 从Mpx资源构建优化看splitChunks代码分割

    背景 MPX是滴滴出品的一款增强型小程序跨端框架,其核心是对原生小程序功能的增强.具体的使用不是本文讨论的范畴,想了解更多可以去官网了解更多. 回到正题,使用MPX开发小程序有一段时间了,该框架对不同 ...

随机推荐

  1. MVP技术沙龙上海站-SQL BI

    5月,微软爱好者们齐聚一起,在上海港汇中心,参加<MVP技术沙龙上海站-SQL BI>系列讲座,下面是现场图片.  

  2. Spring Boot:如何优雅的使用 Mybatis

    mybatis-spring-boot-starter 官方说明:MyBatis Spring-Boot-Starter will help you use MyBatis with Spring B ...

  3. python3.6.3安装步骤,适用linux centos系统

    step1: yum -y install gccyum install zlib zlib-devel step2: cd /usr/bin/ mv python python.bak step3: ...

  4. flask 第四章 偏函数 Local空间转时间 myLocalStack RunFlask+request 请求上下文

    1 . 偏函数 (partial) from functools import partial def func(*args,**kwargs): a=args b=kwargs return a,b ...

  5. linux 虚拟机配置固定ip

    参考这边博客: https://blog.csdn.net/u014466635/article/details/80284792 但是这个有个小问题,就是没有配置dns,导致连不上公网 /etc/s ...

  6. mysql的报错

    这个错误是因为mysql的进程错误关闭导致的,我们需要把/var/lib/mysql/mysql.sock文件删除或者改名,之后再重启就ok

  7. C# Global.asax.cs 定时任务

    定时执行更新Redis缓存操作 protected void Application_Start(object sender, EventArgs e) { Timer timer = new Tim ...

  8. lintcode 四道题

    我们考虑对每个字符进行两边扩展,寻找回文串,并记录长度.有两种情况,一种是bab,从a向两边扩展,一种abba,从bb中间向两边扩展. dp[i][j] 表示子串s[i-j]是否是回文 初始化:dp[ ...

  9. 单链表数据结构 - java简单实现

    链表中最简单的一种是单向链表,每个元素包含两个域,值域和指针域,我们把这样的元素称之为节点.每个节点的指针域内有一个指针,指向下一个节点,而最后一个节点则指向一个空值.如图就是一个单向链表 一个单向链 ...

  10. JAVA第2课

         JAVA   第二课 Eclipse 在加载JAVA环境出错的时候处理办法: 项目-属性-Java build path-add library -JRE system library-OK ...