京东单品页前端开辟那些不能不说的事儿

原文:https://keelii.github.io/2016/07/31/something-have-to-say-with-JD-item

简介

详情页也叫做单品页,域名以「item.jd.com/skuid.html」为花样的页面。是担任展现京东商品 SKU 的落地页面。重要任务是展现和商品相干的信息,如:价钱、促销、库存、引荐,从而指导用户进入购置流程。同时单品页有许多版本。寻常分为两类。一类我们一般看到的「通用类目详情页」—— 一切类目都能够运用,一类是不经常看到的「垂直属性详情页」—— 一些有迥殊属性的商品鸠合。

<!–more–>

《京东单品页前端开辟那些不能不说的事儿》

起首。由于详情页大批(sku上亿)、高并发(日 pv 约 5000 万)等特征,在很长的一段时候里,单品页面都是后端递次生成静态页面运用 CDN 来处置惩罚大批、高并发的题目。

其次。单品页触及的「三方」体系迥殊多,比方:促销、库存、合约、秒杀、预售、引荐、IM、商号、评价社区。而单品页的重要任务就是展现这些体系的信息,而且恰当的处置惩罚他们之间的争执关联,而这些体系的接口寻常都运用 异步 Ajax 来完成,由于 其一 CDN 没法做到页面的动态化,其二 一些体系的信息对及时性要求迥殊高(价钱、秒杀),纵然运用后端动态衬着也很难做到无缓存 0 耽误。

基于上面两个缘由,必定了单品页是一种重多体系营业逻辑展现型页面。重前端页面。我也许汇总了一下页面上异步接口,统共约有 30 个,页首屏的接口迥殊重要,接口之间险些都有耦合关联。

《京东单品页前端开辟那些不能不说的事儿》

前端的生长进程

浑沌时期

浑沌时期的单品页并没有前端开辟的观点。中心的功用剧本只要三个:促销价钱(promotion.js)、库存区域(iplocation.js)、别的逻辑(pshow.js)。这三个剧本分别是三个差别团队的同事担任保护,当时我刚进入京东的时刻在 UED 部门,担任页面剧本团体的保护事变和 pshow的开辟。那时刻我自身保护的 pshow.js 剧本紧缩后只要 80 kb,一切的代码都是历程式的,没有任何运用形式和代码妙技,JS 最多也只被用来做个推断衬着 DOM。那时刻的前端事变内容只在 UI 层面,写款式和一些交互剧本。

这个阶段给我最深入的以为是单品页后端模板很少保护(后端架构是最老的 aspx 版本)。大多数的修正都要用 JavaScript 去动态衬着。由于后端页面是一个生成器生成的。假如页面后端模板有修正那末就须要全量的生成一次,历程能够须要几个小时。

初见端倪

当我接办这个项目时恰好有一次大改版,就在这时候刻老大说页面上的剧本都要放在我们手里保护。然后就是一大波的重构、重写。基本上 pshow 被重写了也许 80% 别的的由于营业逻辑的题目并没有完整重写,只是做了些代码层面的优化。

有一个模板引擎叫 trimPath,晓得这个的预计都算老前端的了。最早的客户端 JavaScript MVC 形式代表作品,只到如今照样运用。这个阶段像评价这类完整异步加载的模块迥殊适宜运用模板引擎来削减保护的事变量。这个时刻虽然页面上的代码并不都是我们写的,但基本上前端对页面的 JavaScript 有了掌握权,接下来的事变就是寻找机会逐一优化。

这段时候是最痛楚的时刻,保护的事变一致到前端。然后后端险些没有变化,只是在一段时候将背景的架构从 aspx 过渡到了 java。本质上并没有什么转变。前端却做了比之前更多的事变,也是在这个时刻我接办了大批的保护事变(包括全站大众库的保护)使得我意想到了一些自动化、工程化方面的重要性,后文会重要解说,趁便说下,那时刻前端自动化东西 Grunt 刚面世,然则我自身却用的是 apache ant,不过不久就切换到了 Grunt 来构建项目。

