技术咨询、项目合作、广告投放、简历咨询、技术文档下载 点击这里 联系博主

# 面试题题目

# 前端基础

# 介绍一下 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;
};
    1. 计算模块的绝对路径
  • 2 . 判断是否有缓存,如果有缓存则从缓存中读取

    1. 是否为内置模块,如果是内置模块则直接加载
    1. 生成模块实例,存入缓存
    1. 模块进行加载
    • 模块加载的原理,以 js 文件为例,首先是读取文件,然后使用 apply 函数进行执行 代码

      • js 模块读取
      • 使用 apply 执行,并注入 export,require 等属性
    1. 输出模块的 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 区别:

  1. 面向连接 vs 无连接

TCP 有三次握手的连接过程,UDP 适合消息的多播发布,从单个点向多个点传输消息

  1. 可靠性

TCP 利用握手, ACK 和重传的机制,提供了可靠性保证,而 UDP 可能丢失,不知道到底有没有接收

  1. 有序性:

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 Hoisting

  • speed-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. 是否还有其他问题

# 看过那些书?

# 怎么获取信息

【未经作者允许禁止转载】 Last Updated: 2/4/2024, 6:06:40 AM