前端入行两年–教会了我这些道理

2018/01/08 · 前端职场 · 1
评论 ·
前端

原文出处: 守候   

在前端性能优化中应用HTTP缓存的三部曲

2017/02/24 · 基础技术 ·
HTTP,
前端

本文作者: 伯乐在线 –
ThoughtWorks
。未经作者许可,禁止转载!
欢迎加入伯乐在线 专栏作者。

Spike先生是Best Experience公司的IT运营部门主管,他的团队成功地利用Http
Cache优化了前端工程。

Spike将通过三个Scenario来展示他的团队是如何做到这一点的:

  • 通过配置Http Cache Expire来消减访问压力,提高用户体验
  • 通过版本化来强制失效本地的过期缓存
  • 通过内容摘要命名文件来更精确的控制缓存以及实现非覆盖式的发布

从 Angular 1 升级到 Angular 2 需要准备的步骤

2016/07/09 · JavaScript
· AngularJS,
升级

本文由 伯乐在线 –
段昕理
翻译,光光头去打酱油
校稿。未经许可,禁止转载!
英文出处:Oren
Farhi。欢迎加入翻译组。

我最近在试玩 Angular
2。刚开始感觉很奇怪,和我们钟爱的第 1
版完全不同。第 1 版是用 ES5 标准的纯 javascript 编写,而第 2 版采用了
typescript 和 es 2015。不过,你已经可以采取一些步骤,让你的 Angular 1
代码(或用 Angular 1 创建的新项目)更加接近 Angular 2。

1.前言

光阴似箭,日月如梭。不得不感慨时间过得很快,2017差不多结束了,一下子我从事前端开发的时间已经两年了。这两年可以说是一波三折,回想这两年的经历,让我忍不住了写下了这篇文章,记录自己在这两年经历的种种种种。这篇文章,打算当做自己的一个经历记录,而对于看这篇文章的你,希望你们能从我的经历里面吸取教训,希望即将步入前端和已经从事前端的你,不要想我这样一波三折,在前端的路走得更好。

第一个故事:我不想要那么多服务器和带宽

我为什么要为 Angular 1 迁移到 Angular 2 做准备

首先,当时机成熟了,你打算用 Angular 2
作为框架时,肯定想让代码迁移更容易些。目前,Angular
小组已经提供了一些迁移策略,你可以混合使用 Angular 1 和 Angular 2
组件,但目标是要将代码库统一,最终只使用一个框架。

其次,在 Angular 2 中更多的是写纯
javascript,然后才是使用专有的框架代码。

再次,社区和浏览器厂商将逐步拥抱 Ecmascript
的最新标准,所以,坚持使用标准编码,尽可能让代码库可复用,而不管选择的框架是什么。

2.大学时光

考完了第二次高考,紧跟着就是懵懵懂懂的上了大学,报的专业就是‘软件技术(网站设计)’。这么说,我也算是科班出身了,只是大学不是那么出名而已!在大学的时光里面,我并不是每天埋头在电脑前面写代码,学习。生活上有社团,班级的活动我基本都参加,也经常约上同学打篮球,聚餐,外出。这些经历,对于大学而言,是非常珍贵的经历,我想拥有多一些这样的经历。至于学习上,我也努力过,也有懒散过。成就方面,除去一些平常的奖项,比较有成就感的就是班里的成绩和个人素质综合测评我都是第一,因此一等奖学金和国家励志奖学金我没落下过。虽然这些和同级的人参加了什么国家省市的比赛,获得了多少等奖,多少名无法相提并论,但是我不求与他人相比,只求超越自己。在步入大学的第一天,我就想不虚度大学的时光,学好专业的知识,不再因自己的不努力而后悔。这个我算是做到了,只是不完美。至于不完美的原因,主要有两个:

一是自己的坚持和自制力不够,主要表现在两个方面——自己本身打算做一个项目练手,后来就是因为懒散或者技术难题放弃了。还有就是和在图书馆借了书,根本没怎么看,等于拿回宿舍放两三个月再还给图书馆!

