七、Webpack
Webpack 的理解
- Webpack 是一个现代的 JavaScript 应用程序的静态模块打包工具。
- 它将应用程序的所有模块视为一个依赖关系图,并生成一个或多个代码包 (bundler),这些文件可以在浏览器中加载。
- Webpack 主要用于处理 JavaScript 文件,但也可以处理许多其他类型的文件,如样式表、图片等。
Webpack 核心概念
- Entry: 入口文件,
Webpack
会从该文件开始进行分析与编译; - Output: 出口路径,打包后创建
bundler
的文件路径以及文件名; - Module: 模块,在
Webpack
中任何文件都可以作为一个模块,会根据配置的不同的Loader
进行加载和打包; - Chunk: 代码块,可以根据配置,将所有模块代码合并成一个或多个代码块,以便按需加载,提高性能;
- Loader: 模块加载器,进行各种文件类型的加载与转换;
- Plugin: 拓展插件,可以通过
Webpack
相应的事件钩子,介入到打包过程中的任意环节,从而对代码按需修改;
Webpack 打包原理
- 初始化参数:从配置文件和
Shell
语句中读取与合并参数,得出最终的参数 - 开始编译:用上一步得到的参数初始化
Compiler
对象,加载所有配置的插件,执行对象的run
方法开始执行编译 - 确定入口:根据配置中的
entry
找出所有的入口文件 - 编译模块:从入口文件出发,调用所有配置的
Loader
对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理 - 完成模块编译:在经过第
4
步使用Loader
翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系 - 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的
Chunk
,再把每个Chunk
转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会 - 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统
Webpack 主要功能
- 模块打包:将应用程序的所有模块打包成一个或多个bundle文件。
- 代码转换:使用loader将不同类型的文件转换为JavaScript代码。
- 代码分割:将应用程序拆分成多个bundle,以实现按需加载。
- 资源管理:处理应用程序中的静态资源,如样式表、图片等。
- 插件系统:通过插件扩展Webpack的功能,如压缩代码、代码分析等。
Webpack 工作流程
- 读取配置文件,按命令 初始化 配置参数,创建
Compiler
对象; - 调用插件的
apply
方法 挂载插件 监听,然后从入口文件开始执行编译; - 按文件类型,调用相应的
Loader
对模块进行编译,并在合适的时机点触发对应的事件,调用Plugin
执行,最后再根据模块依赖查找到所依赖的模块,递归执行第三步; - 将编译后的所有代码包装成一个个代码块 (
Chunk
), 并按依赖和配置确定 输出内容。这个步骤,仍然可以通过Plugin
进行文件的修改; - 最后,根据
Output
把文件内容一一写入到指定的文件夹中,完成整个过程;
Webpack 热更新原理(HMR)
-
什么是 Webpack 热更新
- Webpack 热更新(Hot Module Replacement,HMR)是一种在开发过程中提供实时更新的技术,它可以使开发人员在保持应用程序状态的同时,替换、添加或删除模块,从而实现快速的开发体验。
- HMR 的核心是客户端从服务端拉取更新后的文件。
-
原理
- 建立 WebSocket 连接。Webpack 编译时会在打包的输出中注入一段客户端运行时代码,这段代码会与开发服务器建立 WebSocket 连接,用于实时通信。
- 监听文件变化。当开发者修改了源代码并保存时,Webpack 检测到文件的变化,会重新编译修改的模块,并将更新的模块代码通过 WebSocket 推送到客户端。
- 重新编译模块。客户端接收到更新的模块代码后,会使用模块热替换(Hot Module Replacement)技术来替换对应的模块,而不刷新整个页面。这样就实现了实时更新的效果。
- 应用更新。在替换模块的过程中,Webpack HMR 会尽可能保留应用程序的状态,以确保开发者在调试过程中不会丢失当前的状态。
-
作用
- Webpack 热更新利用了 WebSocket 技术实现了开发代码的实时更新,使开发者可以在修改代码后立即看到效果,提高了开发效率。
- HMR 的优点在于可以保存应用的状态,提高开发效率,相对于 Live Reload 整体刷新页面的方案,HMR 在不需要刷新整个页面的情况下,可以实现局部更新页面。
为什么 Vite 比 Webpack 快
- 主要是因为它采用了不同的开发模式,充分利用了现代浏览器的 ES Modules 支持,使用了更高效的底层语言,并优化了热更新的处理。
- 这些特点使得 Vite 在大型项目中具有显著的优势,能够快速启动和构建,提高开发效率。
- 开发者模式的差异
- 在开发环境中,Webpack 是先打包再启动服务器。这会增加启动时间和构建时间。
- Vite 则是直接启动,然后再按需编译依赖文件。
- 对 ES Modules 的支持
- 现代浏览器本身就支持 ES Modules,会主动发起请求去获取所需文件。
- Vite充分利用了这一点,将开发环境下的模块文件直接作为浏览器要执行的文件,
- 而不是像 Webpack 那样先打包,再交给浏览器执行。
- 这种方式减少了中间环节,提高了效率。
- 底层语言的差异
- Webpack 是基于 Node.js 构建的,Node.js 是毫秒级别的。
- 而 Vite 则是基于 esbuild 进行预构建依赖。esbuild 是采用 Go 语言编写的,Go 语言是纳秒级别的。
- 因此,Vite 在打包速度上相比 Webpack 有 10-100 倍的提升。
- 热更新的处理
- 在 Webpack 中,当一个模块或其依赖的模块内容改变时,需要重新编译这些模块。
- 而在 Vite 中,当某个模块内容改变时,只需要让浏览器重新请求该模块即可,这大大减少了热更新的时间。
Webpack 中启动 Tree Shaking 的条件
- 使用 ES6 模块语法:确保你的 JavaScript 代码使用 ES6 模块语法(即 import 和 export 关键字)来导入和导出模块。
- 生产模式:Tree Shaking 通常在生产模式下才会生效,因为它会移除未使用的代码以减小 bundle 的大小。在 webpack 的配置中设置 mode 为 ‘production’。
- 使用支持 Tree Shaking 的模块:确保你使用的 JavaScript 模块库支持 Tree Shaking,这通常意味着这些库已经使用 ES6 模块语法并且在 package.json 文件中设置了 “sideEffects”: false 或者具体指定了哪些模块是有副作用的。
- 配置 optimization 属性:在 webpack 配置文件中,需要配置
optimization.usedExports
为true
,启动标记功能。
// webpack.config.js
module.exports = {
mode: "production", // Webpack 在构建生产环境模式时会自动启用 Tree Shaking
optimization: {
usedExports: true // 是否启用Tree Shaking
minimize: true, // 是否压缩
}
}
八、其它
树摇(Tree Shaking)
- 原理
- 利用了 ES6 的模块化语法( import 和 export),通过静态分析代码来确定哪些代码是可到达的并且被使用的,然后去除未被使用的部分。
- 作用
- 主要用于移除未被使用的代码,使得最终生成的代码包含应用程序中实际使用的部分。
- 减小应用程序的体积,提高性能。
- 说明
- Tree Shaking 只支持 ESM 的引入方式,不支持 Common JS 的引入方式。
- ESM:export + import
- Common JS:module.exports + require
- Tree Shaking 只支持 ESM 的引入方式,不支持 Common JS 的引入方式。
单页面应用(SPA)
- 单页面应用(SPA)是一种 Web 应用程序的设计模式,其中整个应用程序加载一次,并在用户与应用程序交互时动态地更新页面内容,而不需要重新加载整个页面。
- SPA 通常使用 JavaScript 来处理页面的渲染和数据交互,通过 AJAX 技术从服务器异步加载数据,从而提供更流畅的用户体验。
- 常见的 SPA 框架包括 AngularJS、React 和 Vue.js。
Node.js 的应用
Node.js 是一个基于 Google Chrome 的 V8 JavaScript 引擎的开源跨平台运行环境,用于服务器端和网络应用程序的开发。
- 构建工具:Node.js可以用来运行各种构建工具,如Webpack、Gulp、Grunt等,用于打包、压缩、编译前端资源文件(如JavaScript、CSS、图片等),以优化项目的性能和开发流程。
- 服务器端开发:虽然主要是用于后端开发,但Node.js也可以用来开发服务器端应用程序,如API服务、实时通讯应用等,特别适合需要高性能和高并发的场景。
- 命令行工具:Node.js可以用来创建各种命令行工具,用于自动化任务、快速生成项目模板、数据处理等,提高开发效率。
- 数据处理:Node.js可以用来处理数据,如读取、写入文件,操作数据库等,方便前端开发人员进行数据处理和管理。
- 服务端渲染:Node.js可以用来进行服务端渲染,将动态生成的页面内容直接输出到浏览器,提高页面加载速度和SEO优化。
- 实时通讯:Node.js的事件驱动和非阻塞I/O特性使其非常适合实时通讯应用,如聊天应用、实时数据展示等。
- 中间件:Node.js可以作为中间件来处理HTTP请求,实现路由、身份验证、日志记录等功能,提供更好的用户体验。
MVC
- 什么是 MVC
- MVC(Model-View-Controller)是一种常用的软件架构模式
- 模型(Model):模型代表应用程序的数据结构和业务逻辑。它负责处理数据的存储、检索和操作,以及定义应用程序的行为。
- 视图(View):视图负责展示模型的数据给用户,并接收用户的输入。它通常是用户界面的一部分,如网页、移动应用界面等。
- 控制器(Controller):控制器充当模型和视图之间的中介,负责处理用户的输入、更新模型数据,并将最终结果展示给用户。它处理用户请求,并决定如何相应这些请求。
- MVC(Model-View-Controller)是一种常用的软件架构模式
- 特点
- 在 MVC 框架中,模型、视图和控制器之间的通信是通过一系列规则和约定来实现的,以确保它们之间的解耦和灵活性。
- 作用
- 这种分离可以帮助开发人员更好地组织和管理代码,提高应用程序的可维护性和可扩展性。
- 常见的 MVC 框架
- Spring MVC(Java)、Ruby on Rails(Ruby)、Django(Python)等。
- 这些框架提供了一些通用的功能和工具,帮助开发人员更快地构建和维护应用程序。
MVVM
- 什么是 MVVM
- MVVM(Model-View-ViewModel)是一种常见的软件架构模式,通常用于构建基于用户界面的应用程序。
- 模型(Model):模型在MVVM中与MVC中的模型类似,负责处理应用程序的数据结构和业务逻辑。
- 视图(View):视图在MVVM中与MVC中的视图类似,负责展示模型的数据给用户。视图通常是用户界面的一部分。
- 视图模型(ViewModel):视图模型是MVVM模式的核心,它负责连接视图和模型。视图模型将模型中的数据转换为视图可以展示的格式,并处理用户输入。视图模型还负责实现数据绑定,确保模型和视图之间的同步更新。
- MVVM(Model-View-ViewModel)是一种常见的软件架构模式,通常用于构建基于用户界面的应用程序。
- 核心思想
- MVVM 模式的核心思想是将视图和业务逻辑完全分离,通过视图模型来连接视图和模型,实现数据的双向绑定。
- 特点
- MVVM 框架的一个重要特点是数据绑定,即视图模型与视图之间的数据自动同步。
- 当模型数据发生变化时,视图模型会通知视图进行更新,反之亦然。
- 这种双向绑定可以减少开发人员编写的代码量,并提高应用程序的响应性和可维护性。
- 常见的 MVVM 框架
- AngularJS、Vue.js、React 等
- 这些框架提供了丰富的功能和工具,帮助开发人员更轻松地构建现代的 Web 应用程序,并实现良好的代码组织和结构。
MVC 和 MVVM 的区别
- MVVM 模式是由 MVC 模式衍生出来的
- MVVM 模式是双向绑定数据,而 MVC 模式是单向通信
- MVVM 是真正将页面与数据逻辑分离放到 js 里去实现,而 MVC 里面未分离
- MVVM 模式一般用于前端开发的较多,MVC模式在服务端用的较多
使用微前端乾坤qiankun的难点
- 状态管理:在微前端架构中,不同微应用之间可能需要共享状态,因此需要解决状态管理的问题。qiankun 提供了应用间通信的机制,但如何有效地管理状态仍然是一个挑战。
- 样式隔离:不同微应用可能使用不同的样式库或命名规范,因此需要解决样式之间的隔离问题,避免样式冲突。qiankun 提供了一些解决方案,但在复杂场景下仍然需要注意样式隔离的问题。
- 性能优化:微前端架构会引入额外的网络请求和代码加载时间,可能影响整体性能。如何优化加载速度、减少资源冗余是一个需要考虑的难点。
- 路由管理:不同微应用之间的路由管理也是一个挑战,需要确保路由之间的切换和传递参数的正常工作。qiankun 提供了一些路由管理的解决方案,但在复杂场景下可能需要额外处理。
- 通信机制:微前端架构中,不同微应用之间可能需要进行通信,如事件触发、数据传递等。qiankun 提供了事件总线等机制,但如何合理使用这些机制也是一个难点。
微前端乾坤qiankun如何通信
- 应用间通信:qiankun 提供了应用间通信的机制,可以通过
props
、emitLifeCycle
、onGlobalStateChange
等方式进行通信。比如,一个微应用可以通过emitLifeCycle
发送事件,其他微应用可以通过onGlobalStateChange
监听事件并做出相应处理。 - 事件总线:qiankun 提供了基于事件总线的机制,可以通过
EventBus
进行事件的发布和订阅。这样不同微应用之间就可以通过事件总线进行通信。 - 全局状态管理:qiankun 还提供了全局状态管理的机制,可以通过
setGlobalState
和onGlobalStateChange
来实现全局状态的管理和监听。这样不同微应用之间就可以共享全局状态,实现通信和数据共享。
低代码开发
-
前端低代码开发是一种通过可视化界面和少量的代码来快速构建应用程序的方法。
-
它旨在降低开发人员的编码难度,提高开发效率,使非专业开发人员也能参与应用程序的开发过程。
-
特点:
- 可视化界面:通过拖拽、配置等方式,实现页面和功能的快速搭建。
- 少量代码:开发人员可以通过简单的代码逻辑来实现特定的功能和交互。
- 快速迭代:低代码平台通常提供快速的反馈和迭代机制,使开发过程更加高效。
-
优势:
- 提高开发效率:不需要从零开始编写代码,可以快速构建应用程序。
- 降低技术门槛:非专业开发人员也能参与应用程序的开发,减少对编程知识的依赖。
- 易于维护和更新:通过可视化界面和少量代码,使应用程序更易于维护和更新。
-
应用场景:
- 原型设计:快速搭建原型,验证想法和功能。
- 内部工具开发:快速构建企业内部工具和系统。
- 快速迭代:适用于需求频繁变动或快速上线的项目。
-
工具和平台:
- 市面上有许多前端低代码开发平台,如Microsoft Power Apps、OutSystems、Bubble等,它们提供了丰富的UI组件和功能模块,支持快速搭建应用程序。
权限判断
- 从后端获取权限信息:前端需要向后端发送请求获取当前用户的权限信息,可以是用户的角色、权限列表等。
- 存储权限信息:前端一般会将获取到的权限信息存储在本地,比如使用 Vuex 管理权限信息。
- 根据权限信息进行判断:在前端页面中,根据用户的权限信息来控制页面元素的显示、操作的可用性等。可以在组件的生命周期函数中进行权限判断,或者在路由守卫中进行权限控制。
- 权限指令:可以自定义指令来简化权限控制的代码编写,比如根据用户的权限信息动态添加或移除某个元素的权限。
- 前端路由控制:可以根据用户的权限信息动态生成路由表,只展示用户有权限访问的页面。
如何使用自定义指令控制权限
- 创建自定义指令:首先,在 Vue.js 应用中创建一个自定义指令,用于权限控制。
// main.js
import Vue from 'vue';
Vue.directive('permission', {
inserted(el, binding) {
const userPermissions = ['viewDashboard', 'editProfile']; // 从后端获取的用户权限信息
const requiredPermission = binding.value;
if (!userPermissions.includes(requiredPermission)) {
el.parentNode.removeChild(el);
}
}
});
- 在模板中使用自定义指令:在 Vue 组件的模板中使用自定义指令,指定需要的权限。
<template>
<div>
<button v-permission="'viewDashboard'">View Dashboard</button>
<button v-permission="'editProfile'">Edit Profile</button>
</div>
</template>
-
在上面的示例中,自定义指令
v-permission
会根据用户的权限信息来控制按钮元素的显示。如果用户的权限信息中包含了指定的权限,按钮会显示出来;否则,按钮会被移除。 -
这样,通过使用自定义指令可以简化权限控制的代码编写,使权限判断逻辑更加清晰和易于维护。当用户的权限信息发生变化时,页面上的元素会根据权限自动更新显示状态。
分段上传、断点续传
-
分段上传:
- 将大文件分成多个小段进行上传,可以并行上传这些小段,从而提高上传速度。
- 一旦所有小段上传完成,服务器端会将这些小段合并成完整的文件。
- 这种方式可以减少单个上传文件的失败率,同时也可以更好地处理网络中断等情况。
- 分段上传更注重提高上传速度和稳定性。
- 常见的例子包括百度网盘、腾讯微云等。
-
断点续传:
- 在文件上传过程中,如果发生网络中断或者其他原因导致上传失败,断点续传可以让用户从上次中断的地方继续上传,而不需要重新上传整个文件。
- 这种方式可以节省用户的时间和流量,提高用户体验。
- 断点续传更注重在上传过程中处理中断情况。
- 常见的例子包括云存储、视频网站等。
- 在 Vue 中实现断点续传,需要结合后端的支持。以下是一个基本的思路:
- 切割文件:将要上传的文件切割成多个小文件片段。可以使用 JavaScript 的 File API 中的 slice 方法来实现。
- 上传文件片段:使用 XMLHttpRequest 或者 Fetch API 发送每个文件片段到后端,并携带相关信息,如文件名、文件ID、当前片段序号等。
- 后端接收并保存文件片段:后端接收到每个文件片段后,将其保存在临时位置,并记录文件片段的序号和文件ID等信息。
- 续传处理:如果上传过程中断,下次继续上传时,通过查询后端已保存的文件片段信息,得知已经成功上传的文件片段,从断点处继续上传剩余的文件片段。
- 合并文件:当所有文件片段都上传完成后,后端根据文件ID将所有片段合并成完整的文件。
内嵌 iframe 如何交互
可以使用 postMessage API。这个 API 允许在不同的窗口或 iframe 之间安全地发送消息。
-
在父页面中,可以使用以下代码向 iframe 发送消息:
const iframe = document.getElementById('your-iframe-id'); iframe.contentWindow.postMessage('Message from parent', 'https://your-iframe-url.com');
-
在 iframe 中,可以监听并接收来自父页面的消息:
window.addEventListener('message', function(event) { if (event.origin !== 'https://your-parent-url.com') return; console.log('Message received in iframe:', event.data); });
ES6 新特性
- 箭头函数:使用箭头函数可以更简洁地定义函数。
- 模板字符串:使用反引号(``)可以定义多行字符串和插入变量。
- 解构赋值:可以通过解构赋值来快速获取数组或对象中的值。
- 默认参数:可以为函数参数设置默认值。
- 扩展运算符(…):可以将数组或对象展开为单独的元素。
- 类和模块:引入了类和模块的概念,更好地支持面向对象编程。
- Promise:Promise 是一种处理异步操作的新方式,更加灵活和方便。
- let 和 const:引入了块级作用域的 let 和常量 const。
- 简化对象属性的定义:在对象字面量中可以省略属性名。
- 简化迭代:引入了 for…of 循环,简化了对数组和类数组对象的迭代。
pnpm、npm 的区别
pnpm
与 npm
相比具有更小的空间占用和更快的安装速度,但由于其不同的存储方式可能会导致与某些工具的不兼容
- 包的存储方式:
npm
将每个包都下载到项目的node_modules
目录中,而pnpm
会在全局安装一个存储库,并在项目中创建一个符号链接到该存储库中的每个包。 - 空间占用: 由于
pnpm
使用符号链接,它的空间占用通常比npm
小,因为它避免了在多个项目中重复存储相同的依赖项。 - 安装速度: 由于
pnpm
在全局安装中共享依赖项,因此安装速度通常比npm
更快。 - 命令行接口:
pnpm
的命令行接口与npm
不同,但它们都提供了一组相似的命令来管理包。 - 兼容性: 由于
pnpm
的存储方式不同于npm
,因此某些与npm
兼容的工具可能无法与pnpm
一起使用。
钉钉小程序生命周期
- 应用的生命周期。主要通过app.js中的生命周期函数来管理
onLaunch
:当小程序初始化完成时,会触发onLaunch(全局只触发一次)。onShow
:当小程序启动,或从后台进入前台显示时,会触发onShow方法。onHide
:当小程序从前台进入后台时,会触发onHide方法。onError
:当小程序发生脚本错误,或者api调用失败时,会触发onError方法。
- 页面的生命周期。主要通过.js文件中的Page对象来管理
onLoad
:页面加载时触发。一个页面只会调用一次,参数为上个页面传递的数据。onShow
:页面显示/切入前台时触发。onReady
:页面初次渲染完成时触发。onHide
:页面隐藏/切入后台时触发。onUnload
:页面卸载时触发。
- 组件的生命周期。主要通过组件的.js文件中的Component对象来管理
created
:组件实例被创建时触发。attached
:组件实例进入页面节点树时触发。ready
:组件在视图层布局完成后触发。moved
:组件移入节点树时触发。detached
:组件实例被移出页面节点树时触发。
八、前端综合问题
组件封装
- 什么是组件封装
- 将页面上的一些可复用的功能或UI元素抽象成独立的组件,以便在不同的页面或项目中重复使用。
- 这种思想有助于提高代码的复用性、可维护性和可扩展性,同时也有利于团队协作和开发效率。
- 封装组件的思想
- 模块化开发:将页面拆分成独立的组件,每个组件负责特定的功能或UI展示。这样可以使得代码更易于维护和扩展。
- 功能独立:将页面上的功能模块或UI元素进行拆分,确保每个组件都具有独立的功能和责任,使其易于复用和维护。
- 接口清晰:定义组件的接口和属性,使其对外提供清晰的调用方式和参数配置,方便其他开发者在不了解内部实现的情况下使用组件。
- 样式隔离:采用CSS模块化或CSS-in-JS等方式,确保组件的样式不会影响到其他组件,避免样式冲突和污染。
- 事件通信:通过事件机制或回调函数等方式实现组件之间的通信,使得组件之间可以相互协作和传递数据。
- 文档和示例:编写组件的文档和示例,描述组件的用法和参数配置,方便其他开发者了解和使用组件。
- 场景类别
- UI组件:UI组件主要用于展示页面上的各种UI元素,如按钮、表单、模态框等。这些组件通常具有样式和交互效果,可以帮助开发人员快速构建页面。
- 功能组件:功能组件主要包含各种功能性的模块,如轮播图、下拉菜单、数据表格等。这些组件通常具有一定的业务逻辑,可以提供特定的功能。
- 布局组件:布局组件用于定义页面的整体布局结构,如头部导航、侧边栏、底部信息等。这些组件可以帮助统一页面布局,提高页面的一致性。
- 工具类组件:工具类组件通常用于提供一些通用的功能或工具,如日期选择器、图表库、状态管理等。这些组件可以帮助简化开发流程,提高代码复用性。
- 第三方组件库:除了自行封装组件外,开发人员还可以使用第三方组件库,如Ant Design、Element UI、Bootstrap等。这些组件库提供了丰富的UI组件和功能组件,可以加速开发过程。
前端自动化和工程化
- 前端自动化和工程化是指利用自动化工具和流程来提高前端开发效率、优化代码质量和协作方式的方法。
- 可以提升团队的开发效率、降低错误率,同时提升代码质量和可维护性。
- 以下是一些常见的前端自动化和工程化工具和实践:
- 版本控制系统:使用 Git 等版本控制系统来管理代码,实现团队协作和代码版本控制。
- 包管理工具:使用 npm 或者 yarn 等包管理工具来管理项目依赖,统一管理第三方库和工具。
- 自动化构建工具:使用 Webpack、Gulp 或者 Grunt 等自动化构建工具来自动化处理前端资源,如编译、压缩、打包等。
- 模块化开发:采用模块化开发方式,如使用 ES6 模块、CommonJS 或者 AMD 规范,提高代码复用性和可维护性。
- 预处理器:使用 Sass、Less 等 CSS预处理器和 Babel 等JavaScript编译器来提高开发效率,减少重复工作。
- 代码规范检查:使用 ESLint、StyleLint 等工具进行代码规范检查,确保代码质量和一致性。
- 单元测试和集成测试:使用 Jest、Mocha 等测试框架进行单元测试和集成测试,保证代码质量和稳定性。
- 自动化部署:使用 CI/CD 工具如 Jenkins、Travis CI 等自动化部署代码到生产环境,提高部署效率和稳定性。
性能判断
- 前端性能监控和埋点:通过在关键点上埋点,可以监控网页的加载时间、资源请求、错误等关键性能指标。
- 常用的前端性能监控工具包括自定义的日志记录、第三方服务(如Google Analytics、Sentry等)和开源工具(如Fundebug、Tongji.js等)。
- 此外,
window.performance
API提供了性能数据,可以通过它获取更详细的性能指标,如页面加载时间、资源加载时间等。
- 性能分析工具:使用性能分析工具可以深入分析网站的性能瓶颈,并提供有针对性的优化建议。其中两个常用的工具是:
- Performance:现代浏览器提供的内置性能分析工具,可通过浏览器开发者工具访问。它提供了时间轴记录、CPU、内存和网络分析等功能,帮助开发者找到性能瓶颈并进行优化。
- Lighthouse:由Google开发的开源工具,可用于自动化测试网页性能,并提供综合的性能报告。它评估网页在多个方面的性能表现,并给出相应的优化建议。
- 性能指标:性能指标是用于衡量网站性能的关键指标,常用的指标包括:
- LCP(Largest Contentful Paint):标识页面上最大的可见内容加载完成的时间,衡量用户可见内容的加载速度。
- FCP(First Contentful Paint):表示页面上第一个内容元素(如文字、图片)呈现的时间,标识页面加载的起点。
- FID(First Input Delay):测量从用户首次与页面交互(点击链接、按钮等)到浏览器实际响应该交互的时间。
- CLS(Cumulative Layout Shift):测量页面上元素布局的稳定性,即元素在页面加载过程中发生的意外移动的累积量。
- TTFB(Time To First Byte):表示从发起请求到接收到第一个字节的时间,衡量服务器响应速度。
- TTI(Time To Interactive):表示页面变得可交互的时间,即用户可以进行操作和与页面进行交互的时间点。
- TBT(Total Blocking Time):衡量页面在加载过程中存在的阻塞时间总和,即浏览器忙于处理 JavaScript 执行而导致无法响应用户输入的时间。
性能优化
- 压缩和合并资源文件:压缩 JavaScript、CSS 和图片文件,减小文件大小,同时合并多个文件以减少请求次数。
- 使用缓存:利用浏览器缓存机制,设置合适的缓存头(Cache-Control、Expires 等)来减少服务器请求。
- 异步加载资源:将非关键资源(如广告、社交分享插件等)使用异步加载,不阻塞页面主要内容的加载。
- 图片优化:使用适当的图片格式(如WebP、JPEG 2000等),以及压缩图片大小来减少页面加载时间。
- 延迟加载:延迟加载页面中不是立即可见的内容,如图片懒加载、滚动加载等。
- 使用 CDN:将静态资源托管到CDN(内容分发网络)上,加速资源加载速度。
- 减少重绘和重排:避免频繁修改DOM结构和样式,减少页面的重绘和重排次数。
- 使用服务端渲染(SSR):对于需要SEO和首屏加载速度要求高的页面,使用服务端渲染来提高性能。
- 懒加载和分块加载:按需加载页面内容,减少一次性加载大量资源造成的性能压力。
- 监控和优化:使用工具(如Lighthouse、WebPageTest等)监控网站性能,并根据结果进行优化。
REST API 规范
- 什么是 REST API 规范
- REST API(Representational State Transfer API)是一种基于REST架构风格设计的Web服务接口,用于前端与后端之间的数据交互
- 前端可以通过 REST API 向后端发送请求并获取数据,实现前后端的数据通信和交互
- 设计良好的前端 REST API 规范可以提高前后端开发人员之间的沟通效率,降低开发成本,提升系统的可维护性和可扩展性
- 常见的规范
- 统一的API端点:
- 定义统一的API端点,遵循RESTful风格的URL设计。
- 版本控制:
- 在API端点中包含版本信息,以便后续版本的API可以与旧版本共存并进行逐步迁移。
- 请求方法:
- 使用合适的HTTP动词来表示对资源的操作(GET用于获取资源,POST用于创建资源,PUT用于更新资源,DELETE用于删除资源等)。
- 避免在GET请求中传递敏感数据,应该使用POST或其他安全的HTTP方法。
- 请求参数:
- 使用查询参数传递筛选、排序、分页等参数。
- 对于POST和PUT请求,使用请求体(Request Body)传递数据,可以使用JSON格式或其他合适的数据格式。
- 响应格式:
- 使用合适的HTTP状态码表示请求结果(如200表示成功,400表示客户端错误,500表示服务器错误等)。
- 返回合适的响应体(Response Body),通常使用JSON格式返回数据。
- 错误处理:
- 统一定义错误格式,包括错误码、错误信息、错误详情等。
- 使用合适的HTTP状态码表示错误(如400 Bad Request、404 Not Found、500 Internal Server Error等)。
- 安全性:
- 使用HTTPS协议传输数据,确保数据的安全性。
- 对敏感操作(如删除、更新)进行权限验证,保护API的安全性。
- 文档和测试:
- 提供清晰的API文档,包括API端点、请求方法、请求参数、响应格式等信息。
- 编写测试用例对API进行测试,确保API的正确性和稳定性。
- 性能优化:
- 使用合适的缓存策略(如ETag、Cache-Control)优化API的性能。
- 对于大数据量的请求,考虑分页、延迟加载等技术来提高性能。
- 统一的API端点:
常见的 Mock工具
- Mock.js:
- Mock.js 是一个用于生成随机数据的模拟数据生成器,可以模拟各种数据类型和数据结构,支持 RESTful API 的模拟数据生成。
- 可以通过配置生成模拟数据,支持数据模板、数据占位符、数据规则等功能。
- json-server:
- json-server 是一个快速的、零配置的 RESTful API 服务器,可以快速创建一个模拟的 REST API 服务。
- 可以通过提供一个 JSON 文件作为数据源,快速搭建一个 REST API 服务器,支持增删改查等操作。
- axios-mock-adapter:
- axios-mock-adapter 是一个用于 axios 的模拟数据适配器,可以拦截 axios 请求并返回模拟数据。
- 可以在前端项目中使用 axios-mock-adapter 来模拟后端接口数据,方便进行前端开发和调试。
- MirageJS:
- MirageJS 是一个用于构建前端模拟 API 的库,可以帮助前端开发人员在本地快速搭建一个模拟的 API 服务器。
- 提供了强大的路由、数据模型、序列化等功能,可以方便地模拟各种接口数据。
- faker.js:
- faker.js 是一个用于生成随机数据的库,可以生成各种类型的随机数据,如姓名、地址、邮箱等。
- 可以结合其他工具使用,如 Mock.js,生成更加真实的模拟数据。
- Easy Mock:
- Easy Mock 是一个在线的接口模拟平台,可以快速创建和管理接口模拟数据,支持多种数据类型和数据结构。
- 可以通过 Easy Mock 创建接口文档、模拟接口数据,方便前端开发人员进行接口联调和测试。
常见的 数据交换技术
- AJAX(Asynchronous JavaScript and XML):
- AJAX 是一种通过 JavaScript 发起异步请求的技术,可以在不刷新整个页面的情况下获取服务器端数据。
- 常用的 AJAX 库包括 XMLHttpRequest、fetch API 和 axios 等,可以实现前端与服务器的数据交换。
- Fetch API:
- Fetch API 是一种用于发起网络请求的现代 Web API,提供了更加简洁和强大的方式来处理网络请求。
- Fetch API 使用 Promise 对象处理异步操作,可以更好地管理请求和响应。
- WebSocket:
- WebSocket 是一种在 Web 应用程序中实现双向通信的技术,可以实时地在客户端和服务器之间传输数据。
- WebSocket 提供了持久连接,可以实现实时聊天、实时数据更新等功能。
- Server-Sent Events(SSE):
- Server-Sent Events 是一种服务器向客户端推送事件的技术,可以实现服务器端的实时更新。
- SSE 基于 HTTP 协议,可以在客户端接收到服务器端推送的事件时执行相应的操作。
- GraphQL:
- GraphQL 是一种用于查询和修改数据的数据交换语言,可以更灵活地定义数据结构和查询方式。
- GraphQL 可以减少前端与服务器之间的数据传输量,提高数据获取的效率。
- REST API:
- REST API 是一种基于 REST 架构风格设计的 Web 服务接口,通过 HTTP 方法和资源路径进行数据交换。
- 前端可以通过 REST API 发起 GET、POST、PUT、DELETE 等请求,与服务器进行数据交互。
常见的 设计模式
- 工厂模式(Factory Pattern)
- 优点:封装了对象的创建过程,降低了耦合性,提供了灵活性和可扩展性。
- 缺点:增加了代码的复杂性,需要创建工厂类。
- 适用场景:当需要根据不同条件创建不同对象时,或者需要隐藏对象创建的细节时,可以使用工厂模式。
- 单例模式(Singleton Pattern)
- 优点:确保一个类只有一个实例,节省系统资源,提供全局访问点。
- 缺点:可能引入全局状态,不利于扩展和测试。
- 适用场景:当需要全局唯一的对象实例时,例如日志记录器、全局配置对象等,可以使用单例模式。
- 观察者模式(Observer Pattern)
- 优点:实现了对象之间的松耦合,支持广播通信,当一个对象状态改变时,可以通知依赖它的其他对象进行更新。
- 缺点:可能导致性能问题和内存泄漏,需要合理管理观察者列表。
- 适用场景:当需要实现对象之间的一对多关系,一个对象的改变需要通知其他多个对象时,可以使用观察者模式。
- 发布订阅模式(Publish-Subscribe Pattern)
- 优点:解耦了发布者和订阅者,使它们可以独立变化。增加了代码的灵活性和可维护性。
- 缺点:可能会导致发布者过度发布消息,造成性能问题。订阅者需要订阅和取消订阅相关的逻辑。
- 适用场景:当存在一对多的关系,一个对象的状态变化需要通知多个其他对象时,可以使用发布订阅模式。
- 适配器模式(Adapter Pattern)
- 优点:允许不兼容接口的对象协同工作,提高代码的复用性和灵活性。
- 缺点:增加了代码的复杂性,需要理解和管理适配器的转换过程。
- 适用场景:当需要将一个类的接口转换成客户端所期望的另一个接口时,可以使用适配器模式。
常见的 算法
- 排序算法:
- 冒泡排序(Bubble Sort):比较相邻的元素,如果顺序错误则交换位置,直到没有需要交换的元素。
- 快速排序(Quick Sort):选择一个基准元素,将小于基准的元素放在左边,大于基准的元素放在右边,递归处理左右两边的子数组。
- 搜索算法:
- 线性搜索(Linear Search):从数组的第一个元素开始逐个比较,直到找到目标元素或搜索完整个数组。
- 二分搜索(Binary Search):对已排序的数组进行查找,每次将查找范围缩小一半,直到找到目标元素或查找范围为空。
- 递归算法:
- 递归函数:函数直接或间接调用自身,常用于解决树结构、分治算法等问题。
- 斐波那契数列:经典的递归问题,f(n) = f(n-1) + f(n-2),可以使用递归或动态规划解决。
- 动态规划:
- 最长递增子序列(Longest Increasing Subsequence):寻找一个数组中最长的递增子序列。
- 背包问题(Knapsack Problem):给定一组物品的重量和价值,选择一些物品放入背包使得总价值最大。
- 深度优先搜索(DFS)和广度优先搜索(BFS):
- DFS:从根节点出发,沿着一条路径一直向下搜索直到叶子节点,然后回溯到上一个节点继续搜索。
- BFS:从根节点开始,逐层遍历节点,先遍历完当前层的所有节点,再遍历下一层的节点。
- 位运算:
- 位运算操作:包括与(&)、或(|)、异或(^)、左移(<<)、右移(>>)等操作,常用于优化算法和处理二进制数据。
观察者模式、发布订阅模式
- 相同之处
- 都用于实现对象之间的消息通信和事件处理。
- 都支持解耦,让发布者和订阅者(观察者)之间相互独立。
- 区别
- 关注点不同:
- 观察者模式关注的是一个主题对象(被观察者)和多个观察者对象之间的关系。当主题对象的状态发生变化时,它会通知所有观察者对象进行更新。
- 而发布订阅模式关注的是发布者和订阅者之间的关系,发布者将消息发送到一个中心调度器(或者称为事件总线),然后由调度器将消息分发给所有订阅者。
- 中间件存在与否:
- 观察者模式则直接在主题对象和观察者对象之间进行通信,没有中间件的参与。
- 发布订阅模式通常需要一个中间件(调度器或事件总线)来管理消息的发布和订阅,这样发布者和订阅者之间的通信通过中间件进行。
- 松散耦合程度不同:
- 观察者模式中,主题对象和观察者对象之间是直接关联的,主题对象需要知道每个观察者对象的存在。
- 而在发布订阅模式中,发布者和订阅者之间并不直接关联,它们只与中间件进行通信,发布者和订阅者之间的耦合更加松散。
- 关注点不同:
Web 标准
-
Web 标准是由 W3C 和其他标准化组织制定的,用于创建和解释网页基本内容的一系列规范。
-
这些规范确保网页在不同浏览器和操作系统上能够正确显示样式和功能。
-
旨在提高网页的可访问性、兼容性和用户体验。
-
Web 标准主要分为三个部分:
- 结构(Structure):指网页的基本框架,包括 HTML、XML 等标签语言。结构规范涉及标签的正确使用、嵌套以及语义化
- 表现(Presentation):指网页的外观,包括文字的字体、大小、颜色、间距、布局等,以及图片的尺寸、位置、边框等。表现标准语言主要是 CSS。
- 行为(Behavior):指网页的交互行为,涉及 JavaScript、Ajax 等脚本语言以及CSS等样式语言。行为标准主要包括对象模型(如 W3C DOM)和 ECMAScript。
-
开发人员的理解:
- HTML标准:深入了解HTML标准,包括语义化标签的正确使用、文档结构的合理布局以及无障碍性设计的实践。
- CSS标准:遵循CSS标准,使用层叠样式表来实现页面的样式化和布局,确保页面在不同设备上都能正确显示。
- JavaScript标准:熟悉JavaScript的语法和最佳实践,通过DOM操作和事件处理来增强用户交互体验,同时关注性能和安全性。
- 跨浏览器兼容性:考虑不同浏览器对Web标准的支持情况,编写兼容性代码并进行测试,以确保网站在各种浏览器中都能正常运行。
- 响应式设计:采用响应式设计的原则,使用媒体查询和弹性布局等技术,使网站能够适应不同设备和屏幕尺寸。
- 性能优化:遵循Web标准来优化网站性能,包括减少HTTP请求、压缩资源、使用缓存等方法,以提升用户体验。
- 无障碍性:遵循Web标准可以使网站更易访问,符合残障人士的需求。
Web标准可访问性、可维护性的理解
- 可用性(Usability)
- 是指一个产品或系统在用户使用过程中的易用性和用户满意度。
- 一个具有良好可用性的产品能够满足用户的需求,提供直观、简洁、一致的用户界面,减少用户的学习成本和操作复杂度,提供明确的反馈和帮助信息,从而提升用户的效率和满意度。
- 可访问性(Accessibility)
- 是指 Web 内容对于所有用户,包括残障用户,的可阅读和可理解性。
- 它涉及到使用无障碍技术和遵循无障碍设计原则,以确保残障用户能够平等地获取和使用Web内容。
- 这包括为视觉、听觉、运动和认知等方面的残障用户提供适当的辅助功能和支持,如屏幕阅读器、放大器、辅助键盘等。
- 可维护性(Maintainability)
- 是指一个系统或代码的易维护性和可理解性。
- 一个具有良好可维护性的系统能够快速定位和修复问题,容易进行功能扩展和修改。
- 为了提高可维护性,代码应具有良好的结构和组织,遵循设计模式和编程规范,提供清晰的注释和文档,同时采用合适的工具和方法进行版本控制和测试。
移动端开发常见问题
- 响应式设计:确保网站在不同设备上有良好的显示效果,包括桌面、平板和手机等设备。
- 浏览器兼容性:不同浏览器对CSS和JavaScript的解释可能不同,需要确保网站在各种主流浏览器上都能正常运行。
- 性能优化:移动端设备通常性能较弱,需要优化页面加载速度和性能,以提升用户体验。
- 触摸事件:移动设备使用触摸屏幕进行交互,需要处理触摸事件以实现良好的用户体验。
- 图片优化:移动设备的网络环境通常不稳定,需要对图片进行压缩和优化以减小页面加载时间。
- 移动端适配:针对不同分辨率和屏幕尺寸的移动设备进行适配,确保页面在各种设备上都能正常显示。
- 缓存管理:移动设备的存储空间有限,需要合理管理缓存以提升页面加载速度和减少数据消耗。
- 安全性:移动端开发需要考虑用户数据的安全性和隐私保护,确保用户信息不被泄露或篡改。
移动端前端、Web前端
- 开发环境和技术:移动端前端主要面向移动设备,需要熟悉移动端的开发环境和相关技术,如React Native、Flutter、Ionic等。而Web前端则主要面向浏览器,使用HTML、CSS、JavaScript等技术进行开发。
- 用户体验和交互:移动端前端需要更关注移动设备的特性和用户体验,例如触摸操作、手势识别、屏幕适配等,以提供更好的移动端交互体验。而Web前端则更注重页面的响应式设计和跨浏览器兼容性,以确保在不同浏览器和设备上的良好表现。
- 功能支持和限制:移动端前端开发可能会受到一些限制,如对设备资源的访问(相机、GPS等)、消息推送的限制等。而Web前端在功能上较为灵活,可以通过浏览器提供的API和插件来实现一些高级功能。
- 部署和更新:移动端前端需要通过应用商店进行发布和更新,需要经过审核和下载安装。而Web前端则可以直接通过URL访问,无需下载安装,便于部署和更新。
Web App、hybrid App、Native App
- Web App(HTML5):采用 HTML5 生存在浏览器中的应用,不需要下载安装
- 优点:开发成本低,迭代更新容易,不需用户升级,跨多个平台和终端
- 缺点:消息推送不够及时,支持图形和动画效果较差,功能使用限制(相机、GPS等)
- Hybrid App(混合开发):UI WebView,需要下载安装
- 优点:接近 Native App 的体验,部分支持离线功能
- 缺点:性能速度较慢,未知的部署时间,受限于技术尚不成熟
- Native App(原生开发):依托于操作系统,有很强的交互,需要用户下载安装使用
- 优点:用户体验完美,支持离线工作,可访问本地资源(通讯录,相册)
- 缺点:开发成本高(多系统),开发成本高(版本更新),需要应用商店的审核
面向对象编程(OOP)
- 什么是面向对象编程
- 面向对象编程(Object-Oriented Programming,简称 OOP)是一种编程范式,
- 它以对象为基本单元,通过封装、继承和多态等特性来组织和管理代码。
- 在前端开发中,面向对象编程可以帮助开发者更好地组织和维护代码,提高代码的复用性和可维护性。
- 核心
- 面向对象编程的核心概念是对象和类,对象是类的实例化,类是对现实对象的抽象
- 主要特点
- 封装(Encapsulation):将数据和操作数据的方法封装在一个对象中,隐藏对象的内部实现细节,只暴露必要的接口给外部使用。
- 继承(Inheritance):通过继承机制,子类可以继承父类的属性和方法,实现代码的重用和扩展。
- 多态(Polymorphism):不同对象可以对同一个消息做出不同的响应,提高代码的灵活性和可扩展性。
- 作用
- 在前端开发中,面向对象编程通常通过创建对象、定义类、使用构造函数等方式来实现。开发者可以使用JavaScript等语言来实现面向对象编程,利用对象、类、继承等概念来构建复杂的前端应用程序。
- 面向对象编程的优势包括代码的可重用性、可维护性、扩展性和灵活性等。
函数式编程
- 函数式编程是一种专注于使用纯函数并避免共享状态和可变数据的编程范例
- 它促进不变性并强调高阶函数的使用
Babel 原理
- 什么是Babel
- Babel 是一个 JavaScript 编译器。他把最新版的 javascript 编译成当下可以执行的版本,简言之,利用 babel 就可以让我们在当前的项目中随意的使用这些新最新的 es6,甚至 es7 的语法
- 原理
- Babel 的原理是通过解析、转换和生成的过程,将新版本的 JavaScript 代码转换为兼容旧环境的代码,使开发者能够在当前环境中使用较新的 JavaScript 特性和语法
- 工作流程
- 解析(parse):Babel 使用解析器(如
Babylon
)将输入的 JavaScript 代码解析成抽象语法树(AST)。解析器将代码分析成语法结构,并生成对应的 AST,表示代码的抽象语法结构。这个阶段包括词法分析和语法分析。词法分析将源代码转换为一个个标记(tokens)的流,而语法分析则将这个标记流转换为 AST 的形式。 - 转换(transform):在转换阶段,Babel 使用插件(plugins)对 AST 进行遍历和转换。插件可以对 AST 进行增删改查的操作,可以根据需求对语法进行转换、代码优化等。Babel 的插件系统非常灵活,可以根据需要自定义插件或使用现有插件来进行代码转换。
- 生成(generate):在生成阶段,Babel 使用生成器(如
babel-generator
)将经过转换的 AST 转换回字符串形式的 JavaScript 代码。生成器会深度优先遍历 AST,并根据 AST 的节点类型生成对应的代码字符串,最终将代码字符串输出。
- 解析(parse):Babel 使用解析器(如
前端团队合作场景
- 代码版本管理:
- 使用版本控制工具(如Git)来管理团队项目的代码,确保团队成员能够协同开发、合并代码和解决冲突。
- 任务分配和协作:
- 使用项目管理工具(如Jira、Trello)来分配任务、跟踪进度,确保团队成员知道自己的任务和责任。
- 代码规范和风格统一:
- 制定代码规范和风格指南,确保团队成员编写的代码风格一致,便于代码维护和阅读。
- 组件化开发:
- 采用组件化开发的方式,将页面拆分为独立的组件,方便团队成员复用和维护组件。
- 代码审查:
- 定期进行代码审查,帮助团队成员发现潜在的问题,提高代码质量和可维护性。
- 自动化测试:
- 编写单元测试、集成测试和端到端测试,确保代码的质量和稳定性。
- 文档和知识分享:
- 编写项目文档、技术文档和知识分享,帮助团队成员了解项目背景和技术细节。
代码风格 linting 工具的目的是什么
- 代码风格 linting 工具(例如 ESLint)有助于强制实施一致的编码风格并捕获潜在的错误或代码异味
- 它提高了代码质量、可读性和可维护性