前端工程化
前端的尽头 是 工程化!
技术的尽头 是 全栈 !
前端工程化的主要目标就是解放生产力、提高生产效率。通过制定一系列的规范,借助工具和框架解决前端开发以及前后端协作过程中的痛点和难度问题。
- 包括技术选型、项目脚手架、代码组织结构、UI规范、代码规范、提交规范、单元测试、CICD
- 技术选型: 竞品分析、npm下载量、兼容性、包的大小,最新提交一次,维护记录
1、js 代码压缩 minify 的原理是什么?
我们知道
javascript代码经压缩 (uglify) 后,可以使体积变得更小,那它代码压缩的原理是什么。如果你来做这么一个功能的话,你会怎么去压缩一段
js代码的体积
1、通过 AST 分析,根据选项配置一些策略,来生成一颗更小体积的 AST 并生成代码。
常见用以压缩 AST 的几种方案如下:
-
去除多余字符: 空格,换行及注释
-
压缩变量名:变量名,函数名及属性名
-
解析程序逻辑:合并声明以及布尔值简化
// 压缩前const a = 3;const b = 4;// 压缩后const a = 3, b = 4; -
解析程序逻辑: 编译预计算
// 压缩前const ONE_YEAR = 365 * 24 * 60 * 60// 压缩后const ONE_YAAR = 31536000
2、package-lock.json 有什么作用,如果项目中没有它会怎么样
packagelock.json/yarn.lock用以锁定版本号,保证开发环境与生产环境的一致性,避免出现不兼容 API 导致生产环境报错
3、git hooks 原理是什么
git hooks: Git 能在特定的重要动作发生时触发自定义脚本
2、在开发员提交之前执行检查脚本
3、但是需要把脚本放在本地的 .git/hooks 目录下,不方便在团队内推广
- 因此就出现了husky
4、这样可以避免不符合规范的代码污染远程仓库
以一次commit为例,会先后触发 pre-commit、prepare-commit-msg、commit-msg和 post-commit等hooks。我们可以利用这些hooks做一些有趣的事。比如:我们可以利用 pre-commit进行代码校验,利用 commit-msg进行commit message的校验
4、如何使用 docker 部署前端
为什么需要docker?
使用 docker 部署前端最大的好处是隔离环境,单独管理:
- 前端项目依赖于 Node v16,而宿主机无法满足依赖,使用容器满足需求
- 前端项目依赖于 npm v8,而宿主机无法满足依赖,使用容器满足需求
- 前端项目需要将 8080 端口暴露出来,而容易与宿主机其它服务冲突,使用容器与服务发现满足需求
使用 Docker 部署前端应用程序的基本步骤是:
-
安装 Docker
-
创建 Dockerfile 文件
-
构建 Docker 镜像
-
运行容器并部署应用程序
5、什么是 AST,及其应用
AST(Abstract Syntax Tree)是源代码的抽象语法结构树状表现形式,Webpack、ESLint、JSX、TypeScript 的编译和模块化规则之间的转化都是通过 AST 来实现对代码的检查、分析以及编译等操作。
- 无论什么语言 【java、python】,都有一个共同的部分,将源代码作为纯文本解析成为抽象语法树AST的数据结构
- javascript世界中,你可以认为抽象语法树(AST)是最底层
- 因此了解 js 编译执行的原理,那么你就得了解 AST
AST应用
- Babel中ES6转化成ES5
- vue模板编译
- css预处理
- webpack插件编写
- UglifyJS来压缩js代码
- eslint检查 【将代码解析成抽象语法树,进行分析代码】
AST 如何生成
- js执行的第一步就是读取js文件中的字符流,然后通过词法分析器生成token,之后再通过语法分析生成AST, 最后生成机器码执行
实现词法分析器
- 词法分析器里,每个关键字是一个 Token ,每个标识符是一个 Token,每个操作符是一个 Token,每个标点符号也都是一个 Token。除此之外,还会过滤掉源程序中的注释和空白字符(换行符、空格、制表符等。
AST的应用
- 如何将 Typescript 转化为 Javascript (typescript)
- 如何将 SASS/LESS 转化为 CSS (sass/less)
- 如何将 ES6+ 转化为 ES5 (babel)
- 如何将 Javascript 代码进行格式化 (eslint/prettier)
- 如何识别 React 项目中的 JSX (babel)
6、browserslist 的意义
browserslist 是可以在不同的前端工具之间共用目标浏览器和 node 版本的配置工具。 相当于给 Babel、PostCSS、ESLint、StyleLint 等这些前端工具预设一个浏览器支持范围,这些工具转换或检查代码时会参考这个范围
"browserslist": [
"last 1 version", //每个浏览器支持的最新1个版本
"> 1%", // 兼容全球浏览器使用数量占比1%以上的类型
"maintained node versions", // 兼容所有仍被支持的NODE版本
"not dead" // 一年内官方维护更新的版本
]
browserslist 的原理:
- browserslist根据正则解析查询语句,对浏览器版本数据库进行查询,返回所得的浏览器版本列表。
7、开发组件库问题
1、按需引入 Tree Shaking问题:
- 如何让自己的组件库支持按需引入?
- 1、组件库就必须时基于ESM模块编写的
- 2、package.json的入口文件。增加module字段
- main是cjs模块的入口,module就是esm的入口了,一般的组件库都会配置这两个入口,同时支持cjs和esm两种模块
- 决定具体用哪一种模块,其实是和你的源代码使用哪种模块绑定的
- 如果使用esm语法,即import方式导入,就会去加载module入口文件
- Babel会导致Webpack的Tree-shaking失效吗?
- 是否成功取决于你的 babel 版本,简单的说,如果你使用的是 babel 6,那 Tree Shaking 不生效,如果使用了 Babel 7 及其以上版本,Tree Shaking 是生效的
- package.json的sideEffects要配置吗?
- 默认可以不写sideEffects,如果有需要某些文件不做tree shaking,可以加上
- tree-shaking失效的原因?
- 不要使用mode: development,tree-shaking是用于生产环境。
- webpack4.x的optimization的minimize不能设置为false,会导致失效
8、静态资源如何处理?
1、上传到oss的好处 【阿里云oss对象存储】
- OSS会自动帮你压缩 【使得你的页面加载速度极快】
- 成本低廉
- 减少带宽问题,提高用户体验
2、上传到CDN【内容分发网络】
- CDN主要是用于站点的加速,提高网站中的静态资源的访问性能,比如图片、视频、音频等
- 使用cdn加速oss
OSS和CDN有什么区别呢?使用场景是什么?
- OSS 是做存储的,CDN 是做内容加速的
- 打比方:OSS 是硬盘,用来存数据,那么 CDN 就是宽带,用来传输数据
- 一般二者是配合使用的,对象存储oss里面存的就是一些图片、视频、文件等等,都是静态数据,可以给用CDN做加速
OSS 和 CDN 能否相互替代?
- 不能
OSS和CDN如何配合使用?
- OSS可作为CDN的源站,通过CDN加速内容分发,用户通过CDN节点就近获得文件资源
- 可降低服务器负载
1、在CDN的控制台上,添加OSS的域名
2、获取CDNME, 配置CDNME
- CDNME:域名的别名,用于将域名解析到另一个域名
2、在OSS控制台上,打开加速域名的CDN缓存自动刷新开关
静态资源加载失败,如何处理?
- cdn加载失败
- 如果cdn加载资源失败,可以使用本地备份的
- 或者也可以切到另一个cdn服务
<script src='https://cdn.vue.js' onerror="handleCdnError()"><script/>
function handleCdnError(){
// 加载备用脚本
const fallbackScript = document.createElement('script')
fallbackScript.src = 'fallback-main.js'
document.head.appendChild(fallbackScript)
}
- 图片加载失败
- 占位符。通过error事件,来替换src路径
- 重试机制
<img src='image.jpg' alt='image' onerror="handleImageError(this)" >
function handleImageError(image){
image.onerror = null // 防止死循环
image.src = 'placeholer.jpg' // 使用占位符
}
9、如何从0到1搭建 webpack或者vite?
- webpack和vite两者之间的区别?
- 做了哪些优化?
1、初始化项目
2、配置相关的规范
- 统一代码格式化
- eslint
- hooks
3、配置按需加载,组件库的按需加载、第三方包按需加载
4、打包优化
5、拆包
6、缓存
10、移除未使用的代码
-
移除未使用的代码,包括JS、TS、CSS
-
tree-shaking
-
利用 ES6 模块的静态分析特性,分析哪些导出模块被实际使用,没有被使用的模块,会被移除
-
TypeScript 在编译后变为 JavaScript,因此 Tree-Shaking 对它也有效
- 注意TypeScript 编译配置要设置为ES6 模块,即module为
esnext或es2020
- 注意TypeScript 编译配置要设置为ES6 模块,即module为
-
PurgeCSS
- PurgeCSS 是一个用于删除未使用的 CSS 的工具。它对于优化应用通常很有用
- 当使用了css原子化,比如Tailwind、UnoCSS等框架的时候,会有很多未使用的css,通过PurgeCSS会分析内容和CSS文件,来确定哪些样式未使用的,并将它删除
- PurgeCSS 还有很多配置项,可以根据需求自定义其行为