citrus327/issue-blog-record

2019年终总结与2020年未来规划

Closed this issue · 0 comments

2019年终总结与2020年未来规划

引子

从来没有想过写年终总结,也没有对自己的技术做过整理和归纳。2019年是正式做前端的第一年,也是从生活上和技术上变化最大的一年。借此机会梳理归纳当前的知识树和将要学习的内容。

2019年

计划小结

在2018年的年底,有定制过2019年的学习计划。

  • Learn TypeScript
  • Learn React and build a project with React
  • Learn Git and Github
  • Contribute to the Open Source community
  • Learn CSS animation
  • Clear easy difficulty in LeetCode
  • Learn Express.js
  • Build a Vue.js functional component library
  • Write a blog about what I learnt
  • At least achieve three goals above

以上的每个计划其实都有接触和实现,有些是实现了,有些是中途废弃了。

2018年底是我刚刚接触并进入前端领域的时候,可以看出那时候的学习思路还是在掌握一些基本的语言层面,学习一些工具和基本框架,尝鲜的部分比较多。

那时候有了解NativeScript,有了解Node.js,认为JavaScript要大一统,"唾弃"别的语言,认为JavaScript是未来。

其实现在也觉得JavaScript是未来,但是思考的角度不同。技术是用来解决问题的,现在会去思考”为什么会有NativeScript, react-native“,”为什么会有Node.js“,“他们解决了什么问题”

例如想要学习TypeScript,只是因为TypeScript被人追捧的多,而没有实际去考虑和理解TypeScript带来的好处。在初期写代码的时候,一味的使用TypeScript,但是对其复杂的语法、泛型、类型推断等没有足够的了解,网上的很多最佳实践并没有解决我碰到的问题。

例子还有很多,说白了就是没有清楚自己需要解决的问题在哪里,那解决方案也就是空谈了。

工作小结

2019年正式成为了一名前端工程师。主要技术栈就是JavaScript和Vue.js。

在工作中碰到了很多沟通和实际解决方案的问题,在初期其实踩了很多的坑,也犯了很多的错误。

例如问题没有及时沟通导致task进度延缓耽误了release;代码过度设计导致维护困难;缺少沟通导致很多无意义的加班熬夜。

技术积累

Vue.js

2019年在Vue.js上其实提升并不大,其实Vue.js能够玩出的花样并不是很多,痛点无非在于组件的抽象封装,路由的分解,Vuex store的模块拆分。
这里简单概述一下自己的想法。

Vue.js对于一般的组件来说保证props向下,event向上基本就没什么问题。

组件的设计讲究受控与非受控的共同设计,一个优秀的通用组件必须提供受控模式和非受控模式2种才能够达到基本满足需求变更的需求。当然在业务场景中要充分考虑实际应用场景,因为一个复杂组件同时支持受控与非受控,是很复杂的,会有很多的冗余的local state和event抛出。

Vue.js对于单个不可拆分的职责很难拆分,如果有一个BaseComponent,想对其进行拓展,只有使用mixin或者是加入更多的prop。这两种方式对于组件的后期维护和复用来说都是噩梦。

mixin带来很多命名空间问题,�数据和方法来源通常无法追溯。这种基于继承而非组合的方式,在多个mixin介入进来之后,会发生很多意想不到问题。mixin中对于状态合并,生命周期调用顺序,是有一定的规律的,在多人开发或者换人维护的情况下很容易造成困扰进而引发bug。mixin对于一个组件来说,只有拓展功能,如果我想要一个mixin中的一部分内容,而不要另一部分,除了分解当前mixin为多个小mixin单独引入之外别无他法,这种只能做加法不能做减法的方式对于长期维护和多处调用的组件来说只有弊没有利。

还有一种就是加入更多的prop,这个对于一般人来说很容易就能看出来这种方式的缺点在哪里。这里可以借用一个例子,Prettier的官网有篇文章叫Option Philosophy,这文章大概就是说为何prettier不提供很多option供调用方进行自定义。当然这个文章主要说的是如果提供的自定义项过多,只会造成开源项目的难易维护进而影响项目的生命力。我觉得这个可以应用到Props的这个问题上来,选项过多代表着功能过多,功能过多就会很多的边缘用例,处理各种各样的边界问题会导致组件代码冗余复杂进而引发bug。

这里提到了2种官方里提到的比较普遍的组件拓展方式,其实还有slot,scoped-slots, hoc, 利用scoped-slots构建renderless-components等方式来构建复杂的抽象的组件。其实这里说的有点偏题了,以后可能会单独开一篇文章细说。