无论是否是大学生,无论有老师与否,学习这个都是靠自己的努力,靠自己的坚持,坚持,再坚持

二是自己在大学的学习里面,我虽然成绩很好,但不代表技术好,因为和同学对比,我的技术差了可不止一两条街。因为在学习上,我最多也是跟着老师和课本上面的内容学习,不了解外面的世界,不知道技术趋势,也没有和行业的人交流过。这也导致我在实习的时候很是吃亏!

大学的知识需要学习,但是外面的技术趋势也得了解。反复折腾大学的项目,功课。学到的知识比较有限。对外面的技术趋势有有了解,加入社区和行业的人交流,学到的会更多,学习效率也更高。

Best Experience面临的资源访问压力和用户体验方面的问题

随着Best Experience提供的前端应用越来越强大,Spike的压力也越来越大:

  • IT部门为了应对来自静态资源的访问压力,不断购置服务器和带宽。
  • 糟糕的用户体验使得用户转投到竞争对手的网站。

工程师们刚刚通过应用Minify、AMD、打包、Gzip等手段优化了前端页面的体验,
最终得到如下图所示的一个资源引用关系:

图片 1

“还是很多东西要下载啊,该拿什么来拯救该死的延迟呢?”——Spike看着图想到。

他突然想起来:在早年间,Yahoo曾发布了关于优化前端体验的35条建议和指导,其中第三条是:“Add
an Expires or a Cache-Control Header”。

Yahoo是这样描述这条建议的:

Web page designs are getting richer and richer, which means more
scripts, stylesheets, images, and Flash in the page. A first-time
visitor to your page may have to make several HTTP requests, but by
using the Expires header you make those components cacheable. This
avoids unnecessary HTTP requests on subsequent page views. Expires
headers are most often used with images, but they should be used on
all components including scripts, stylesheets, and Flash components.

Browsers (and proxies) use a cache to reduce the number and size of
HTTP requests, making web pages load faster.

“这个正是我寻找的银弹”——Spike得意的笑了。

于是,Spike写下了第一个Technology Story。

作为IT 部门的老大:

我希望通过应用HTTP缓存技术,重用已经下载过的资源,

用于消减用户在浏览页面时产生的不必要的Http Request。

以此,来提升用户在浏览页面时候的体验,

以及降低对于公司服务器资源的访问压力。

并找来了工程师Tom。

迁移到 Angular 2 的步骤

采取这些策略可以让你的代码更加接近 Angular 2,使转换变得容易。

3.初入前端

大学的两年时间感觉一晃就过了,一下就到了大三,出来实习了。在接触前端之前,我写了三个月的php,后来发现自己对前端更有兴趣,所以转前端了。但是这条路并不平坦,因为我找了半个月的的工作,面试了16家公司,15家拒绝,最后一家录用我了,就在两年前的11月,我有了第一份前端的工作。当时听到录用了,想都没想,立马就去入职了,没有上网或者去群聊消息打听过这个公司,对立面的情况一概的不了解。带着兴奋的心理去入职了,一个星期之后,我就在想着什么时候离职了。因为公司虽然是有400人,前端也有50人,但是基本(95%)都是实习生或者应届生,做的东西都是切图(html+css,js基本不需要写)即使是技术经理,当时觉得他技术厉害,现在觉得技术很水。做的项目都是很粗糙的(几千块一个项目,设计+前端+后台,大家可以想下是什么样的项目了),工资基本就是1600-2000,涨薪最多也就2500,每天加班也拼不上3000,在那工作四五年最多4000,福利补贴什么也没有,反倒是扣钱的借口就一大堆。每天开会进行‘洗脑’活动,平均每天入职一人,离职一人,入职没满一年就离职还要扣15个工作日的工资等等等等。公司名称不说了,毕竟当时入职都是你情我愿的事情,只是当时自己太天真而已。

