# 面试题题目
# 前端基础
# 介绍一下 this 绑定常用的几种方式
https://mrgaogang.github.io/javascript/base/Javascript%E4%B8%ADthis%E7%BB%91%E5%AE%9A%E8%AF%A6%E8%A7%A3.html#%E4%B8%80%E3%80%81-%E9%BB%98%E8%AE%A4%E7%BB%91%E5%AE%9A
- 显示绑定 call,bind,apply
- 隐式绑定
- 全局环境调用
# Javascript 中 call,apply 和 bind 的共同点和区别
# JS 模块化
https://mrgaogang.github.io/javascript/base/Javascript%E6%A8%A1%E5%9D%97%E5%8C%96%E5%8F%91%E5%B1%95AMD,CMD,CommonJS,UMD,ES6.html
# common.js 和 es6 中模块引入的区别?
# 讲一下闭包
# ajax 的状态值有几种,分别是什么?
https://mrgaogang.github.io/interview/%E8%85%BE%E8%AE%AF%E9%9D%A2%E8%AF%95.html#%E4%BA%94%E9%9D%A2
# 介绍一下 Promise
什么是 promise
常用的 API 有哪些
Promise.all()和 Promise.race()的区别
如果向 Promise.all()和 Promise.race()传递空数组,运行结果会有什么不同?
all 会立即决议,决议结果是 fullfilled,值是 undefined
race 会永远都不决议,程序卡死……
错误捕获
# 介绍一下 es6 的 Generator 函数
https://es6.ruanyifeng.com/#docs/generator
# 介绍一下前端实现动画的常用方式
至少要答出:requestAnimationFrame, css 的 animation, css 的 transform+translate+scale
# js 执行会阻塞 DOM 树的解析和渲染,那么 css 加载会阻塞 DOM 树的解析和渲染吗?
# css 的加载会阻塞 js 的执行吗?
# 浏览器渲染机制
https://juejin.cn/post/6844903702306750471#heading-33
# 介绍一下 FileReader,ArrayBuffer,Blob
https://cloud.tencent.com/developer/article/1525156
# CSS
# first-child 和 first-of-type 区别
# 介绍一下 BFC 及其用途
块级格式化上下文: 具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性。
BFC 触发的场景: body 根元素 浮动元素:float 除 none 以外的值 绝对定位元素:position (absolute、fixed) display 为 inline-block、table-cells、flex overflow 除了 visible 以外的值 (hidden、auto、scroll)
BFC 的特性: 利用 BFC 避免 margin 重叠; 利用 BFC 清楚浮动
# 介绍一下 css 的盒模型和怪异盒模型
https://segmentfault.com/a/1190000015235886
# 图片放大两倍
# css 中 scale(-1)
# 用纯 CSS 创建一个三角形的原理是什么?
width: 0; height: 0; border-top: 40px solid transparent; border-left: 40px solid transparent; border-right: 40px solid transparent; border-bottom: 40px solid #ff0000;
# flex 布局()
# 介绍一下前端布局 flex-grow 和 flex-shink
答:flex 布局比较情况
# 讲一下 gif jpeg png apng 等各种图片格式的区别
https://blog.mimvp.com/article/39919.html
- jpg / jpeg
JPEG 是有损的、采用直接色的、点阵图。jpg 的优点是它支持百万种色彩。jpg 是一种有损压缩的方式,它会放弃图片的某些细节。所以要是对图片质量的要求不是很高,可以采用 jpg 的保存方式。那么根据 jpg 的特点总结出:色彩丰富的照片适合 jpg 的保存方式,不适合小图标,线条的图片。
- gif
gif 支持动画,支持透明,支持渐变色彩,同时 gif 是无损压缩,但是 gif 得缺点也是相当明显,仅支持 8bit 的索引色,即在整个图片中,只能存在 256 种不同的颜色,就是它只支持 256 中色彩,所以对于色彩丰富的图片压缩效果不好。
- APNG
火狐 mozilla 提出来的, 24 位的,而且也是动图,可以容纳 1680 万种颜色,也是为了取代 GIF
# TypeScript
# ts 和 js 的区别
# typeof 可以判断哪些类型?instanceof 做了什么?
typeof 可以判断 number、boolean、symbol、string、object、undefined、function。无法判断 Date、RegExp 等复杂的对象。
instanceof 主要的实现原理就是只要右边变量的 prototype 在左边变量的原型链上即可。因此,instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype,如果查找失败,则会返回 false,告诉我们左边变量并非是右边变量的实例。
# 什么是 TypeScript 映射文件
TypeScript Map 文件是一个源映射文件,其中包含有关我们原始文件的信息。
.map 文件是源映射文件,可让工具在发出的 JavaScript 代码和创建它的 TypeScript 源文件之间进行映射。
许多调试器可以使用这些文件,因此我们可以调试 TypeScript 文件而不是 JavaScript 文件。
# Typescript 中的模块是什么?
模块是创建一组相关变量、函数、类和接口等的强大方法。它可以在它们自己的范围内执行,而不是在全局范围内。换句话说,在模块中声明的变量、函数、类和接口不能在模块外部直接访问。
# 说说什么 Typescript 中的泛型?作用是什么?
# 介绍一下 type 和 Interface 的区别
# NodeJS
# 介绍一下 require 模块加载机制
http://www.ruanyifeng.com/blog/2015/05/require.html
Module._load = function(request, parent, isMain) {
// 计算绝对路径
var filename =
Module._resolveFilename(request, parent);
// 第一步:如果有缓存,取出缓存
var cachedModule = Module._cache[filename];
if (cachedModule) {
return cachedModule.exports;
// 第二步:是否为内置模块
if (NativeModule.exists(filename)) {
return NativeModule.require(filename);
}
// 第三步:生成模块实例,存入缓存
var module = new Module(filename, parent);
Module._cache[filename] = module;
// 第四步:加载模块
try {
module.load(filename);
hadException = false;
} finally {
if (hadException) {
delete Module._cache[filename];
}
}
// 第五步:输出模块的exports属性
return module.exports;
};
- 计算模块的绝对路径
2 . 判断是否有缓存,如果有缓存则从缓存中读取
- 是否为内置模块,如果是内置模块则直接加载
- 生成模块实例,存入缓存
- 模块进行加载
模块加载的原理,以 js 文件为例,首先是读取文件,然后使用 apply 函数进行执行 代码
- js 模块读取
- 使用 apply 执行,并注入 export,require 等属性
- 输出模块的 exports 属性
# require 查找资源顺序
1)如果 X 是内置模块(比如 require('http')) a. 返回该模块。 b. 不再继续执行。 2)如果 X 以 "./" 或者 "/" 或者 "../" 开头
- a. 根据 X 所在的父模块,确定 X 的绝对路径。
- b. 将 X 当成文件,依次查找下面文件,只要其中有一个存在,就返回该文件,不再继续执行。
X
X.js
X.json
X.node
- c. 将 X 当成目录,依次查找下面文件,只要其中有一个存在,就返回该文件,不再继续执行。
X/package.json(main 字段)
X/index.js
X/index.json
X/index.node
3)如果 X 不带路径 a. 根据 X 所在的父模块,确定 X 可能的安装目录。 b. 依次在每个目录中,将 X 当成文件名或目录名加载。
4) 抛出 "not found"
# Node 中的事件循环和浏览器的事件循环的区别?
浏览器的事件循环:
当某个宏任务执行完后,会查看是否有微任务队列。如果有,先执行微任务队列中的所有任务,如果没有,会读取宏任务队列中排在最前的任务,执行宏任务的过程中,遇到微任务,依次加入微任务队列。栈空后,再次读取微任务队列里的任务,依次类推
node v11 之后的时间循环和浏览器是一直的。 node v11 之前的事件循环: microtask 会在事件循环的各个阶段之间执行,也就是一个阶段执行完毕,就会去执行 microtask 队列的任务
https://juejin.cn/post/6844903761949753352#heading-13
# require 模块和 import 的区别
调用时机
- CommonJS 加载的是一个对象(即 module.exports 属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成
require/exports 输出的是一个值的拷贝,import/export 模块输出的是值的引用
require/exports 输出的是值的拷贝。也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。
import/export 模块输出的是值的引用。JS 引擎对脚本静态分析的时候,遇到模块加载命令 import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。
若文件引用的模块值改变,require 引入的模块值不会改变,而 import 引入的模块值会改变。
- import 支持动态导入
# exports.xxx 和 module.exports 的区别
# express/koa 中间件原理
# 新技术
# PWA 面试题
https://juejin.cn/post/6844904052166230030
- 什么是 PWA?
- PWA 的优缺点
- Service Workers 是什么?
- PWA 与 Hybrid 之间有什么不同?
- Service Worker 和 web worker 的区别
# Webassembly
简单介绍一下 webassembly
WebAssembly 的是将 C,C++, Rust 等静态语言通过编译器的程序编译成浏览器能够运行的 wasm 二进制文件,当浏览器加载 wasm 文件后编译为本地机器码后运行。
为什么能提升当前 js 的性能?
正常的 JS:在浏览器中,对 JavaScript 源码进行解析,生成抽象语法树或者字节码(parse),JIT 编译器会对生成的代码进行编译优化,当然后当发生去优化时,再去重新编译优化,最后执行。
WebAssembly:则省去了比较耗时的解析和编译的过程,是直接生成的二进制可执行机器码进行执行。
WebAssembly 适合的场景:
地图/图像/音频编辑 一些高性能的库 CAD 应用 游戏 科学的可视化和模拟
webassembly 大致使用的步骤?
对于前端同学而言直接使用 AssemblyScript 将 typescript 转换成 wasm 文件。
WebAssembly 代 码驻留在.wasm 文件中。这个文件应该被编译成特定于它所运行的机器的机器码。我们可以使用 WebAssembly.compile 方法来编译 WebAssembly 模块。
WebAssembly.instantiate 方法实例化已编译模块。 另外,我们也可以从.wasm 文件获得的数组缓冲区传递到 WebAssembly.instantiate 方法中。 这也适用,因为实例化方法有两个重载。
let exports; fetch("sample.wasm") .then((response) => response.arrayBuffer()) .then((bytes) => WebAssembly.instantiate(bytes)) .then((results) => { exports = results.instance.exports; });
上述方法的缺点之一是这些方法不能直接访问字节码,因此在编译/实例化 wasm 模块之前,需要采取额外的步骤将响应转换为 ArrayBuffer。
相反,我们可以使用
WebAssembly.compileStreaming / WebAssembly.instantiateStreaming
方法来实现与上述相同的功能,其优点是可以直接访问字节码,而无需将响应转换为 ArrayBuffer。let exports; WebAssembly.instantiateStreaming(fetch("sample.wasm")).then((obj) => { exports = obj.instance.exports; });
注意,WebAssembly.instantiate 和 WebAssembly.instantiateStreaming 会返回实例以及已编译的模块,它们可用于快速启动模块的实例。
let exports; let compiledModule; WebAssembly.instantiateStreaming(fetch("sample.wasm")).then((obj) => { exports = obj.instance.exports; //access compiled module compiledModule = obj.module; });
详情请见: https://cloud.tencent.com/developer/article/1746970
# Vue
# 介绍一下 Vue 响应式原理
答:Object.defineProperty,使用 set 和 get 方法,
# 组件间通信的几种方式
https://mrgaogang.github.io/vue/%E4%BD%A0%E6%89%80%E5%BF%BD%E7%95%A5%E7%9A%84Vue.html#%E5%85%AD%E3%80%81-vue%E7%88%B6%E5%AD%90%E7%BB%84%E4%BB%B6%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E8%B0%83%E7%94%A8%E6%AC%A1%E5%BA%8F
# 你对虚拟 DOM 原理的理解?
https://user-gold-cdn.xitu.io/2019/8/1/16c49afec13e0416
# Vue 父子组件生命周期调用次序
# 介绍一下 vuex
# vuex 中 module 的动态注册怎么实现
不知道。
# 介绍一下 Vue3.0
不知道
# 介绍一下 Proxy
# Vue 3.0 和 2.0 的区别
- 组合式 API
- Teleport
- 片段
- 触发组件选项
- 来自 @vue/runtime-core 的 createRenderer API 创建自定义渲染器
- 单文件组件组合式 API 语法糖 (
<script setup>
) 实验性 - 单文件组件状态驱动的 CSS 变量 (
<style vars>
) 实验性 - 单文件组件 <
style scoped
> 现在可以包含全局规则或只针对插槽内容的规则
# React
# 1. 介绍一下 React 组件间通信的常用方式
不知道;没有做过
# 2. 介绍一下 Redux 如何做状态管理
# 3. react 和 vue 的区别
# 4. redux 异步 action 方案
答:
redux-thunk
- 手写一下?
redux-promise
# redux 和 mobx 的区别和使用场景?
https://juejin.cn/post/6844903562095362056
- 函数式和面向对象
- 单一 store 和多 store
- JavaScript 对象和可观察对象
- 不可变(Immutable)和可变(Mutable
# React Hooks 的闭包问题以及如何修复
http://blog.dangosky.com/2019/11/16/React-Hook-%E4%B8%AD%E7%9A%84%E9%97%AD%E5%8C%85%E9%99%B7%E9%98%B1/
- 添加依赖项
- useState 更新使用函数方式
- 使用 useRef
- 使用 useReducer
# redux 的三大原则?
单一数据源: 整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。
State 是只读的: 唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。
使用纯函数来执行修改: 为了描述 action 如何改变 state tree ,你需要编写 reducers。
https://www.redux.org.cn/docs/basics/Reducers.html
# redux 为什么要求数据不可变?
# React-Redux 是如何使用浅比较的?
React-Redux 使用浅比较来决定它包装的组件是否需要重新渲染。
首先 React-Redux 假设包装的组件是一个“纯”(pure)组件,即给定相同的 props 和 state,这个组件会返回相同的结果。
做出这样的假设后,React-Redux 就只需检查根 state 对象或 mapStateToProps 的返回值是否改变。如果没变,包装的组件就无需重新渲染。
为了检测改变是否发生,React-Redux 会保留一个对根 state 对象的引用,还会保留 mapStateToProps 返回的 props 对象的每个值的引用。
最后 React-Redux 会对根 state 对象的引用与传递给它的 state 对象进行浅比较,还会对每个 props 对象的每个值的引用与 mapStateToProps 返回的那些值进行一系列浅比较。
# React-Redux 是如何使用浅比较来决定组件是否需要重新渲染的?
http://cn.redux.js.org/docs/faq/ImmutableData.html#how-react-redux-uses-shallow-checking
# 介绍一下 Redux 中间件原理
https://mrgaogang.github.io/react/Redux%E4%B8%AD%E9%97%B4%E4%BB%B6%E8%AF%A6%E8%A7%A3.html#_1%E3%80%81-%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84-applymiddleware
# diff 算法(最新的)
16 及以后的: https://cloud.tencent.com/developer/article/1477707
15 版本的: https://zhuanlan.zhihu.com/p/20346379?refer=purerender
15 及 16 的区别: https://blog.csdn.net/halations/article/details/109284050
# 简单介绍一下 Fiber
https://mrgaogang.github.io/react/Fiber%E7%9A%84%E7%90%86%E8%A7%A3.html
完全理解 React Fiber: http://www.ayqy.net/blog/dive-into-react-fiber/
# 计算机网络
# DNS 解析流程
https://juejin.im/post/6854573212425814030
# tcp 和 udp 的区别和使用场景?
TCP 和 UDP 区别:
- 面向连接 vs 无连接
TCP 有三次握手的连接过程,UDP 适合消息的多播发布,从单个点向多个点传输消息
- 可靠性
TCP 利用握手, ACK 和重传的机制,提供了可靠性保证,而 UDP 可能丢失,不知道到底有没有接收
- 有序性:
TCP 利用序列号保证了消息包的的顺序交付,到达可能无序,但 TCP 会排序
4 . 速度:
TCP 速度比较慢,因为要创建连接,保证消息的可靠性和有序性等,需要做额外的很多事情,UDP 更适合对速度比较敏感的应用,比如在线视频媒体,电视广播,多人在线游戏等。
5.重量级
TCP 重量级,UDP 轻量级,体现在元数据的头大小是,TCP 20 字节,UDP 8 字节
# http1.0、http1.1、http2.0 的区别
http1.x 相比 http1.0:
缓存处理,在 HTTP1.0 中主要使用 header 里的 If-Modified-Since,Expires 来做为缓存判断的标准,HTTP1.1 则引入了更多的缓存控制策略例如 Entity tag,If-Unmodified-Since, If-Match, If-None-Match 等更多可供选择的缓存头来控制缓存策略。 带宽优化及网络连接的使用,HTTP1.0 中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
错误通知的管理,在 HTTP1.1 中新增了 24 个错误状态响应码,如 409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
Host 头处理,在 HTTP1.0 中认为每台服务器都绑定一个唯一的 IP 地址,因此,请求消息中的 URL 并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个 IP 地址。HTTP1.1 的请求消息和响应消息都应支持 Host 头域,且请求消息中如果没有 Host 头域会报告一个错误(400 Bad Request)。
长连接,HTTP 1.1 支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个 TCP 连接上可以传送多个 HTTP 请求和响应,减少了建立和关闭连接的消耗和延迟,在 HTTP1.1 中默认开启 Connection: keep-alive,一定程度上弥补了 HTTP1.0 每次请求都要创建连接的缺点。
HTTP2.0 和 HTTP1.X 相比的新特性
新的二进制格式(Binary Format),HTTP1.x 的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认 0 和 1 的组合。基于这种考虑 HTTP2.0 的协议解析决定采用二进制格式,实现方便且健壮。
多路复用(MultiPlexing),即连接共享,即每一个 request 都是是用作连接共享机制的。一个 request 对应一个 id,这样一个连接上可以有多个 request,每个连接的 request 可以随机的混杂在一起,接收方可以根据 request 的 id 将 request 再归属到各自不同的服务端请求里面。
header 压缩,如上文中所言,对前面提到过 HTTP1.x 的 header 带有大量信息,而且每次都要重复发送,HTTP2.0 使用 encoder 来减少需要传输的 header 大小,通讯双方各自 cache 一份 header fields 表,既避免了重复 header 的传输,又减小了需要传输的大小。
服务端推送(server push),同 SPDY 一样,HTTP2.0 也具有 server push 功能。
# 常用的 HTTP 状态码
https://mrgaogang.github.io/interview/Http%E9%9D%A2%E8%AF%95%E6%B1%87%E6%80%BB.html#%E5%B8%B8%E7%94%A8%E7%9A%84http%E7%8A%B6%E6%80%81%E7%A0%81
# http 三次握手,若第三次握手失败,客户端和服务端分别怎么处理?
TCP 三次握手流程如下: 如果第三次握手失败怎么办呢?
server 端发送了 SYN+ACK 报文后就会启动一个定时器,等待 client 返回的 ACK 报文。 如果第三次握手失败的话 client 给 server 返回了 ACK 报文,server 并不能收到这个 ACK 报文。那么 server 端就会启动超时重传机制,超过规定时间后重新发送 SYN+ACK,重传次数根据/proc/sys/net/ipv4/tcp_synack_retries 来指定,默认是 5 次。 如果重传指定次数到了后,仍然未收到 ACK 应答,那么一段时间后,server 自动关闭这个连接。但是 client 认为这个连接已经建立,如果 client 端向 server 写数据,server 端将以 RST 包响应
# 前端缓存
https://github.com/ljianshu/Blog/issues/23
缓存的位置
- Memory Cache
- Push Cache
- Disk Cache
- Service Work
本地没有缓存进行请求
强缓存
no-cache 和 no-store 的区别
no-cache:客户端缓存内容,是否使用缓存则需要经过协商缓存来验证决定。表示不使用 Cache-Control 的缓存控制方式做前置验证,而是使用 Etag 或者 Last-Modified 字段来控制缓存。需要注意的是,no-cache 这个名字有一点误导。设置了 no-cache 之后,并不是说浏览器就不再缓存数据,只是浏览器在使用缓存数据时,需要先确认一下数据是否还跟服务器保持一致。
no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存
Expires 和 Cache-Control 的区别
其实这两者差别不大,区别就在于 Expires 是 http1.0 的产物,Cache-Control 是 http1.1 的产物,两者同时存在的话,Cache-Control 优先级高于 Expires;在某些不支持 HTTP1.1 的环境下,Expires 就会发挥用处。所以 Expires 其实是过时的产物,现阶段它的存在只是一种兼容性的写法。
协商缓存
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要有以下两种情况
协商缓存生效,返回 304 和 Not Modified 协商缓存失效,返回 200 和请求结果
协商缓存可以通过设置两种 HTTP Header 实现:Last-Modified 和 ETag 。
# CDN 原理
https://gaogangsever.cn/javascript/cdn%E4%BB%8B%E7%BB%8D.html#%E5%8A%A0%E9%80%9F%E5%8E%9F%E7%90%86
# 前端跨域及解决方案
https://mrgaogang.github.io/javascript/proxy.html
# 前端安全
XSS
CSRF
出现场景
攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的
特点
攻击一般发起在第三方网站,而不是被攻击的网站。被攻击的网站无法防止攻击发生。 攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作;而不是直接窃取数据。 整个过程攻击者并不能获取到受害者的登录凭证,仅仅是“冒用”。 跨站请求可以用各种方式:图片 URL、超链接、CORS、Form 提交等等。部分请求方式可以直接嵌入在第三方论坛、文章中,难以进行追踪。
解决方案
阻止不明外域的访问 。同源检测 。 Samesite Cookie 提交时要求附加本域才能获取的信息 。CSRF Token 。双重 Cookie 验证
DDos 攻击
# Webpack
https://juejin.cn/post/6844904094281236487#heading-1
# 有哪些常见的 Plugin?你用过哪些 Plugin?
define-plugin
:定义环境变量 (Webpack4 之后指定 mode 会自动配置)ignore-plugin
:忽略部分文件html-webpack-plugin
:简化 HTML 文件创建 (依赖于 html-loader)web-webpack-plugin
:可方便地为单页应用输出 HTML,比 html-webpack-plugin 好用terser-webpack-plugin
: 支持压缩 ES6 (Webpack4),开启多进程压缩 JS 文件webpack-parallel-uglify-plugin
: 多进程执行代码压缩,提升构建速度mini-css-extract-plugin
: 分离样式文件,CSS 提取为独立文件,支持按需加载 (替代 extract-text-webpack-plugin)css-minimizer-webpack-plugin
: 移除无用的 css 代码HotModuleReplacementPlugin
: webpack 热更新serviceworker-webpack-plugin
:为网页应用增加离线缓存功能clean-webpack-plugin
: 目录清理ModuleConcatenationPlugin
: 开启 Scope Hoistingspeed-measure-webpack-plugin
: 可以看到每个 Loader 和 Plugin 执行耗时 (整个打包耗时、每个 Plugin 和 Loader 耗时)webpack-bundle-analyzer
: 可视化 Webpack 输出文件的体积 (业务组件、依赖第三方模块)
# 有哪些常见的 loader,简单介绍一下各个 loader 的作用
https://juejin.cn/post/6942322281913778206
# Loader 和 Plugin 的区别?
Loader 本质就是一个函数,在该函数中对接收到的内容进行转换,返回转换后的结果。 因为 Webpack 只认识 JavaScript,所以 Loader 就成了翻译官,对其他类型的资源进行转译的预处理工作。 Plugin 就是插件,基于事件流框架 Tapable,插件可以扩展 Webpack 的功能,在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。
Loader
loader 使用:
当链式调用多个 loader 的时候,它们会以相反的顺序执行。取决于数组写法格式,从右向左或者从下向上执行。
最后的 loader 最早调用,将会传入原始资源内容。 第一个 loader 最后调用,期望值是传出 JavaScript 和 source map(可选)。 中间的 loader 执行时,会传入前一个 loader 传出的结果。
loader 开发: loader 是导出为一个函数的 node 模块。该函数在 loader 转换资源的时候调用。给定的函数将调用 loader API,并通过 this 上下文访问 options 的获取通常是使用 loader-utils 这个库 支持同步和异步回调,同步直接返回 return 异步则是使用 callback 回调
Plugins
插件的开发,直接返回一个函数,且在插件开发中最重要的两个资源就是 compiler 和 compilation 对象:
compiler 暴露了和 Webpack 整个生命周期相关的钩子。 钩子的地址为: https://www.webpackjs.com/api/compiler-hooks/#hooks
compilation 对象代表了一次资源版本构建。当运行 webpack 开发环境中间件时,每当检测到一个文件变化,就会创建一个新的 compilation,从而生成一组新的编译资源。一个 compilation 对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态信息。compilation 对象也提供了很多关键时机的回调,以供插件做自定义处理时选择使用。
# Webpack 构建流程简单说一下?
Webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程:
- 初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数
- 开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译
- 确定入口:根据配置中的 entry 找出所有的入口文件
- 编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理
- 完成模块编译:在经过上一步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系
- 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会;
- 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统在;
以上过程中,Webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 Webpack 提供的 API 改变 Webpack 的运行结果。
https://juejin.cn/post/6844904038543130637
# 用过哪些可以提高效率的插件?
# source map 是什么?生产环境怎么用?
# Webpack 的热更新原理?
https://zhuanlan.zhihu.com/p/30669007
# 如何对 bundle 体积进行监控和分析?
# 如何优化 Webpack 的构建速度?
# 介绍一下 webpack 异步加载原理
https://mrgaogang.github.io/javascript/webpack/webpack%E6%A8%A1%E5%9D%97%E5%BC%82%E6%AD%A5%E5%8A%A0%E8%BD%BD%E5%8E%9F%E7%90%86%E8%A7%A3%E6%9E%90.html#%EF%BC%88%E4%BA%8C%EF%BC%89%E5%88%9D%E8%AF%86-bundle-js
# 介绍一下 webpack 如何实现缓存
hash,content-hash 和 chunk-hash 的区别
# Babel 插件原理
解析:将代码转换成 AST
词法分析:将代码(字符串)分割为 token 流,即语法单元成的数组语法分析:分析 token 流(上面生成的数组)并生成 AST 转换:访问 AST 的节点进行变换操作生产新的 AST
Taro 就是利用 babel 完成的小程序语法转换 生成:以新的 AST 为基础生成代码
# RN
# RN 组件生命周期
# shouldComponentUpdate 应该做什么
# 讲述一下 RN Native 和 js 是如何通信的?
# RN 如何进行 module 依赖收集的
# 性能优化
# 如何定义白屏时间
# 图片懒加载实现原理
# 虚拟列表的实现?
https://juejin.cn/post/6844903695281307662#heading-3
# 函数防抖和节流
# 介绍一下常用的性能优化手段
# 回流和重绘的区别
# 效率提升
# 组件封装原则
https://juejin.cn/post/6844904032700481550
- 单一职责
- 通用性
- 封装
- 组合
- 可测试
- 扁平化设计
- 富有意义
# Android/iOS
# Android 是如何和 JS 进行通信的
https://mrgaogang.github.io/interview/webview-js.html#%E4%BA%A4%E4%BA%92%E6%96%B9%E5%BC%8F%E6%80%BB%E7%BB%93
# iOS 如何和 js 通信
https://mrgaogang.github.io/ios/webview/#%E4%B8%80%E3%80%81wkwebview-%E7%9A%84-14-%E4%B8%AA%E7%B1%BB%E5%92%8C-3-%E4%B8%AA%E5%8D%8F%E8%AE%AE
# 前端工程化
# CI/CD
# 脚手架
# 统一入口/cli
常用的工具
- chalk 终端带有颜色的输出
- bunyan: 日志打印到终端
- cross-spawn: 跨平台启动子进程执行命令
- osenv: 跨平台获取环境变量参数
- inquirer: 给用户的命令式交互工具
- minimist: 命令参数解析
- js-yaml: js 解析 yaml 文件
- command-line-usage: 简单的命令说明使用工具
# 前端监控
# 统一联调
# 日志上报
# 流水线
# 单元测试/E2E 测试
# 移动相关
# 如何解决移动端 300ms 点击延迟?其 fastClick 解决原理时什么
# 常用移动 1px 像素解决方案
# 其他
# 1. 你认为在工作中做的最好的一次项目是什么?你承担的什么角色?
# 在日常开发中有做过什么项目开发效率的东西吗?比如 vscode/idea 插件等待
# 2. 是否还有其他问题
# 看过那些书?
# 怎么获取信息
- 本文链接: https://mrgaogang.github.io/interview/%E9%9D%A2%E8%AF%95%E9%A2%98%E9%A2%98%E7%9B%AE.html
- 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 许可协议。转载请注明出处!