2.5 webpack 进阶
配置分离
code splitting 异步加载
理解 webpack chunk
webpack 调试
2.5.1 配置分离
在大型项目中,可能 webpack.config.js 会变得越来越臃肿,这个时候可以利用做 webpack-merge 插件。将配置定义在一个目录下面的不同文件中,然后通过 webpack-merge 来合并成最终的配置。
webpack-merge 详见 https://www.npmjs.com/package/webpack-merge
2.5.2 code splitting 异步加载
代码分割不仅仅是提取业务的公共代码,更应该关注的是实现代码的按需加载。 通过在模块中定义 split point ,webpack 会在打包的时候自动的分割代码块。定义 split point 的方式有两种
CommonJs 方式
require.ensure 方法:
/**
* @param dependencies [Array] 模块依赖的数组
* @param callback [Function]
*/require.ensure(dependencies, callback)
eg:// 模块 index.js
/**
* [description]
* @param {[type]} ) { const async [description]
* @return {[type]} [description]
*/require.ensure(['./async'], function() {
const async = require('./async');
console.log(async.default)
});
// 模块 async.js
export default {
a: 1
}
webpack 打包过后会生成三个文件
index.js 1.1.js vendor.common.js
index.js 的内容为
webpackJsonp([0],[
/* 0 *//***/ function(module, exports, __webpack_require__) {
'use strict';
__webpack_require__.e/* nsure */(1, function () {
var async = __webpack_require__(1);
console.log(async.default);
});
/***/ }
]);
//# sourceMappingURL=home.js.map
1.1.js 的内容为
webpackJsonp([1],[
/* 0 */,
/* 1 *//***/ function(module, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
/**
* async module
*/
exports.default = {
a: 1
};
/***/ }
]);
//# sourceMappingURL=1.1.js.map
webpackJsonp 方法定义在 vendor.bundle.js 中:
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);
/******/ }
/******/ };
所以在 html 中应该先加载 vendor.bundle.js
<script src="js/vendor.bundle.js"></script><script src="js/index.js"></script>
在使用异步加载的时候需要注意一下两点:
配置 output.publicPath: publicPath 为脚本在服务器中的文字,只有定义了 publicPath 才能通过 webpackJsonp 获取;
是对于异步的 CommonJs 模块引入只能通过 require 的方式引用,不能通过 Es6 import 的方式引入;
AMD 方式
AMD 的方式也可以实现异步加载,这和使用 require.js 的使用方式基本相同,在定义模块的时候需要按照 AMD 的规范来定义
/**
* @param dependencies [Array] 模块依赖
* @param callback [Function]
*/require(dependencies, callback)
eg:
// 定义模块
define('modula-a', ['module-c'], function(c) {
//return ...
})
// 依赖模块require(["module-a", "module-b"], function(a, b) {
console.log(a, b);
});
这时候的 require 实现是异步的方式,只有依赖的模块加载完成并执行回调,才会执行模块的 callback,依赖模块的回调结果会作为参数传入 a, b 中。
2.5.3 代码块 Chunk
Chunk 是什么?
webpack 中 Chunk 实际上就是输出的 .js 文件,可能包含多个模块,主要的作用是为了优化异步加载。
Chunk 包含了哪些内容?
对于同步的情况,一个 Chunk 会递归的把模块中所有的依赖都加入到 Chunk 中。
对于异步的情况,在每一个 split point 上所有依赖的模块会打包进一个新的 chunk,和同步一样,依赖也是递归的,如果子模块依赖其他模块也会加入到 chunk 中,依赖的回调函数中 require 的其他模块也会打包进 chunk 中,以下公式表示 chunk 内容:
chunk content = recursive(ensure 依赖) + recursive(callback 依赖)
Chunk 分类
Entry Chunk
入口代码块包含了 webpack 运行时需要的一些函数,如 webpackJsonp, __webpack_require__ 等以及依赖的一系列模块。
Normal Chunk
普通代码块没有包含运行时需要的代码,只包含模块代码,其结构有加载方式决定,如基于 CommonJs 异步的方式可能会包含 webpackJsonp 的调用。 The chunk also contains a list of chunk id that it fulfills.
Initial chunk
与入口代码块对应的一个概念是入口模块(module 0),如果入口代码块中包含了入口模块 webpack 会立即执行这个模块,否则会等待包含入口模块的代码块,包含入口模块的代码块其实就是 initial chunk。 以上面的 CommonJs 异步加载为例:
<!-- 入口 Chunk, 未包含入口模块 --><script src="js/vendor.bundle.js"></script><!-- 包含入口模块的 Initial Chunk,执行入口模块 --><script src="js/index.js"></script>
Commons chunk 与 CommonsChunkPlugin
之前我们已经利用 CommonsChunkPlugin 来分割公共代码如 react, react-dom 到 vendor.bundle.js 中,这里介绍相关的原理。
以下面的配置为例
var webpack = require("webpack");
module.exports = {
entry: { a: "./a", b: "./b" },
output: { filename: "[name].js" },
plugins: [ new webpack.optimize.CommonsChunkPlugin("init.js") ]
}
当有多个入口的时候,CommonsChunkPlugin 会把 a,b 模块公共依赖的模块抽离出来,并加上 webpack 运行时代码,形成一个新的代码块,这个代码块类型为 entry chunk。a,b 两个入口会形成两个单独的代码块,这两个代码块为 initial chunk。
在 html 中,可以如下加载:
<!-- entry chunk --><script src="init.js"></script><!-- inital chunk a --><script src="a.js"></script><!-- initial chunk b --><script src="b.js"></script>
更多 CommonChunkPlugin 的参数参见 https://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin
require.include
可以使用 require.include 方法,直接引入模块,如下例子:
require.ensure(["./file"], function(require) {
require("./file2");
});
// is equal torequire.ensure([], function(require) {
require.include("./file");
require("./file2");
});
这个方法可以实现一些分块的优化,当一个 chunk-parent 可能会异步引用多个 chunk-child 而这些 chunk-child 可能都包含了 moduleA, 那么可以在 chunk-parent 中 require.include('moduleA') 就可以避免重复加载 moduleA。
给异步 Chunk 命名
根据 split point 生成出来的 chunk 名称都是数字,可以在 split point 上定义 chunk 名称:
/**
* @param chunkName [String] chunk 名称
*/require.ensure(dependencies, callBack, chunkName)
也可以在 webpack.config.js 中配置修改 output.chunkName 来修改 chunk 名称
Chunk 优化
在一些特殊的场景可以利用如下这些插件来完成 Chunk 的优化,
LimitChunkCountPlugin
MinChunkSizePlugin
AggressiveMergingPlugin
调试 webpack
在配置 webpack 的过程中,可以利用 webpack 提供的一些工具和参数来调试。
命令行参数
通过调用
$ webpack [--params,...]
--progress: 能够看到打包进度--json: 可以将打包结果输出为 json--display-chunks: 可以看到打包出来的 chunk 信息
webpack analyse
analyse 地址:https://webpack.github.io/analyse/
可以通过 analyse 网站分析 webpack 的编译结果,如下图,可以分析 chunks, modules, Assets 等。
2.5 webpack 进阶的更多相关文章
- webpack进阶构建项目(一)
webpack进阶构建项目(一) 阅读目录 1.理解webpack加载器 2.html-webpack-plugin学习 3.压缩js与css 4.理解less-loader加载器的使用 5.理解ba ...
- webpack进阶用法你都get到了么?
如何消除无用代码:打包自己的私有js库:实现代码分割和动态import提升初次加载速度:配置eslint规范团队代码规范:打包异常抓捕你都get到了么? 摇树优化:Tree Shaking webpa ...
- 前端利器躬行记(4)——webpack进阶
webpack是一个非常强大的工具,除了前文所介绍的基础概念之外,还有各种进阶应用,例如Source Map.模块热替换.集成等,本文会对这些内容做依次讲解. 一. runtime和manifest ...
- [转]webpack进阶构建项目(一)
阅读目录 1.理解webpack加载器 2.html-webpack-plugin学习 3.压缩js与css 4.理解less-loader加载器的使用 5.理解babel-loader加载器 6.理 ...
- webpack进阶之插件篇
一.插件篇 1. 自动补全css3前缀 autoprefixer 官方是这样说的:Parse CSS and add vendor prefixes to CSS rules using values ...
- webpack进阶构建项目(一):1.理解webpack加载器
1.理解webpack加载器 webpack的设计理念,所有资源都是“模块”,webpack内部实现了一套资源加载机制,这与Requirejs.Sea.js.Browserify等实现有所不同. We ...
- webpack进阶--loader
webpack的核心就是它的配置文件,只要配置好配置文件webpack就可以用得利索-- 而配置文件主要就是7个部分entry.output.plugins.resolve.devserver(web ...
- webpack进阶--打包
上一片博文主要让大家了解下究竟webpack是干什么的,明显它是专注于打包的. gulp 和 webpack 的区别 gulp,要求我们一步步写task(es6编译.css压缩.图片压缩.打包. ...
- webpack进阶之loader篇
webpack的loaders是一大特色,也是很重要的一部分.这遍博客我将分类讲解一些常用的laoder 一.loaders之 预处理 css-loader 处理css中路径引用等问题 style-l ...
随机推荐
- Nginx + Tomcat 配置负载均衡集群简单实例
一.Hello world 1.前期环境准备 准备两个解压版tomcat,如何同时启动两个tomcat,请看我的另一篇文章<一台机器同时启动多个tomcat>. nginx官网下载解压版n ...
- kafka 简单安装以及java小demo
文章目录 第1步,下载解压 kafka: 第2步,运行 kafka: 第3步,创建topic 第4步,生产者发送消息 第5步,消费者接收消息 使用 java 客户端 kafka 0.8.0版本demo ...
- yum安装apache
一.查询是否已经安装apache rpm -qa httpd 注:Apache在linux系统里的名字是httpd 如果有返回的信息,则会显示已经安装的软件.如果没有则不会显示其它的信息.如下图是 ...
- PAT甲级——A1146 TopologicalOrder【25】
This is a problem given in the Graduate Entrance Exam in 2018: Which of the following is NOT a topol ...
- java swing 中JTable实现指定单元格为下拉框
利用自定义的CellEditor实现第四列第二行为下拉框,本列其余行为文本框 利用默认的DefaultCellEditor设置第五列整列为下拉框 package mypackage; import ...
- Python升级3.多
本文主要介绍在Linux(CentOS)下将Python的版本升级为3.6.2的方法 众所周知,在2020年python官方将不再支持2.7版本的python,所以使用3.x版本的python是必要的 ...
- python-函数-动态传参,作用域的问题,函数嵌套,global nonlocal
⼀. 函数参数--动态传参 之前我们说过了传参, 如果我们需要给⼀个函数传参, ⽽参数⼜是不确定的. 或者我给⼀个 函数传很多参数, 我的形参就要写很多, 很⿇烦, 怎么办呢. 我们可以考虑使⽤动态参 ...
- syslog-ng收集日志+ELK平台搭建教程
syslog-ng部署: 用于接收交换机输出的日志. syslog-ng安装很简单,可以顺便搜一下,文章有很多.我是yum直接安装的. syslog-ng配置: vi /etc/syslog-ng/s ...
- redis集群添加新节点
一.创建节点(接上文) 1.在H1服务器/root/soft目录下创建7002目录 2.将7001目录的配置文件redis.conf拷贝到7002,并修改配置文件的端口 3.进入 redis-5.0. ...
- 【leetcode】955. Delete Columns to Make Sorted II
题目如下: We are given an array A of N lowercase letter strings, all of the same length. Now, we may cho ...