Webpack面试考点之核心考点

1、模块打包运行原理

Webpack是如何把这些模块合并到一起,并且保证其正常工作的,你是否了解呢?

webpack的整个打包流程:

a、读取webpack的配置参数;

b、启动webpack,创建Compiler对象并开始解析项目;

c、从入口文件(entry)开始解析,并且找到其导入的依赖模块,递归遍历分析,形成依赖关系树;

d、对不同文件类型的依赖模块文件使用对应的Loader进行编译,最终转为Javascript文件;

e、整个过程中webpack会通过发布订阅模式,向外抛出一些hooks,而webpack的插件即可通过监听这些关键的事件节点,执行插件任务进而达到干预输出结果的目的。

其中文件的解析与构建是一个比较复杂的过程,在webpack源码中主要依赖于compiler和compilation两个核心对象实现

compiler对象是一个全局单例,他负责把控整个webpack打包的构建流程。compilation对象是每一次构建的上下文对象,它包含了当次构建所需要的所有信息,每次热更新和重新构建,compiler都会重新生成一个新的compilation对象,负责此次更新的构建过程。

而每个模块间的依赖关系,则依赖于AST语法树。每个模块文件在通过Loader解析完成之后,会通过acorn库生成模块代码的AST语法树,通过语法树就可以分析这个模块是否还有依赖的模块,进而继续循环执行下一个模块的编译解析。

最终Webpack打包出来的bundle文件是一个IIFE的执行函数。(IIFE(Immediately Invoked Function Expressions) 叫做立即执行表达式,顾名思义,该表达式一被创建就立即执行)。

2、缓存

webpack 是如何解决两次引入的?他想问的是webpack是怎么处理模块的,就是引入了一次就会"缓存起来",再次引入会去判断是否引入过

1)babel缓存 

设置cacheDirectory: true,可以 让第二次打包构建速度更快。

2)文件资源缓存

a、hash:每次wepack构建时会生成一个唯一的hash值。

 存在的问题:因为js和css同时使用一个hash值。如果重新打包,会导致所有缓存失效。(可能我却只改动一个文件)

b、chunkhash:根据chunk生成的hash值。如果打包来源于同一个chunk,那么hash值就一样

存在的问题:js和css的hash值还是一样的,因为css是在js中被引入的,所以同属于一个chunk

c、contenthash: 根据文件的内容生成hash值。不同文件hash值一定不一样

3、webpack 热更新

基于 WDS (Webpack-dev-server) 的模块热替换,只需要局部刷新页面上发生变化的模块,同时可以保留当前的页面状态。

热更新的过程:

1)启动阶段:文件经过 Webpack-complier 编译好后传输给 Bundle Server,Bundle Server 可以让浏览器访问到我们打包出来的文件。

2)文件热更新阶段:同时文件经过 Webpack-complier 编译好后传输给 HMR Server,HMR Server 知道哪个资源 (模块) 发生了改变,并通知 HMR Runtime 有哪些变化(也就是上面我们看到的两个请求),HMR Runtime 就会更新我们的代码,这样我们浏览器就会更新并且不需要刷新。

4、webpack的性能优化

1)缩小文件范围 Loader

优化loader配置,使用test、include、exclude三个配置项来缩⼩loader的处理范围,推荐include。

2)优化resolve.modules

resolve.modules用于配置webpack去哪些目录下寻找第三方模块,默认是

['node_modules']。寻找第三方,默认是在当前项目目录下的node_modules里面去找,如果没有找到,就会去上一级目录../node_modules找,再没有会去../../node_modules中找,以此类推,和Node.js的模块寻找机制很类似。

如果我们的第三⽅模块都安装在了项⽬根⽬录下,就可以直接指明这个路径。

3)使用静态资源路径publicPath(CDN)

CDN通过将资源部署到世界各地,使得⽤户可以就近访问资源,加快访问速度。要接⼊CDN,需要把网页的静态资源上传到CDN服务上,在访问这些资源时,使⽤CDN服务提供的URL。

4)借助MiniCssExtractPlugin完成抽离css

5)压缩css和HTML

6)抽取公共代码

在多页应用中,抽离各页面模块公共代码。

5、Source Map

我们知道 Webpack 通过模块之间的引用关系,构建一个依赖树,并生成相应的结果文件。但这个结果文件是存在一定的缺陷的:代码有可能压缩并混淆;代码文件可能是由一个或者多个组成。

Source Map, 顾名思义,是保存源代码映射关系的文件。因为代码是压缩混淆的,我们找不到报错的文件的相关信息,那有没有一个拥有源文件与打包后文件的映射关系的文件,让它来告诉我们呢?这个文件就是 Source Map 文件。

官方文档列出了很多种组合,在这之前,我们可以先好好看看以下的关键字,不管是什么组合都是下面的一个或者多个拼接而成的。

source map:产生 .map 文件(配合 eval 或者 inline 使用的时候,会不生成 source map 文件,具体要看哪个模式)。

eval:使用 eval 包裹块代码。

cheap:不生成列信息。

inline:将 .map 作为 DataURI 嵌入,不单独生成一个 .map 文件。

module:包含 loader 的 source map。

6、webpack异步加载原理及分包策略

webpack ensure 有人称它为异步加载,也有人称为代码切割,他其实就是将 js 模块给独立导出一个.js 文件,然后使用这个模块的时候,再创建一个 script 对象,加入到 document.head 对象中,浏览器会自动帮我们发起请求,去请求这个 js 文件,然后写个回调函数,让请求到的 js 文件做一些业务操作。

需求:main.js 依赖两个 js 文件:A.js 是点击 aBtn 按钮后,才执行的逻辑,B.js 是点击 bBtn 按钮后,才执行的逻辑。

 正常情况下,webpack 把 main.js 依赖的两个文件都同时打包到同一个 js 文件,并在 index.html 中引入。但是 A.js 和 B.js 都是点击相应按钮才会执行的逻辑,如果用户并没有点击相应按钮,而且这两个文件又是比较大的话,这样是不是就导致首页默认加载的 js 文件太大,从而导致首页渲染较慢。

1)require.ensure 异步加载

能否实现当用户点击按钮的时候再加载相应的依赖文件呢?require.ensure 异步加载可以解决这个问题。

我们再进行一下打包,发现多了 1.index.js 和 2.index.js 两个文件。而我们打开页面时只引入了 index.js 一个文件,当点击按钮 A 的时候才引入 1.index.js 文件,点击按钮 B 的时候才引入 2.index.js 文件。这样就满足了我们按需加载的需求。

require.ensure 这个函数是一个代码分离的分割线,表示回调里面的 require 是我们想要进行分割出去的,即 require('./A.js'),把 A.js 分割出去,形成一个 webpack 打包的单独 js 文件。它的语法如下:

打开 1.index.js 文件,发现它的代码如下:

a、异步加载的代码,会保存在一个全局的webpackJsonp中。

b、webpackJsonp.push的的值,两个参数分别为异步加载的文件中存放的需要安装的模块对应的 id 和异步加载的文件中存放的需要安装的模块列表。

c、在满足某种情况下,会执行具体模块中的代码。

2)import() 按需加载

webpack4 官方文档提供了模块按需切割加载,配合 es6 的按需加载 import() 方法,可以做到减少首页包体积,加快首页的请求速度,只有其他模块,只有当需要的时候才会加载对应 js。

该函数只接受一个参数,就是引用包的地址,并且使用了 promise 式的回调,获取加载的包。在代码中所有被 import()的模块,都将打成一个单独的包,放在 chunk 存储的目录下。在浏览器运行到这一行代码时,就会自动请求这个资源,实现异步加载。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容