拨云见日

单品页不仅重体系逻辑,也重保护。

在这段时候里一方面有一般的保护类需求要做,一方面自身也不停的进修新学问为今后的改版做铺垫。不过就在这时候单品页有汗青意义的一次技改涌现了 —— 单品页动态化技改。关于后端部份的革新细节能够去 开涛的文章 相识。

总的来说此次的改版后许多数据直接从后端读取,不再从前端异步猎取而且我们也做过一些异步加载的优化,多接口 combo 从一致效劳吐出给前端运用。这时候前端就不必再为异步接口的加载时苦脑了,只须要专注体系接口的逻辑。

跟着此次技改,前端的代码也迎来了模块化的时期。我们把一切的前端代码都举行了模块化然后基于 SeaJS 重写,合营 Nginx concat 功用完成了当地模块化开辟,线上效劳端兼并。

单品页前端模块的构造与分别

概览

《京东单品页前端开辟那些不能不说的事儿》

上图能够看出,基本上最中心的模块都在首屏。每一个模块都有零丁的一/多个剧本。代码行数(LOC)由 230+ ~ 1200+ 不等。一般来说代码行数越多代码庞杂性就越高,逻辑越庞杂。很难设想「购置体式格局」这类只要一行属性挑选功用的代码行数却 高达 1200 多行。其重要缘由就在于购置体式格局地点的体系和别的首屏中心体系(库存、促销、地点挑选、白条)都有逻辑上的耦合。

看着不错,但是在一个前端工程师眼里最少应当是如许的(我只取了一些典范的模块,并非悉数):

《京东单品页前端开辟那些不能不说的事儿》

这就可以够诠释为何有的时刻只是加一个很小的东西我们都为斟酌再三然后经由过程 AB 测试提取相干数据,末了后再举行决议计划。单品页的首屏能够说是寸土寸金。

按什么维度分别模块

早先我按模块的属性分别,比方:中心、大众剧本、模块剧本。但用了一段时刻今后发明如许分别在单品这类大型体系中并不科学,由于如许分别出来的代码只要分别的人晓得是什么划定规矩,别的人接办代码很难疾速掌握代码架构,而且特别在模块比较多的时刻不随意马虎保护。

厥后我尝试完整以功用模块在页面上涌现的位置维度分别。如许以来保护起来随意马虎多了,须要修正某个模块代码只须要对照着图内里标识的模块信息就可以随意马虎找到代码。

团体中心模块

我们按页面上的模块构造首屏分别出来这几个中心模块:

  • curmb – 面包屑

  • concat – 联络征询相干商号信息

  • prom – 价钱促销信息

  • address – 区域库存挑选,配送效劳

  • color – 色彩尺码

  • buytype – 合约机购置体式格局

  • suits – 套装购置

  • jdservice – 增值效劳

  • baitiao – 白条付出

  • buybtn – 购置按钮

  • info – 区域提醒信息

项目标团体树形构造是如许的:

《京东单品页前端开辟那些不能不说的事儿》

模块内部构造

比方下面这个大图预览的功用,我悉数放在一个文件夹内里保护,然则逻辑上的 JavaScript 模块是星散的,只是说文件夹(preview)就代表页面上的某一部份功用鸠合。

《京东单品页前端开辟那些不能不说的事儿》

注重文件夹的定名有肯定的划定规矩:

  • 模块剧本与款式名必需一样

  • 须要制造 sprite 的图片一致放在 module/i 目次下面,生成的 sprite 图片也在个中

  • 生成的 mixin 在模块根目次下,便于别的款式文件挪用

我们再来看下自动生成生成的 __sprite.scss 是什么内容:

/* __sprite.scss 自动生成 */
@mixin sprite-arrow-next {
    width: 22px;
    height: 32px;
    background-image: url(i/__sprite.png);
    background-position: -0px -30px;
}

/* preview.scss 手动增添 */
@import "./__sprite";
.sprite-arrow-next {
    @include sprite-arrow-next;
}