React.js

工作中是完全没有React.js的应用场景的,纯靠自己推敲、实践和学习。
现在可以通过React.js完成一个基本的项目。
很多语法还是不熟,hooks方面除了useState, useEffect以外的hooks基本没用过。
因为有Vue.js基础,像hoc, render props基本可以类推。
状态管理方面采用原始Redux配合Redux-thunk做状态副作用。

CSS预处理器

在我目前的工作场景中,其实就是指Sass。
Sass对于我来说,其实只是做一个嵌套语法,sass的变量只能说是一个辅助,并没有解决什么实际问题。
sass的变量无法通过js操作,毕竟sass是个预处理器,很多事情都是在compile time完成的。目前产品线上要求有自定义的runtime branding要求(换肤),其实sass是没法做到的(可能会有解决方案吧,但是官方是没有提供runtime级别的api用来操作sass variables的)

私下里有去了解别的css预处理器,看上去基本差不多,都是自己的语法,基本就是嵌套语法,语法简化,变量,mixin,函数之类的,主要是想做到代码重用。

在目前产品线上没有让我去单独负责一些css framework的工作,其实没有运用到mixin,函数之类的高级特性,最主要的就是嵌套语法。
如果日后有碰到实际问题,再重新捡回来看吧。

在年末的时候仔细看了下PostCSS,PostCSS官方阐述说他并不是一个css预处理器。而我的理解是,PostCss有点像是css里的webpack,拥有很多的插件可以基于原始css进行拓展。例如我常用的嵌套语法就可以使用postcss-nested插件,css variables可以使用postcss-variables,还有很多的插件基于此进行拓展。也就是说postcss其实是可以借助其生态来达到less, sass, stylus等预处理器的效果的。只不过一开始的目的不同,postcss基于插件用来拓展自己的功能,而其他的css预处理器则提供一整套解决方案。PostCSS的autoprefixer插件非常知名,很多人都是通过autoprefixer来了解到postcss的,而不清楚他本身的目的。

包管理

其实包管理这部分的技术积累单纯只是因为之前完全没有包管理的概念,也没有这方面的场景。
主要就是利用Yarn的workspace,配合Lerna做Monorepo。目前公司项目使用的就是Monorepo,但是又没有充分利用他的特点做相互引用,只是拿来把dependecies放到最外层。。

自己私下里的项目其实有尝试去做,除了踩了无尽的坑和无尽的坑之外,等着我只有更多的坑,主要还是各种工具类的配置共享,配置继承,单独为某个package添加依赖,升级依赖等问题。不过毕竟是自己折腾的项目,整体复杂度摆在这里,暂时没有围绕着做相关生态和大力开源的想法。monorepo这个事情可行,但是没必要。暂缓。

工程化

产品早期的工程化就是基于webpack搭的架子,无非就是各种plugin和各种Loader,公司也不存在多部门共享一个脚手架所谓的场景。所以其中经验都是借鉴公司脚本和自己摸索出来的。

目前工程化还是基于Vue.js的经验比较多。Vue.js主要是基于Vue-Cli进行项目搭建的,Vue-Cli提供了很多的built-in特性,例如开启eslint,选择代码风格,选择是否使用typescript, 是否使用某个测试插件等等等。Vue-Cli算是比较通用的脚手架工具了,提供的配置项也很多,webpack的配置也可以通过webpack-chain来进行拓展。

因为目前工作中没有多部门使用同一个脚手架,或者说封装脚手架来共用的场景。在私下里开发的项目中,基本项目开发使用这种通用脚手架是很不错的选择,毕竟官方出品,坑也少。

因为目前所在的公司所面对的场景不足,没有实际的共用脚手架的需求。所以我只能理想化的猜想一个跨部门的前端脚手架肯定是基于一套统一协商好的前端文件架构,统一的编码风格,当然对于其中不统一的部分,提供多个模板,而不提供过多的自定义。因为这个脚手架毕竟是面向内部,约定大约规范。

工程化中除了利用打包工具解析各种文件格式,载入插件,提供开发环境dev server等功能,打包性能优化也是其中很重要的一点。
打包性能优化无非

  1. 压缩代码
  2. 减少首屏渲染载入的文件大小
  3. 通过hash/contenthash进行缓存级别的优化
  4. 通过webpack dll记住之前打过包的部分,减少打包时间
  5. 通过splitChunk将原有一个app.js分成一个或多个vendors,减少文件大小。

目前的工作场景也只能够让我摸到这几个部分,很多细节其实是需要更大的场景去设计与实践的,凭空想象业务场景,只会额外花时间解决伪需求。