可能是因为我的专业技能学得并不是很好,这个经历现在还历历在目,在从那一次开始,我找工作再也不敢着急了,因为越是着急,越是找不到合适的工作。现在面试的时候我也会多问几句,公司的规章制度,福利补贴,薪资待遇,工作内容等问题,入职之前也多了解下公司,上网看评价(如果是初创的公司,网上没有评价的就爱莫能助了)。

前端的第一份工作是不如意,但不代表我就自暴自弃,在工作之余,我也有抓紧学习!这几个月我先是看了blue(智能社的创始人)的入门视频,后来又看了红皮书(【javascript高级程序设计】)。我看视频或者看书的时候,我并没有太着急,要逼自己太紧,而是紧盯的自己要劳逸结合,不能懒散。三个月后,视频和红皮书看完了,前端的三大基础,html+css+js有了一个最基本的认识,并不是很牢固的那一种,即使是切图,也是有点粗糙。看完了视频和红皮书的半个月后,我实在是不想再拖了,拿了2月份的工资的当天,就提离职了。当时主管跟我说,我入职没满一年就离职,是要扣15个工作日的工资的,这个月至少要做够15个工作日,我当时并没有理会,直接第二天不来了,合同没签,我走你也没办法!

遇到实在是受不了的公司,不建议在纠缠下去,早点一刀两断或者就是最好的一个决定。当时在这家公司,有些人觉得被扣15个工作日的工资不划算,打算做满一年再离职。我就直接放弃,频繁请假或者上班不做事,自己学习。他不仁我不义,所以三月份免费给他打工的工作日并没有多少。对于这一次离职3月份的几天工资,我也不那么在乎,第一没多少,第二在乎可能会失去更多,代价更大!

虽然工作的前三年我看重的是收获,待遇次之。如果收获基本没有,待遇也不行,我找不到理由留下,别人也无法说服我留下!

Expire带来的美好生活

Tom刚刚参与了前一轮的优化工作,虽然成果显著,但是他并不满足。

当Tom看到Jim写下的Story时眼前一亮:“这个方法太赞了!我甚至可以在登录页面底部放置对其他页面资源的引用。提升用户在整个网站的浏览体验。”——Tom的小宇宙瞬间爆发,很快就完成了新的优化方案。

Best-Experience的用户在接下来的时间里浏览页面,会这样下载资源,以图片bgimage.png为例:

  • 用户第一次获取图片的时候,Http Request 如图:

图片 2

  • 之后用户再次获取图片的时候,则完全可以从浏览器的缓存中读取数据了。

图片 3

因为采用了Http缓存方案,

  • 用户的feedback越来越好,访问量提高了;
  • IT部门也不用那么多服务器和带宽了。

财务总监邀请Spike共进晚餐,并谈起了自己在希腊的度假。

“我想我也应该去圣托里尼度个假,犒劳下自己”——Spike美滋滋的想到。

1. 开始用 Ecmascript 2015

Angular 2 使用 Typescript 编写,Typescript 是 Ecmascript 2015
的超集,带有更多的特性。不过,如果你不喜欢 Typescript, 也可以只用
Ecmascript 2015 编写 angular 2。 目前,代码最终都会编译成 Ecmascript
5。所以实际上你也可以用 Ecmascript 5 来编写 Angular 2。

但是,在我看来,使用 Ecmascript 2015
的新特性,可以减少代码量(有些时候…)、增强代码可读性、用上令人兴奋的特性,如解构。

如果想使用 Ecmascript 2015
的特性,你需要一个转换器来编译代码。目前最流行的转换器是 babel。babel
在很多流行的构建脚本中都可以配置,如 gulp、webpack、browserify 及其它。

JavaScript