注重援用的 mixin 称号和我们须要手动增添的款式类名一致。固然也能够直接生成一个类名对应的款式,然则灵活性不好。比方 hover 的时刻是别的一张图片就没法自动生成了。

前端妙技树

HTML

DOM 节点数

与重营业逻辑的页面差别,重展现的页面寻常具有很高的 DOM 节点数。比方京东首页,一般状况加载完页面一共有 3500 多个 DOM 节点,基本上悉数用于展现商品信息、广告图和内容规划,页面上的三方异步效劳也比较少。特别像频道页基本上没有什么营业上的逻辑,悉数是静态页面。这类页面的特点是更新换代频次高,一年两三次改版很一般,CMS 做模块化后两天换个皮肤都是没题目标。然则这类思绪并不适宜单品页。单品页更重营业逻辑,同时展现层 UI 逻辑也有许多关联。

我自身的履历是:页面上的 DOM 节点数相对不能凌驾 5000 个,不然页面转动的时刻就会涌现卡顿的状况,特别是挪动端。

同步衬着照样异步加载

理论状况下最好做法是后端同步动态衬着页面,然则由于 Web 运用中许多功用都是用户行动驱动的。同步加载不可避免的斲丧了后端效劳资本。比方:非首屏模块(大众头尾、评价)、点击事宜触发的 DOM 内容(异步 tab)。

所以我的履历是:能放到后端做推断衬着的 DOM 就只管放在后端(特别是首屏)。如许做的优点有四点优点

  1. 后端衬着页面相对稳固,不像前端 JavaScript 动态衬着 DOM,能够由于剧本报错或许不可用构成模块都没法展现

  2. 可接见性、SEO 及用户体验也比较好。不会发作剧本的衬着发抖题目

  3. 肯定程度上削减了前端衬着页面的庞杂性,削减前端代码庞杂度

  4. 逻辑一致到一个处所保护起来也随意马虎,而且后端应当为营业逻辑担任,前端应当为展现UI 交互担任

关于异步衬着的模块来说,后端一般须要推断 「页面有什么元素」,以及元素之间的依靠对应关联;而前端须要专注于 「元素应当怎样展现」,UI 层面的交互以及模块与模块之前的逻辑关联。

着实更多的时刻 异步是一种没有要领的要领,也就是说异步是别的计划都处置惩罚不了的状况下才斟酌的。

外链静态资本

只管运用外链 CSS 和 JavaScript 资本,一方面便于缓存,削减效劳同步输出的资本糟蹋。IE 6 内里会有一些可怪的 bug,比方有内联款式 style 标签的页面 A 假如在别的一个页面 B 中的 link 标签中援用,那末这段 style 会在 B 页面也起作用。

运用双协定的 URL

运用 // 来替代http:https: 浏览器会自动顺应两种协定的资本接见,兼容性较好。注重 IE 8 下运用剧本更新 src 为双协定时会涌现 bug,发起运用 location.protocol 来推断然后做兼容处置惩罚。

删除元素默许属性

比方 script 标签默许的 type 就是 text/javascript,假如 script 内里的内容是 JavaScript 时能够不必写 type。别的假如要在页面内里插进去一段不须要浏览器剖析的 HTML 片断时能够将 type 写成 text/x-template(恣意不存在的 type) 用于安排模板文件,一般用来在剧本中猎取其 innerHTML 而无任何负作用。

给剧本掌握元素加上类钩子

在剧本中取页面元素运用 J- 前缀类名,与一般款式类星散。如许做会生成许多冗余的类名,但却很好的降低了款式和剧本的耦合,而且在重构和剧本职位离开团队里会是一条最好实践。

CSS

款式分类

一切页面只同享一个 sass Mixin,内里包括了基本的 sass 语法糖、经常使用类(清浮动、页面团体色彩字体等)。

模块级的款式分为两类:

  1. 与剧本无关的大众款式,零丁在模块文件夹中构造。比方:按钮、标签页。悉数放在 common 模块中保护

  2. 与剧本相干的模块级款式,与对应模块剧本放在一同,能够援用 common 中的大众款式,但不能够被别的模块援用

