本周有位群友说我不应该为了面试而背题,我很认同他的说法,这里想表达下我建立这个专栏的初衷吧。 当然,以上只是我个人观点。 值新的一岁之际,希望自己可以:勤思考,多动手,善总结,能坚持。 建了一个公众号,每周周一 至 周五,每天发布若干道面试题,并奉上个人觉得还行的解答,周五(周末发好像点击率真的有点低)、周六或周天发一遍汇总~。 希望大家有所得,希望自己有所得。下面是本周的汇总(2020.08.03 - 2020.08.07)。 所谓 loader 只是一个导出为函数的 JavaScript 模块。 webpack 中的 loader runner 会调用这个函数,然后把上一个 loader 产生的结果或者资源文件(resource file)传入进去。函数的 this 上下文将由 webpack 填充,并且 webpack 的 loader runner 具有一些有用方法,可以使 loader 改变为异步调用方式,或者获取 query 参数。 编写 Loader 时要遵循单一 z 职责,每个 Loader 只做一种"转义"工作。 每个 Loader 的拿到的是源文件内容(source),可以通过返回值的方式将处理后的内容输出,也可以调用 this.callback()方法,将内容返回给 webpack。 还可以通过 this.async()生成一个 callback 函数,再用这个 callback 将处理后的内容输出出去。 此外 webpack 还为开发者准备了开发 loader 的工具函数集——loader-utils。 参考 / 来源: 官网 webpack 在运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 webpack 提供的 API 改变输出结果。 官网 大多数 JavaScript Parser 遵循 estree 规范,Babel 最初基于 acorn 项目(轻量级现代 JavaScript 解析器)Babel 大概分为三大部分: 解析:将代码(其实就是字符串)转换成 AST 转换:访问 AST 的节点进行变换操作生产新的 AST 生成:以新的 AST 为基础生成代码 详细一点: 面试官: 聊一聊 Babel 优化开发体验 首先说下衡量手段:speed-measure-webpack-plugin,监控构建过程中,loader 和 plugin 的执行时长 使用 高版本 的 webpack 和 node.js 缩小文件搜索范围 使用 DLLPlugin 使用 HappyPack(不维护了)、thread-loader 使用 ParallelUglifyPlugin 充分利用缓存提升二次构建速度 优化输出质量 区分环境,不同环境使用的配置不相同 压缩代码: 多进程并行压缩 通过 mini-css-extract-plugin 提取 Chunk 中的 CSS 代码到单独文件,通过 css-loader 的 minimize 选项开启 cssnano 压缩 CSS。 Tree Shaking:删除没用到的代码 - 打包过程中检测工程中没有引用过的模块并进行标记,在资源压缩时将它们从最终的 bundle 中去掉(只能对 ES6 Modlue 生效) 开发中尽可能使用 ES6 Module 的模块,提高 tree shaking 效率- 禁用 babel-loader 的模块依赖解析,否则 Webpack 接收到的就都是转换过的 CommonJS 形式的模块,无法进行 tree-shaking- 使用 PurifyCSS(不在维护) 或者 uncss 去除无用 CSS 代码 - purgecss-webpack-plugin 和 mini-css-extract-plugin 配合使用(建议)复制代码 提取公共代码 基础包分离: 按需加载 prepack Scope Hoisting 图片压缩: imagemin、image-webpack-loader 参考 / 来源: CDN 的全称是 Content Delivery Network,即 内容分发网络。 工作原理:将源码的资源缓存到位于全国各地的 CDN 节点上,用户请求资源时,就近返回节点上缓存的资源,而不需要每个用户的请求都回源站点获取,避免网络拥塞、分担源站压力,保证用户访问资源的速度和体验。 为什么要用 CDN 代理是在服务器和客户端之间假设的一层服务器,代理将接收客户端的请求并将它转发给服务器,然后将服务端的响应转发给客户端。 不管是正向代理还是反向代理,实现的都是上面的功能。 正向代理,意思是一个位于客户端和原始服务器之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并制定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。 正向代理 是为我们服务的,即为客户端服务,客户端可以根据正向代理访问到它本身无法访问到的服务器资源。 正向代理 是对我们是透明的,对服务端是非透明的,即服务端并不知道自己收到的是来自代理的访问还是来自真实客户端的访问。 反向代理 方式是指以代理服务器来接受连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给客户端。 反向代理 是为服务端服务的,反向代理可以帮助服务器接收来自客户端的请求,帮助服务器做请求转发,负载均衡等。 反向代理 对服务端是透明的,对客户端是非透明的,即客户端并不知道自己访问的是代理服务器,而服务器知道反向代理在为他服务。 参考 / 来源: 公众号:code 秘密花园 - 前端开发者必备的 nginx 知识 js 事件模型主要分为 3 种:原始事件模型、DOM2 事件模型、IE 事件模型 这是一种被所有浏览器都支持的事件模型,对于原始事件而言,没有事件流,事件一旦发生将马上进行处理,有两种方式可以实现原始事件: <!-- 在 html 代码中直接指定属性值 --><button onclick="doSomeTing()">test</button><script> // 在 js 代码中 document.getElementsById('demo').onclick = doSomeTine();</script>复制代码 优点:所有浏览器都兼容缺点: 此模型是 W3C 指定的标准模型,现代浏览器(IE6 ~ IE8 除外)都已经遵循这个规范。 W3C 制定的事件模型中,一次事件的发生包含三个过程: 事件捕获:当某个元素触发某个事件(如 onclick),顶层对象 document 就会发出一个事件流,随着 DOM 树的节点向目标元素节点流去,直到到达事件真正发生的目标元素。在这个过程中,事件相应的监听函数是不会触发的。 事件目标:当到达目标元素之后,执行目标元素该事件相应的处理函数。 事件冒泡:从目标元素开始,往顶层元素传播。途中如果有节点绑定了相应的事件处理函数,这些函数都会被依次触发。 所有的事件类型都会经历事件捕获,但是只有部分事件会经历事件冒泡阶段,例如 submit 事件就不会冒泡。 在 W3C 中,使用 stopPropagation() 方法阻止事件传播,在捕获的过程中 stopPropagation() 后,后面的冒泡过程就不会发生了。 用法: // eventType: 事件类型,例如 click// 第二个参数,处理函数 handler// 第三个参数用来指定是否在捕获阶段进行处理,一般设为 false 或不传addEventListener('eventType', 'handler', 'true|false');复制代码 IE 不把该对象传入事件处理函数,由于在任意时刻只会存在一个事件,所以 IE 把它作为全局对象 window 的一个属性。 用法 document.getElementById('demo').attachEvent('onclick', func);复制代码 传统的事件处理中,我们为每一个需要触发事件的元素添加事件处理器,但是这种方法将可能会导致内存泄露或者性能下降(特别是通过 ajax 获取数据后重复绑定事件,总之,越频繁风险越大)。事件代理在 js 中是一个非常有用的功能,我们将事件处理器绑定到一个父级元素上,避免了频繁的绑定多个子级元素,依靠事件冒泡机制与事件捕获机制,子元素的事件将委托给父级元素。 函数组件的性能比类组件性能高,因为类组件在使用时要实例化,而函数组件之间调用函数取返回结果即可。 函数组件没有 this、生命周期、state 初始化阶段 挂载阶段 更新阶段 组件卸载 错误处理 废弃的原因主要是因为 react 在 16 版本重构了调度算法,新的调度可能会导致一些生命周期被反复调用,所以在 16 中就不建议使用了,而改在其他时机中暴露出其他生命周期钩子用来替代。 Portal(传送门),提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的方案。 常见使用场景 使用方法 render() { return ReactDOM.createProtal( <div>{this.props.children}</div>, body )}复制代码 React 的 StrictMode 是一种辅助组件,可以帮助我们编写更好的 React 组件,可以使用 <StrictMode />包装一组组件,并且可以帮我们做一下检查: 纯函数是不依赖并且不会在其作用域外修改变量状态的函数。本质上,纯函数始终在给定相同参数的情况下返回相同的结果。 纯组件是通过控制 sholdComponentUpdate 生命周期函数,减少 render 渲染次数来减少性能损耗的。 PureComponent 浅比较出现的问题的解决方案: 建议放在 componentDidMount() 中。 不能放在 render() 中,因为会重复调用 不能放在 componentWillMount() 中,会与 RN 等其它框架冲突,而且该生命周期已经不安全,即将弃用。 也可以写在构造函数 constructor() 之中,但是不建议这样做 React 根据 W3C 规范定义了每个事件处理函数的参数,即事件合成。 为什么要合成事件机制? 前端的世界纷繁复杂,远非笔者所能勾画,部分面试题不是靠背诵记忆就能掌握的,希望我摘录的、总结的简单答案可以引起读者的兴趣,闲暇时可以自己深入总结,如果读者有更好的答案,或有想了解的题目,欢迎留言。 笔者新建了一个 github 仓库,对公众号内发布的面试题做进一步分类,同时也会在周六同步本周题目、公布下周问题,欢迎大家关注~ 想要实时关注笔者最新的文章和最新的文档更新请关注公众号前端地基,后续的文章会优先在公众号更新. github:关注笔者最新的仓库写在前面
目录
详情
一、是否写过 Loader?简单描述一下编写 loader 的思路?
关于 webpack 的面试题
「吐血整理」再来一打 Webpack 面试题二、是否写过 Plugin?简单描述一下编写 Plugin 的思路?
「吐血整理」再来一打 Webpack 面试题三、聊一聊 Babel 原理吧
ES6、7 代码输? -> babylon 进?解析 -> 得到 AST (抽象语法树)->plugin ? babel-traverse 对 AST 树进?遍历转译 -> 得到新的 AST 树 -> ? babel-generator 通过 AST 树?成 ES5 代码
「吐血整理」再来一打 Webpack 面试题四、在项目中,如何优化 Webpack
优化构建速度
优化使用体验
减少用户能感知到的加载时机,也就是首屏加载速度
提升流畅度,也就是提升代码性能
官网Webpack 优化
「吐血整理」再来一打 Webpack 面试题
Webpack 优化——将你的构建效率提速翻倍五、CDN 是什么?描述下 CDN 原理?为什么要用 CDN?
六、说一下正向代理和反向代理
正向代理(VPN)
反向代理(Nginx)
七、说一下事件模型、事件流和事件代理
原始事件模型(DOM0 级)
DOM2 事件模型
IE 事件模型
事件代理
八、「react」React 中函数组件和普通组件有什么区别
九、「react」说一下 React 生命周期,以及新版本中都有哪些改变,为什么去掉了那几个旧的生命周期
十、「react」知道 Portal 吗,有哪些使用场景?
十一、「react」 React 中 StrictMode (严格模式) 是什么?
十二、「react」什么是纯函数 && 什么是纯组件
十三、「react」请求接口放在哪个生命周期
十四、「react」React 事件合成机制是什么?为什么要合成?
写在最后
作者:同学请留步
链接:https://juejin.im/post/6858139075807805453
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。