// 对象属性增强 var exports = { search: search, setType: setType,
setDuration: setDuration }; // 可以写成这样 var exports = { search,
setType, setDuration }; ///////////// // 使用“胖箭头” =>
可以简化代码并增强可读性 var videoIds =
response.data.items.map(function(video){ return
video.id[idPropertyName[activeType]]; }).join(‘,’); //
使用了胖箭头符号 var videoIds = response.data.items.map((video) => {
return video.id[idPropertyName[activeType]]; }).join(‘,’);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 对象属性增强
var exports = {
    search: search,
    setType: setType,
    setDuration: setDuration
};
// 可以写成这样
var exports = {
    search,
    setType,
    setDuration
};
 
/////////////
// 使用“胖箭头” =>  可以简化代码并增强可读性
var videoIds = response.data.items.map(function(video){
    return video.id[idPropertyName[activeType]];
}).join(‘,’);
 
// 使用了胖箭头符号
var videoIds = response.data.items.map((video) => {
    return video.id[idPropertyName[activeType]];
}).join(‘,’);

4.播种之路

上一份工作离职了之后,好像面试了5家公司吧,最终入职了一家初创公司,这家公司当时不到10个员工。基本都是技术开发,但是前端只有我一个。所以在这家公司,所有的前端只能靠我自己了,不懂的上网搜,或者在Q群问人。在这家公司里工作,比第一份工作好了很多,很多。但是做的事情,也可以说是比较机械,就是切图,只是比第一份工作复杂了些,也需要写交互特效,因此我的javascript和jquery练得比较多,用起来也顺手了很多。

自己也是在一些前端群里面也是比较活跃了,经常和一些人交流,也会上github看别人的代码!这份工作的前半年,我主要活跃于Q群,但是和那些人聊天,闲聊比较多,代码基本没怎么聊过,有时候也会交流下意见,这些都让我获益匪浅,改变了我很多的认知和做事方式。其中最简单粗暴的一个场景就是:我遇到不懂的,去群上提问,有人回答说:“网上一大堆答案,还来问!”,“看文档啊,写得那么详细!”。正因为被别人说得多了,我遇到问题不再是不懂马上问,而是不懂的先思考,再上网搜,看下有没有类似的答案或者教程,实在是搞不定的再去群里问。在这里也很感谢那些耐心帮我解决难题的大牛,也感谢他们的指导。有时候遇到自己能解答的,我也会尽力而为,毕竟能帮到别人,对自己也是一种实战。在群里,除了答疑和闲聊,也有交流意见,比较有印象的是这些谈话:“我一个星期看完【javascript高级程序设计】,3天看完【javascript
dom编程艺术】”,“我买了犀牛书,目标一个月内看完”。

这些话看着很威风。但我当时在想,这些人把看书当成百米赛跑了,谁看得快谁就厉害?为什么看书要加上期限?在自己规定的期限内看完,里面的知识点能吸收多少呢?

出于这样的心理,我想主要是由两个,一个是为了逼自己学习,避免因为自己懒散而出现有书不看这样的场景。第二个是学习的浮躁心理,看着要学习的这么多,得赶紧看完,再看下一本!

还有一个就是比较深刻一个聊天内容时:有人说想学javascript,但是不知道看什么书,我就推荐红皮书,但是那个人直接回答:“那本我都看完了!”。

那时候我在想,一本书看完了就不能重复再看,还是说一本书只能看一遍,或者是看完了一本书,书上的知识都学会了,不需要看了?

这份工作的后半年,因为我老是用html+css+javascript+jquery开发项目,以及自己的一些练习。对于群里人说的es6,gulp,webpack,vue,angular,react等这一些完全不懂,甚至根本没听过。那个时候我先是看了阮一峰的【es6标准入门】,学习es6的语法,之后也是对gulp,webpack,angular,vue有了一个最基本的了解,但是还是很懵逼。因为并不是大家所说的前端模块化,工程化。而且这份工作,开发的项目一直用的是html+css+javascript+jquery。没跟上技术的趋势,也使用不了新技术。对自己技术水平,再提升一个等级比较困难,而且待遇方面也没增加,就是在今年年初涨了500。所以,出于对自己成长的考虑,我2月份提出了离职!在3月份正式离职。

