# 一、阿里面试题

# 1.使用过的 koa2 中间件

  • koa-router:koa.js 为了保持自身的精简,并没有像 Express.js 自带了路由功能,因此 koa-router 做了很好的补充,koa-router 提供了全面的路由功能,比如类似 Express 的 app.get/post/put 的写法,URL 命名参数,路由命名,支持加载多个中间件,嵌套路由等。
  • koa-bodyparse:kao.js 并没有内置 Request Body 的解析器,当我们需要解析请求体时需要加载额外的中间件,官方提供的 koa-bodyparser 是个不错的选择,支持 x-www-form-urlencoded,application/json 等格式的请求体,但不支持 form-data 的请求体积,需要借助 formidable 这个库,也可以直接使用 koa-body 或 koa-better-body
  • koa-views:koa-views 对需要进行视图模板的渲染应用是个不可缺少的中间件,支持 ejs,nunjucks 等众多模板引擎
  • koa-static:node.js 除了处理动态请求,也可以用做类似 nginx 的静态文件服务,在本地开发特别方便,可以用于加载前端文件或后端 fake 数据,可结合 koa-compress 和 koa-mount 使用
  • koa-session:http 是无状态协议,为了保持用户状态,我们一般使用 session 会话,koa-session 提供了这样的功能,既支持将会话信息存储在本地 cookie,也支持存储在如 redis,mongodb 这样的外部存储设备
  • koa-jwt:随着网站前后端分离方案的流行,越来越多的网站从 session base 转为使用 token base,jwt(json web tokens)作为一个开放的标准被很多网站采用,koa-jwt 这个中间件使用 jwt 认证 http 请求
  • koa-helmet:网站安全得到越来越多的重视,helmet 通过增加如 Strict-Transport-Security,X-Frame-Options 等 HTTP 头提高 Express 应用程序的安全性,koa-helmet 为 koa 程序提供了类似的功能,参考 Node.js 安全清单
  • koa-compress:当响应体比较大时,我们一般会启用类似 Gzip 的压缩技术减少传输内容,koa-compress 提供了这样的功能,可以根据需要进行灵活的配置
  • koa-logger:koa-logger 提供了输出请求日志的功能,包括请求的 url 状态码,响应时间,响应体大小等信息,对于调试和跟踪应用程序特别有帮助,koa-bunyan-logger 提供了丰富的功能
  • koa-convert:对于比较老的使用 gennerate 函数的 koa 中间件,官方提供了一个灵活的工具可以将他们转为基于 Promise 的中间件供 koa2 使用,同样可以将新的基于 Promise 的中间件转为旧式的 Generate 中间件

# 2.koa-body 原理

我记得我之前做过这样一个项目,一个后台服务系统,支持同时上传大量资源文件。当时我们针对这个服务,做了一个简单的单机集群。其实也就是借助了pm2,做了一些并发,将我们的上传服务速比之前提升了3倍

# 3.介绍自己写过的中间件

koa2 中间件在项目中的使用还是比较频繁的,我主要使用到了 koa-router、koa-session、koa-bodyparser 和 koa-static 等中间件。当然我也自己写过一些中间件,例如在项目中,我曾经写过接口请求及返回内容、耗时情况的日志记录中间件;风控拦截中间件;前端跨域代理等中间件。

# 4.有没有涉及到 Cluster

我记得我之前做过这样一个项目,一个后台服务系统,支持同时上传大量资源文件。当时我们针对这个服务,做了一个简单的单机集群。其实也就是借助了 pm2,做了一些并发。将我们的上传服务速度比较之前提升了 3 倍。

# 5.介绍 pm2

pm2,作为 node 应用的进程管理器。可以实现 node 对应用的启动、监控、日志。其内建了负载均衡,可以让我们的 node 应用充分利用我们的 cpu。其不光能够实现 node 应用进程的管理,也能管理一般的脚本程序。它甚至还有 deploy 功能,能够直接从本地部署我们的线上应用。非常强大的一款工具,我上家公司的上线打包工具就是基于 pm2 实现的, 通过一个命令即可完成项目的打包发布。

# 6.master 挂了的话 pm2 怎么处理

pm2 可以通过 fork 产生多个独立进程实例。 这些实例能够在 master 挂掉后,随时替代 master。

# 7.如何和 MySQL 进行通信

npm 提供了 mysql 的 node 应用。在项目中,项目中引入 mysql,通过调用 connect 方法,连接到远程数据库,拿到 connection 连接对象。 connect 连接对象,提供了增删改查 api,通过输入数据库脚本,完成与数据库的通信。 mysql 还提供了连接池对象,通过它可以直接完成 curd 操作,当然也可以复用已有的连接池,减少连接开销

# 8.React 生命周期及自己的理解

