前端工程师2022学习笔记

###download:前端工程师2022版

前端工程化

快速发展的大背景
前端发展太快了,在2004年之前,大概只要会网页三剑客(一套强大的网页编辑工具,最初是Macromedia公司开发的,由Dreamweaver、Fireworks、Flash三个软件组成)就很牛了,那时候前端还比较“纯洁“。在进入以Ajax为代表的异步刷新改进用户体验的Web 2.0时代后,开始涌现出大量的库,比如Prototype、jQuery、MooTools、YUI、Ext JS、kissy等,它们都还只是对浏览器兼容性和工具类函数的封装,可是从Backbone、Angular 1.x相继出现后,前端就开始热闹起来了,出现MVC、MVVM、IOC(控制反转,Java著名框架Spring里的概念)、前端路由(类似于Express、Koa等框架的路由)、Virtual DOM(虚拟DOM,通过DOM Diff算法,减少对DOM操作)、JSON API(接口规范)、JavaScript Runtime(Coffee、Babel、TypeScrpt)等等,各种框架格式如雨后春笋一样冒出来,以前可能半年甚至更长时间才出一个框架,现在可能几周就有新的框架诞生,前端进入了空前的爆发阶段。

原始阶段
脚本加载还都比较原始,方式如下:使用多个script标签加载、手动管理顺序、手动管理加载哪些。
在Web开发里经过了很多尝试,也做过很多龌蹉的事儿,比如动态创建Script标签XHR Eval、XHR Injection、$.getScript()、 Script in Iframe、Script DOM Element、Script Defer。
如果说加载比较恶心,那么脚本顺序更恶心,而且JavaScript有个“特性”,一处报错,所有后面的都会崩溃,所以开发会很苦的维护脚本加载的顺序。

包管理器
如果代码存在一个问题,更新jQuery UI版本怎么做呢?jQuery UI依赖jQuery,先下载jQuery UI代码,然后找到依赖的jQuery版本,再替换已有文件,之后测试,如果没问题就直接替换了。
很明显,直接进行文件操作是非常低效率的做法,对于版本、依赖都没法做更好的处理。于是就出现了Bower、NPM等包管理器,所有模块升级,依赖都有包管理负责,可以说很大程度上省去了前端的重复性工作。

模块规范
模块化加载的本质是按需加载。比较常见的规范有3个:(1)AMD、CommonJS和ES6 Modules;(2)使用标准的模块系统来处理依赖和导出每个文件是一个模块;(3)使用模块加载器或打包器进行处理

模块加载器
模块加载器需要实现两个基本功能:1 实现模块定义规范,这是模块系统的基础2 模块系统的启动与运行
常见的比如RequireJS、Sea.js和SystemJS。以AMD的模块加载器RequireJS为例,通常使用RequireJS的话,我们只需要导入RequireJS即可,不需要显式导入其他的JS库,因为这个工作会交给RequireJS来做。

模块打包器
模块加载器提供运行环境,能够让遵守模块规范的代码在上面跑,所以模块化的好处是很明显的。但对于真实项目来说,你还需要构建、打包等操作。
对于开发来说,只需要关注业务模块,不需要了解模块加载器和构建过程,很明显这是非常理想的,也因此产生了webpack这样的模块打包器。
Gulp作为通用构建工具,它已经非常完美了。但技术变革太快了,应用各种预处理器、前端组件化,导致前端无比复杂,而webpack的出现刚刚好,完美解决了前端工程化的问题。

webpack基本介绍

webpack是Node编写的著名模块,是打包器(bundler),不只是支持CommonJS模块,而且还支持更潮的ES6模块,是目前使用极其广泛的打包器,像前端组件化的框架(React、Vue)大多都是使用webpack的。

loader && plugins
它提供了两个极其好的机制:loaders和plugins。
loaders:webpack认为每个文件都是资源模块,针对打包构建过程中用来处理源文件的(JSX、SCSS、Less…)统称为loader。
plugins:插件可以完成更多loader不能完成的功能。插件并不直接操作单个文件,它直接对整个构建过程起作用,大多数内容功能都是基于这个插件系统运行的;当然还可以开发和使用开源的webpack插件,来满足各式各样的需求。比如知名插件autoprefixer、html-webpack-plugin、webpack-dev-middleware、webpack-hot-middleware。