离职的时候,还是挺不舍的,因为和这家公司的同事相处不错,也是激发了我的兴趣。这一份工作,增加了我对前端的兴趣,接触新的技术,也感觉是种下了前端的种子!这也解释了为什么我把第二份工作的经历称为我的‘播种之路’。

这又说到找工作的事情,大家找工作的时候,建议问下面试官,应聘的职位的工作内容主要是的。我所见过的一些情况就是:一些群友去面试前端,虽然是前端开发,但是工作内容是做小程序或者切图。然后就觉得这样的工作很无趣,做了几天就离职。所以大家应聘的时候,多问几句!除了薪资待遇,公司环境。工作内容也很重要!

第二个故事:失效缓存是个技术活

2. 使用 “angular.service” 替换 “angular.factory”

使用 Ecmascript 2015 意味着我们可以用新的 “class”
关键字来创建新对象甚至扩展其它对象。我曾经写过,比起继承我更热衷于组合,所以我看不出用
“extend” 实现继承有什么用处,不过通过 class
的特性的确可以为创建对象增加好用的语法糖(简化代码)。

在 angular 1 中的 “service” 和 “factory” 的区别是实例化方法:

“service” 使用 “new” 关键字调用(仅一次)

“factory” 使用普通函数调用 — 不需要 “new” 关键字。

在 Angular 2 中,Services 使用了 Ecmascript 2015
类编写。这会导致你需要将 Angular 1 代码中的 factories 转化成
services,并且使用 “class” 替代 function。

例如在我的开源项目-Echoes Player 中,我使用了“class” 和
Angular“service” 编写 youtube api 服务(我以前用的是 factory):

JavaScript

(function() { ‘use strict’; /* @ngInject */ class YoutubePlayerApi {
/* @ngInject */ constructor ($window, $q) { /*jshint validthis: true
*/ this.deferred = $q.defer(); //当 API 准备好时,Youtube 回调
$window.onYouTubeIframeAPIReady = () => { this.deferred.resolve() };
} // 注入 YouTube 的 iFrame API load () { let validProtocols =
[‘http:’, ‘https:’]; let url = ‘//www.youtube.com/iframe_api’; //
我们愿意使用相关的 url 协议,但为避免协议不可用,还是回退到 ‘http:’ if
(validProtocols.indexOf(window.location.protocol) < 0) { url =
‘http:’ + url; } let tag = document.createElement(‘script’); tag.src =
url; let firstScriptTag = document.getElementsByTagName(‘script’)[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); return
this.deferred.promise; } } angular .module(‘youtube.player’)
.service(‘YoutubePlayerApi’, YoutubePlayerApi); })();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
(function() {
    ‘use strict’;
 
    /* @ngInject */
    class YoutubePlayerApi {
 
        /* @ngInject */
        constructor ($window, $q) {
            /*jshint validthis: true */
            this.deferred = $q.defer();
            //当 API 准备好时,Youtube 回调
            $window.onYouTubeIframeAPIReady = () => {
                this.deferred.resolve()
            };
        }
 
        // 注入 YouTube 的 iFrame API
        load () {
            let validProtocols = [‘http:’, ‘https:’];
            let url = ‘//www.youtube.com/iframe_api’;
 
            // 我们愿意使用相关的 url 协议,但为避免协议不可用,还是回退到 ‘http:’
            if (validProtocols.indexOf(window.location.protocol) < 0) {
                url = ‘http:’ + url;
            }
            let tag = document.createElement(‘script’);
            tag.src = url;
            let firstScriptTag = document.getElementsByTagName(‘script’)[0];
            firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
            return this.deferred.promise;
        }
    }
 
    angular
       .module(‘youtube.player’)
       .service(‘YoutubePlayerApi’, YoutubePlayerApi);
})();

发表评论

电子邮件地址不会被公开。 必填项已用*标注