雪碧图

关于雪碧图 我履历是:永久不要想把一切的图标拼合在一同。按模块而不是按页面去拼 sprite 更合理,更随意马虎保护,然后合营构建东西自动接合生成款式文件才是最好的处置惩罚计划。固然假如你的页面比较简单,那这条划定规矩并不实用。说到这个题目我就得把收藏多年的图片拿出来 show 一把,用现实来说明为何把一切图片都拼在一张图上就肯定是对的。

初期由于年青深信将一切的 icon 拼在一张图上才是圆满的(图 1)

《京东单品页前端开辟那些不能不说的事儿》

厥后保护起来着实不随意马虎,就把按钮悉数零丁接合起来。注重,当时的按钮都是图片,设想方面要求的很严厉。到场购物车按钮做的也异常美丽(图 2)

《京东单品页前端开辟那些不能不说的事儿》

然后这些都不是最典范的,下面这个 promise icon 才是 (图 3)

《京东单品页前端开辟那些不能不说的事儿》

从图内里能够看到,这个功用在第一个版本的时刻只要 7 个 icon,厥后不停增添,最多的时刻到达 77 个。以至于当时每周都邑增添两个的频次。

同时这个 icon 当时接合的时刻手艺上也有题目:不应当把笔墨也切到图片内里,重要缘由是初期 icon 比较少加上外边框款式对齐的题目综合挑选了直接运用图片。

厥后我就以为如许是不对的。然后经由过程和产物的沟通,申明我的斟酌以及新的处置惩罚计划后获得了认同。结果就是对图片不举行拼合,背景上传经由考核的不带笔墨 icon,笔墨由接口输出,然后在产物上做了商定:icon 最多不能凌驾 4 个,代码里也做了响应限定。如许就可以保证页面上的要求数不会太多同时随意马虎体系保护,题目获得了处置惩罚。

恰当运用 DataURI

这个在一些小图片场景方面迥殊适宜,比方 1*1 的占位图、loading 图等,不过 IE 6 并不支撑这类写法,须要的时刻能够加上一些兼容写法:

.ELazy-loading {
    background: url(data:image/gif;base64,R0lGODlhKwAeAJEAAP///93d3Xq9VAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFFAAAACwDAA0AJQADAAACEpSPAhDtHxacqcr5Lm416f1hBQAh+QQJFAAAACwDAA0AJQADAAACFIyPAcLtDKKcMtn1Mt3RJpw53FYAACH5BAkUAAAALAMADQAlAAMAAAIUjI8BkL0CoxQtrYrenPjcrgDbVAAAOw==) center center no-repeat;
    *background-image: url(//misc.360buyimg.com/lib/skin/e/i/loading-jd.gif);
}

关于兼容性

兼容机能够说是前端工程师在寻常开辟中消费很大批无意义事变的处所。关于兼容性我想说的是 假如你不愿意去压服四周的人摒弃或许让他们意想到兼容性是个不能够完整处置惩罚的题目,那末你就得为那些初级浏览器给你带来的痛楚埋单

着实更好的要领是你和设想、产物沟通然后给出一种分级支撑的计划。把每种浏览器定义一个级别。然后在开辟功用的时刻以「渐进加强」的体式格局。一般来说我们的处置惩罚计划是在初级浏览器内里保证流程一般举行、模块能够运用,但疏忽一些可有可无的错位、不透明等题目,在高等浏览器内里须要对设想稿举行准确复原,恰当的加上一些井上添花在细节。比方细小的动画、逻辑细节上的处置惩罚等。

举个例子吧,下面这个进度条示意预定的人数,它是接口异步加载完才展现的。假如加载完就马上设置进度条宽度会显得僵硬无趣,然则假如加上一点动画结果的话就好多了。但是题目又来了,假如加上动画那末逻辑上这个进度条应当是一点点的增添,对应的人数也应当是逐一增添。因而我就做了个优化,让人数在这段时候内匀称的增添。这个细节并非很轻易被人发明,然则这类设想会让用户以为很专心而且有意思。

《京东单品页前端开辟那些不能不说的事儿》

JavaScript

《京东单品页前端开辟那些不能不说的事儿》

单品页的剧本加载/实行递次:

  1. 守候页面准备就绪(DOM Ready)

  2. 准备就绪后加载进口剧本(main.js),剧本担任别的功用模块的调理,动态接合模块经由过程 seajs 的 require.async 要领异步挪用

  3. 大众模块(common.js)担任加初始化全局变量并挂载到 pageConfig 定名空间

  4. 动态模块数组,这个是后端经由过程递次推断处置惩罚生成的一个模块名列表。寻常只包括首屏须要加载的模块

  5. 后加载模块(lazyinit.js)初始化,这个剧本只做一些页面转动才加载的模块事宜绑定。当模块涌如今视口内再运用 require.async 异步加载模块的资本及初始化

进口剧本

大抵代码以下

/**
* 模块进口(1. 大众剧本 2. 首屏模块资本 3. 非首屏「后加载模块」)
*/
var entries = [];

// 页面大众剧本款式
entries.push('common');
// 页面运用到的首屏模块(后端开辟依据页面差别设置须要挪用的模块)
entries = entries.concat(config.modules);
// 非首屏「后加载模块」
entries.push('lazyinit');

for (var i = 0; i < entries.length; i++) {
    entries[i] = 'MOD_ROOT/' + entries[i] + '/' + entries[i];
}

if (/debug=show_modules/.test(location.href)) console.log(entries);

require.async(entries, function() {
    var modules = Array.prototype.slice.call(arguments);
    var len = modules.length;

    for (var i = 0; i < len; i++) {
        var module = modules[i];

        if (module && typeof module.init === 'function') {
            module.init(config);
        } else {
            console.warn('Module[%s] must be exports a init function.', entries[i]);
        }
    }
});

注重模块途径中的 MOD_ROOT 是提早在页面定义好的一个 seajs path。目标是为了把前端版本号更新的掌握权释放给后端,从而处置惩罚了前后端依靠上线差别步构成的缓存耽误题目,设置剧本中只要几个定义好的途径:

seajs.config({
    paths: {
        'MISC' : '//misc.360buyimg.com',
        'MOD_ROOT' : '//static.360buyimg.com/item/default/1.0.12/components',
        'PLG_ROOT' : '//static.360buyimg.com/item/default/1.0.12/components/common/plugins',
        'JDF_UI'   : '//misc.360buyimg.com/jdf/1.0.0/ui',
        'JDF_UNIT' : '//misc.360buyimg.com/jdf/1.0.0/unit'
    }
});

另有一点,在测试环境的页面中版本号(上面代码中的 1.0.12 是一个全量的版本号)是后端从 URL 上动态读取的(运用参数接见就可以够掷中对应版本 item.jd.com/sku.html?version=1.0.12)。如许以来测试环境上就可以够并行测试差别版本的需求,而且互不影响。固然假如差别版本的后端代码也有修正的话如许是不可的,由于后端代码也须要有个对应的版本号。

不过我们已处置惩罚了这个题目。后端会在测试环境里 动态加载后端模板 而且能够做到版本号与前端一致。如许以来合营 git 随意马虎的分支战略就可以够同时并行开辟测试多个需求,不必零丁配多个测试环境。什么?你还在运用 SVN!哦。那当我没说过。

事宜处置惩罚模子

客户端的 JavaScript 代码基本上都是事宜驱动的,代码的加载剖析依靠于浏览器供应的 DOM 事宜。比方 onload, mouseover, scroll 等。

事宜驱动的的模子迥殊实用于异步编程,而 JavaScript 生成就是异步,一切的异步操纵行动都终究会在一个回调函数(callback)中触发。

比方单品页中价钱接口,加载完成后须要更新 DOM 元夙来展现及时价钱;区域挑选接口加载完成后会更新配送信息、库存/商品状况等,伪代码以下:

/* onPriceReady 和 onAreaChange 能够以为都是一个 Ajax 异步函数挪用
 * code 1 和 code 2 实行到的时候是不肯定先后递次的
 */
/* prom.js */
onPriceReady(function(price) {
    // code 1
    $('#price').html(price);
});

/* address.js */
onAreaChange(function(area) {
    // code 2
    $('#stock').html(area.stockInfo);
});

上面的两段代码分别在两个剧本中保护,由于他们的逻辑相对自力。初期并没有关联关联。厥后需求有变,他们之间须要同享一些对方的数据(切换区域后须要从新猎取价钱数据并展现)。然则物理上又不能放在一同经由过程运用全局变量的体式格局同享,而且它们都是异步加载接口后才取到数据的,并不好肯定谁先谁后(非要做到那就只能用全局变量双向推断)。所以如许并不能很好的处置惩罚题目,而且代码的耦合度会成倍增添。

这时候刻我们引入了一种设想形式来处置惩罚这类题目 —— 宣布者/定阅者,我们把这类形式笼统成了自定义事宜代码来处置惩罚这一题目。这段代码是由 YUI 中心开辟者 Nicholas C. Zakas 完成的。代码很简单,事宜对象重要有两个要领 addListener(type, listener)fire(event)

因而我们重构了上面的伪代码:

/* prom.js */
// 在代码中注册一个区域变化事宜,猎取变化后的区域 id
// 然后从新要求价钱接口并展现
Event.addListener('onAreaChange', function(data) {
    getAreaPrice(data.areaIds)
});

onPriceReady(function(price) {
    $('#price').html(price);

    Event.fire({
        type: 'onPriceReady',
        data: 'Any data you want'
    })
});

/* address.js */
onAreaChange(function(area) {
    $('#stock').html(area.stockInfo);

    // 在区域变化后除了做自身该做的事变之外
    // 触发一个名为 onAreaChange 的事宜,用来
    // 关照别的定阅者事宜完成,并通报区域相干参数
    // 这个时刻在 onAreaChange Ajax 回调函数
    // 中就只须要体贴自身的逻辑,别的模块的耦合关联
    // 交给它们自身经由过程定阅事宜来处置惩罚
    Event.fire({
        type: 'onAreaChange',
        data: area.ids
    })
});

须要注重的一点是,必需确保事宜先注册后触发实行,也就是说先 addListener, 再 fire。

一些典范的机能优化点

基本上客户端的 JavaScript 机能题目都来自于 DOM 查找和遍历,在用于的时刻肯定要警惕,能够不经意的一个操纵就会丧失许多机能,特别在低端浏览器中。趁便多说一点,当代的 JavaScript 诠释器自身是很快的,言语层面的机能题目很少碰到。DOM 查找慢是由于 浏览器给 JavaScript 接见页面供应的一套 DOM API 自身慢。

  1. 缓存 DOM 查找,同时 DOM 查找不要凌驾 2000 个,初级浏览器会卡顿

  2. 不要运用链式挪用 find,如:find('li').find('a') 而是 find('li a')

  3. 在切换元素显近况况的时刻,假如元素许多。优先运用 show()/hide() 要领,而不是 css('display', 'block/none') 前者有缓存,后者会强迫触发 reflow

  4. 给节点增添 data-xx 属性在寄存一些数据,经由过程运用 jQuery 的 data('xx') 要领取更高效,削减 DOM 属性接见

  5. 高密度事宜(scroll, mousemove)触发场景请运用撙节要领

  6. 运用事宜代办,而不是直接绑定。假如不肯定代码被挪用次数,能够先消除绑定再绑定具有定名空间的事宜处置惩罚函数

  7. 只管罕用 DOM 动画,运用 CSS 3 动画替代

前端工程化

缘由

前端工程化着实并非近来两年才有的观点。大约在 2013 年的时刻 Grunt 问世的时刻就已有所触及。这类打包东西重要的目标是自动化一些开辟流程,我最早运用 Grunt 来构建代码的时刻只处置惩罚了三个题目:

  1. 兼并紧缩优化款式剧本

  2. 上线完自动备份

  3. 单个文件打包到多目次(汗青缘由一个文件线上的途径有两种,须要传两个目次)

当时我还在组内做过一个分享,有兴致的能够去围观一下 Best Workflow With Grunt

着实这些东西涌现的缘由是:当时前端范畴的种种基本设施很缺少,而前端的事变内容又相对零星。事变时须要开许多的软件。再加上 JavaScript 言语自身也很弱,就连包治理这类基本的东西也没有内置,以至于模块化要经由过程一些第三方类库来完成,比方:RequireJS, SesJS。

东西的重要机能够在我之前的一个分享中找到 前端开辟东西系列

近况

如今前端工程的生态环境由于 NodeJS 的涌现已变得很好了。你能够依据自身的需求选一个适宜的直接用到项目内里。像 Grunt, Gulp, browserify, webpack 等。不过要邃晓这些东西的涌现从另一方面证明了前端开辟生成存在许多的题目:

  • HTML 从降生到 HTML 5 之前险些没有任何变化,DOM 机能生成缺失。所以才有了 Virtual DOM 这类东西

  • CSS 只是一门形貌型的言语,没有变量、逻辑掌握、语句。所以才涌现了 Sass, Less 这类预编译东西

  • JavaScript 号称「高阶的(high-level)、动态的(dynamic)、弱范例的(untyped)诠释型(interpreted)编程言语,适宜面向对象(oop)和函数式的(functional)编程作风」的编程言语,然则言语自身有许多题目(ES 6 之前)。不适宜大型项目标开辟、没有一些高等特征的支撑、同时被别的言语诟病的 callback 作风、单线程实行等。所以才涌现了像 TypeScript, Babel 这类编译成 JavaScript 代码的言语

这些题目险些都是汗青性的缘由和兼容性要素构成的。作为一位好的前端工程师要看清晰近况,然后按自身项目标需求去定制一些前端工程化的计划,而不是同流合污。

挑选

其完成在自身开辟一套前端工程化/自动化流程的本钱已很低了,你只须要进修一些 NodeJS 的学问,合营 NPM 包治理机制,顺手就搞出一个构建东西出来。由于并不须要你去完成什么东西,一切的东西都有现成的包。剧本紧缩有 UglifyJS,CSS 优化有 CSS-min,图片紧缩优化有 PNG-quant 等等。你只须要想清晰自身要到达什么目标,处置惩罚什么题目就可以够抄家伙自身写一套事变流出来。

我自身的阅历也从 Grunt, GulpJS 到如今自造轮子。自身依据需求开辟出来一套集成的打包东西,有兴致的能够去围观一下 Wooo

固然你也能够不必任何打包东西,自身写一些 NPM Script 来完整定制化项目开辟/测试/打包流程。我猜这也是为何如今相似 Grunt 不再那末火,Gulp 迟迟没有宣布 4.0 版本的缘由。写一个构建东西的本钱太低了,而且这类集成的东西很难满足差别的开辟需求。君不知已有人意想到了这一点么why-i-left-gulp-and-grunt-for-npm-scripts

递次、设想、产物

我始终以为递次、设想是为了产物效劳的。好的产物是要注重设想的,好的(前端)工程师是要有一些审美素养。

着实许多时刻手艺处置惩罚计划都是要依据产物的定位来设想的,相识产物需求今后才定制出真正适宜的高效的处置惩罚计划。比如前面讲到的谁人 sprite 案例,假如一开始就和产物议论好计划厥后也不能够有那种失控的状况发作。在产物构成/上线前期能发明题目比上线后发明题目更轻易处置惩罚。

这部份内容和代码无关,就不多说了。但是从前我另有一次分享关于前端、转变

总结

关于单品页的前端开辟本篇文章只是冰山一角,另有许多没有说起,每一个小东西都能够零丁写一篇文章来分享。随后愿望能够有更多的总结和分享。

    原文作者:keelii
    原文地址: https://segmentfault.com/a/1190000006187694
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