组件创建、更新、卸载三个阶段。创建时,依次顺序调用 constructor、getDerivedStateFromProps、render、componentDidMount 这四个生命周期函数,其中 getDerivedStateFromProps 主要用来将外部属性转换为自身状态,比较适用于组件既能被外部控制又能内部更新的场景。更新阶段,依次通过 getDerivedStateFromProps、shouldComponentUpdate、render、getSnapshotBeforeUpdate、componentDidUpdate 这个四个方法。 最后卸载时调用 componentWillUnMount 方法

# 9.如何配置 React-Router

配置 React-Router,概括起来就是有大概三种方式: 第一种,通过标签形式,例如 Router 这样的标签,通过这样的标签来引入我们的组件,最后 render 的时候返回这样的 Router 就好了,这种方式比较简单,但是不能做一些比较个性化的事情。 第二种,通过声明式配置的方式,声明一个对象,该对象是一个数组,可以更加灵活的配置我们的路由,可以配置我们跳转路由之前的操作,例如离开页面、进入页面,都能配置响应的回调事件。然后通过<Router routes={routerConfig} />这种方式来应用我们的配置。 第三种,按需加载的方式,在大型应用中,性能是一个很重要的问题,按需要加载 JS 是一种优化性能的方式。在 React router 中不仅组件是可以异步加载的,路由也是允许异步加载的。Route 可以定义 getChildRoutes,getIndexRoute 和 getComponents 这几个函数,他们都是异步执行的,并且只有在需要的时候才会调用。这种方式需要配合 webpack 中有实现代码拆分功能的工具来用

# 10.路由的动态加载模块

实现动态加载需要 webpack,babel-plugin-systax-dynamic-import 和 react-loadable, 具体配置如下。这样组件动态加载和 HMR 就都实现了。

# 11.服务端渲染 SSR

传统的服务端渲染 SSR,主要是通过在服务端组装 html,组装的 html 已经是结合了 css,并执行了 js,返回给客户端,直接就可以展示,客户端省去了解析 html 和渲染 css 的工作。在这种开发模式下,服务端与前端的分工变得模糊,前后端分离的目标并没有达到。虽然利于 SEO,但是服务端的压力比较大。 Node.js 技术浪潮袭来之后,服务端渲染主要有 node 中间件来完成了,这样保证了,前后端分工仍然明确。并且 node 技术框架下,有大量优秀的服务端渲染工具可以选择,例如中间件架构,我们可以选择的 express、koa、egg 等, 视图模版,我们有 pug(jade)、handlebars、art-template、ejs 等等工具, React 体系下有 next.js,Vue 体系下有 Nuxt.js。

# 12.介绍路由的 history

history 对象最初设计来表示窗口的浏览历史。但出于隐私方面的原因,history 对象不再允许脚本访问已经访问过的实际 url。唯一保持使用的功能只有 back、forward、go 方法。

  • window.history.pushState(stateObject,title,url)
    • 将当前 URL 和 history.state 加入到 history 中,并用新的 state 和 URL 替换当前,不会造成页面刷新。
    • 参数解释 stateObject // 与要跳转到 URL 对应的状态信息,没有特殊的情况下可以直接传{} title //现在大多浏览器不支持或忽略这个参数,我们在用的时候建议传一个空字符串 url // 这个参数提供了新历史记录的地址,它不一定是要绝对地址,也可以是相对的,不可跨域

# 13.介绍 Redux 数据流的流程

# 14.Redux 如何实现多个组件之间的通信,多个组件使用相同状态如何进行管理

使用状态提升的方式在多个组件之间共享数据,切记维持应用单项数据流和数据唯一来源原则

# 15.多个组件之间如何拆分各自的 state,每块小的组件有自己的状态,它们之间还有一些公共的状态需要维护,如何思考这块

状态提升,找到容器组件和展示组件,保证唯一数据源和单向数据,对于组件的拆分还要做到高内聚低耦合

# 16.使用过的 Redux 中间件

  • redux-thunk 中间件 改造 store.dispatch,解决异步操作
  • redux-promise 中间件 使得 store.dispatch 方法可以接受 Promise 对象作为参数
  • redux-logger 中间件 日志中间件

# 17.如何解决跨域的问题

  • 降级浏览器、jsonp、cors、nginx、proxy-middle-ware、websocket、name、hash、domain

# 18.常见 Http 请求头

  • Accept:浏览器可接受 MIME 类型
  • Accept-Charset:浏览器可接受的字符集
  • Accept-Encoding:浏览器能够进行解码的数据编码方式。
  • Accept-Language:浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到。
  • Authorization:授权信息,通常出现在对服务器发送的 WWW-Authenticate 头的应答中。
  • Connection:表示是否需要持久连接。
  • Content-Length:表示请求消息正文的长度。
  • Cookie:这是最重要的请求头信息之一。
  • From:请求发送者的 email 地址,由一些特殊的 web 客户程序使用,浏览器不会用到它。
  • Host:初始 URL 中的主机和端口。
  • if-Modified-Since:只有当所有的内容在指定的日期之后又经过修改才返回,否则返回 304"Not Modified"应答。
  • Pragma:指定"no-cache"值表示服务器必须返回一个刷新后的文档,即使它是代理服务器而且已经有了页面的本地拷贝页面。
  • Referer:包含一个 URL,用户从该 URL 代表的页面出发访问当前请求的页面。