webpack打包过程
(1)从配置文件里找到entry point(2)解析模块系统(3)解决依赖(4)解决依赖管理(读取、解析、解决)(5)合并所有使用的模块(6)合并模块系统的运行时环境(7)产生打包后的文件

浏览器加载过程
(1)通过

javascript 代码是如何被压缩的

在 jquery 时代,当我们引用它的 CDN 地址时,在线上需要引用的是 jquery.min.js。

在现代前端时代,当我们对资源进行打包后,同样需要对代码进行压缩。在生产环境的 JS 仅有一行代码,变量也被压缩为单字符,体积大大减小。

压缩后的代码仅有一行

我们是如何对 JS 代码进行压缩的呢?

#如何压缩代码体积?
这里介绍几种关于压缩代码体积的几种思路

#去除多余字符: 空格,换行及注释
// 对两个数求和
function sum (a, b) {
return a + b;
}
此时文件大小是 62 Byte, 一般来说中文会占用更大的空间。

多余的空白字符会占用大量的体积,如空格,换行符,另外注释也会占用文件体积。当我们把所有的空白符合注释都去掉之后,代码体积会得到减少。

去掉多余字符之后,文件大小已经变为 30 Byte。 压缩后代码如下:

function sum(a,b){return a+b}
替换掉多余字符后会有什么问题产生呢?

有,比如多行代码压缩到一行时要注意行尾分号。 这就需要通过以下介绍的 AST 来解决。

#压缩变量名:变量名,函数名及属性名
function sum (first, second) {
return first + second;
}
如以上 first 与 second 在函数的作用域中,在作用域外不会引用它,此时可以让它们的变量名称更短。但是如果这是一个 module 中,sum 这个函数也不会被导出呢?那可以把这个函数名也缩短。

// 压缩: 缩短变量名
function sum (x, y) {
return x + y;
}

// 再压缩: 去除空余字符
function s(x,y){return x+y}
在这个示例中,当完成代码压缩 (compress) 时,代码的混淆 (mangle) 也捎带完成。 但此时缩短变量的命名也需要 AST 支持,不至于在作用域中造成命名冲突。

#解析程序逻辑:合并声明以及布尔值简化
通过分析代码逻辑,可对代码改写为更精简的形式。

合并声明的示例如下:

// 压缩前
const a = 3;
const b = 4;

// 压缩后
const a = 3, b = 4;
布尔值简化的示例如下:

// 压缩前
!b && !c && !d && !e

// 压缩后
!(b||c||d||e)
#解析程序逻辑: 编译预计算
在编译期进行计算,减少运行时的计算量,如下示例:

// 压缩前
const ONE_YEAR = 365 * 24 * 60 * 60

// 压缩后
const ONE_YAAR = 31536000
以及一个更复杂的例子,简直是杀手锏级别的优化。

// 压缩前
function hello () {
console.log(‘hello, world’)
}

hello()

// 压缩后
console.log(‘hello, world’)
#AST
AST,抽象语法树,js 代码解析后的最小词法单元,而这个过程就是通过 Parser 来完成的。

那么 AST 可以做什么呢?

eslint: 校验你的代码风格
babel: 编译代码到 ES 低版本
taro/mpvue: 各种可以多端运行的小程序框架
GraphQL: 解析客户端查询
我们在日常工作中经常会不经意间与它打交道,如 eslint 与 babel,都会涉及到 js 与代码中游走。不同的解析器会生成不同的 AST,司空见惯的是 babel 使用的解析器 babylon,而 uglify 在代码压缩中使用到的解析器是 UglifyJS。

你可以在 AST Explorer (opens new window)中直观感受到,如下图:

那压缩代码的过程:code -> AST -> (transform)一颗更小的AST -> code,这与 babel 和 eslint 的流程一模一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值