前端性能优化

这部分主要说说代码和个别feature的实现上的优化。
目前碰到的可以被优化的点有

  1. 使用Functional Components解决多个无状态vue组件渲染问题。
  2. 使用虚列表vue-virtual-scroller解决大列表渲染问题。不过这个坑蛮多的,很多时候列表改变,但是virtual-scroller重新渲染导致dom没有及时变更,展示空的占位符之类的问题。
  3. 使用图片懒加载减少图片请求个数。
    • 图片懒加载主要的机制就是如果图片在视窗内,就载入图片,否则不载。这个问题被分成2个部分,一个是如何判断在视窗,第二就是如何延迟发出请求家在图片。
    • 第一个问题其实有很多解决方案
      • 使用dom距离viewport上下左右的距离判断是否在视窗内,这个可以用offsetTop之类的属性可以做到,或者使用Element.getBoundingClientRect()获取距离然后判断。但是任何只要实时获取距离的,宽高的,就会触发reflow。这个如果影响的地方很多的话,会对性能有很大影响,所以就有了方案二。
      • 方案二是利用较新的api: Intersection Observer API。这个新的api会动态监测dom的位置,而不会触发reflow。需要借助polyfill
    • 第二个问题就是延迟载入图片,图片的载入是在img的src被实际赋予值的时候发出请求的。所以延迟载入可以先创建img标签,当img标签在视窗范围内时,将src由空置成实际值。
    • 这2个问题有一个库解决了,那就是Lozad

技能树

以下的技能树是我目前能够想到的技术点。我会根据这颗树进行2020的规划编排。
image

总结

2019年是学习的东西最多的一年,但是很明显可以看出来东西浮于表面,没有更深层次的深入。
很多待解决的问题需要被列出来留到2020年解决了。

针对2019年的计划,留下了几个疑难点

  1. 各大开源项目的贡献方式各不同,如何正确的提交pr?如何反馈?
  2. TypeScript
    • TypeScript的类型文件如何管理?
    • Tslint淘汰后,如何配置Eslint?Monorepo的情况下呢?
    • 如何给js based的lib加上typescript类型支持?
    • 多个TypeScript项目构建Monorepo,如何配置配置文件?
  3. React.js
    • React.js学习的时间不够集中,很散,没有彻底经历过React的版本迭代,是很难看出来他每个版本都解决什么问题的。所以需要重新浏览一遍React.js的文档,生命周期函数。�好像有取消一些老的生命周期钩子,了解其原因和替代品。
    • React.js的fiber算法算是初步了解,但是fiber是如何计算任务耗时,是如何编排任务的呢?
    • React.js可以通过一种React.memo进行状态浅对比,如何配合immutable.js作性能优化?最佳实践?性能提升多少?
    • React.js hooks,如何最大化利用hooks进行状态和副作用的封装?最佳实践?可以做什么,不可以做什么?
  4. 工程化。目前其实除了monorepo之外,工程化问题并不是很多,有些最佳实践不是自己捣鼓就能捣鼓出来的,需要更多的场景和理解才能有答案。所以可能转变思路,看一下通用的项目脚手架是如何搭建的?可以通过阅读Vue-Cli的源码来提升。
    • 了解Vue-Cli设计理念
    • Vue-Cli做了哪些事情?想要做到什么地步?
    • 个性化到什么样的程度?
    • 如果通过插件机制对脚手架进行拓展?
  5. 移动端。这个反正是一片空白,也不准备自己研究。有实际业务场景就会解决。
    • H5?
    • React Native?
    • Flutter?
    • 小程序?
    • 公众号?
  6. Node.js。基本不准备在深究了,因为目前场景很少,能够基于此搭建基本Rest服务就满足当前需求了。

2020年计划

  1. 效仿Antd, 使用rollup构建monorepo,尝试搭建自己的组件库或组件库脚手架。
  2. 学习服务端渲染技术,使用expressjs实现最基本的ssr服务
  3. 学习next.js, 并完成shynode-blog端
  4. 使用egg.js完成shynode-eggjs的nodejs后端
  5. 使用React.js完成shynode-admin的前端
  6. 深入学习算法,I-Algorithms
    刷leetcode
  7. 使用React.js高级特性,使用Immutable.js和React.memo实现性能优化
  8. 尝试复刻网易云音乐,做PWA或者H5应用,参考掘金小册

2020年侧重点

  1. Monorepo工程化搭建
  2. 深入理解和应用React.js
  3. github贡献,pr提交步骤