# 19.移动端适配 1px 的问题

# 20.介绍 flex 布局

# 21.其他 css 方式设置垂直居中

  • 1.flex
<div class="parent">
  <div class="children">123</div>
</div>
1
2
3
.parent {
  width: 200px;
  height: 200px;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
1
2
3
4
5
6
7
8
  • 2.absolute+transform
<div class="parent">
  <div class="children"></div>
</div>
1
2
3
.parent {
  width: 200px;
  height: 200px;
  position: relative;
}
.chidlren {
  width: 10px;
  height: 10px;
  position: absolute;
  top: 50%;
  left: 50%;
  translate: transform(-50%, -50%);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
  • 3.absolute+margin auto
<div class="parent">
  <div class="children">123</div>
</div>
1
2
3
.parent {
  width: 200px;
  height: 200px;
  position: relative;
}
.children {
  width: 20px;
  height: 20px;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  margin: auto;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  • 4.absolute + 负 margin
<div class="parent">
  <div class="children">123</div>
</div>
1
2
3
.parent {
  width: 200px;
  height: 200px;
  position: relative;
}
.children {
  width: 20px;
  height: 20px;
  position: absolute;
  top: 50%;
  right: 50%;
  margin-left: -10px;
  margin-top: -10px;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  • 5.absolute + calc
<div class="parent">
  <div class="children">123</div>
</div>
1
2
3
.parent {
  width: 200px;
  height: 200px;
  position: relative;
}
.children {
  width: 20px;
  height: 20px;
  position: absolute;
  top: calc(50% - 10px);
  left: calc(50% - 10px);
}
1
2
3
4
5
6
7
8
9
10
11
12
  • 6.writing-mode
<div class="box">
  <div class="parent">
    <div class="children">123</div>
  </div>
</div>
1
2
3
4
5
.box {
  width: 200px;
  height: 200px;
  writing-mode: vertical-lr;
  text-align: center;
}
.father {
  writing-mode: horizontal-tb;
  display: inline-block;
  text-align: center;
  width: 100%;
}
.children {
  display: inline-block;
  margin: auto;
  text-align: left;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  • 7.table
<table>
  <tbody>
    <tr>
      <td class="parent">
        <div class="children">123</div>
      </td>
    </tr>
  </tbody>
</table>
1
2
3
4
5
6
7
8
9
.parent {
  width: 200px;
  height: 200px;
  text-align: center;
}
.children {
  display: inline-block;
}
1
2
3
4
5
6
7
8
  • table-cell
<div class="parent">
  <div class="children">123</div>
</div>
1
2
3
.parent {
  width: 200px;
  height: 200px;
  display: table-cell;
  text-align: center;
  vertical-align: middle;
}
.children {
  display: inline-block;
}
1
2
3
4
5
6
7
8
9
10
  • grid
<div class="parent">
  <div class="children">123</div>
</div>
1
2
3
.parent {
  width: 200px;
  height: 200px;
  display: grid;
}
.children {
  align-self: center;
  justify-self: center;
}
1
2
3
4
5
6
7
8
9
  • 10 lineHeight
<div class="parent">
  <div class="children">123</div>
</div>
1
2
3
.parent {
  width: 200px;
  height: 200px;
  line-height: 200px;
  text-align: center;
  font-size: 0;
}
.children {
  font-size: 16px;
  display: inline-block;
  vertical-align: middle;
  line-height: initial;
  text-align: left;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 22.居中为什么要使用 transform(为什么不使用 marginLeft/Top)

transform 会开启 gpu 加速渲染;marginLeft/Top 会引起页面 layout 回流和 repaint 重绘;因此从浏览器性能考虑,transform 会比 marign 更节省时间

# 23.使用过 webpack 里面哪些 plugin 和 loader

  • loader
    • style-loader
    • css-loader
    • less-loader
    • sass-loader
    • postcss-loader
    • autoprefixer-loader
    • file-loader
    • url-loader
    • html-minify-loader
    • babel-loader
  • plugins
    • providePlugin
    • commonsChunkPlugin
    • ExtractTextPlugin
    • NoErrorsPlugin
    • UglifyJsPlugin
    • HotModuleReplacementPlugin
    • HtmlWebpackPlugin

# 24.webpack 里面的插件是怎么实现的

# 25.dev-server 是怎么跑起来

# 26.项目优化

  • 压缩代码
  • 减少入口文件大小
  • 按需加载
  • 动态加载
  • 懒加载
  • 精灵图

# 27.抽取公共文件是怎么配置的

# 28.项目中如何处理安全问题

  • 转义字符
  • 使用验证码
  • 使用 token

# 29.怎么实现 this 对象的深拷贝

上次更新: 2022/6/29 上午12:09:44