web性能优化

web 性能优化:

1.基本方法:

a.客户端文本资源 minification。

比如 npm install –g minifier html-minify。
minify .css,.js。
htmlminify .html。

b.服务器开启压缩技术

c.优化图片 tinyPng

2.优化 css:

CSS shorthand properties not only are convenient, but also offer us a way to reduce the size of our style sheets by cutting down on excessive and verbose rules.

Using shallow CSS selectors can also significantly reduce the size of a style sheet, as well as make code more maintainable and modular.

Applying the DRY principle with the csscss redundancy checker can further winnow bloated CSS files by enabling you to remove superfluous properties.

避免使用@import。@import 会串行化资源请求。
尽量使用 <link>。可以并行化请求。 # 针对http1.x。

<head>里提前放置 css。
理由:
1) 防止flash of unstyled content 出现。
2) 减少 re-render and repaint the entire DOM.

使用性能更快的选择器。常见的 tag: div,descendant: div ul li ,class: .listitem,direct child: section > ul > li 性能都差不多,其他的 Sibling,Pseudo,Attribute 比较慢。

尽可能使用 flexbox 布局。

例如有 flexbox style:
        parent:> display: flex; justify-content: space-between; flex-flow: row, wrap;
        children: > flex-basis: 24.25%

比较 box model:
        parent: > display:block。
        children:> width: 24.25%;
        往往还会用到 :nth-child selector 调整尾端

The conclusion you can draw is that when it comes to rendering content, flexbox tends to be a better-performing solution. Better yet, it enjoys broad support without vendor-specific prefixes. When used with vendor prefixes, support only increases. If you’re not using flexbox on your websites, it’s rather trivial to retrofit in most cases.

3.images responsive:

  • Delivering responsive images in CSS with media queries, and how supplying the correct image sources to the proper devices can positively impact loading and processing time

  • Delivering responsive images in HTML by using the srcset attribute and the <picture> element

  • Providing polyfill support for the <picture> element and srcset attribute for older browsers in an optimal fashion

  • Using SVG images in both CSS and HTML, and the convenience and flexibility inherent to the format when it comes to optimal display on all devices

4.images else:

  • reduce size, compression or optimizing.
  • use webp.
  • lazy loading images.

5.fonts.

  • 只选择需要 weight 字体
  • 用 css @font-face 确定使用字体
  • 使用 font-display 声明字体未加载时策略
  • 使用 subset 减少字体文件大小

e.g.

@font-face{
    font-family: "Open Sans Light";
    font-weight: 300;
    font-style: normal;
    src: /*
         These local sources are commented out for debugging purposes.
         In any production site, they should be enabled.
         local("Open Sans Light"),
         local("OpenSans-Light"),
         */
         url("open-sans/OpenSans-Light-BasicLatin.woff2") format("woff2"),
         url("open-sans/OpenSans-Light-BasicLatin.woff") format("woff"),
         url("open-sans/OpenSans-Light-BasicLatin.eot") format("embedded-opentype"),
         url("open-sans/OpenSans-Light-BasicLatin.ttf") format("truetype");
         font-display: swap;     # local fallback
         unicode-range: U+0000-007F;    # subset
}  

6.script

- Depending on its position, the <script> tag can block rendering, which delays the display of the page in the browser. Placing <script> tags toward the bottom of the document can speed up the rendering of a page.
- The async attribute can provide further performance benefits if you can manage the execution of scripts that use it.
- Managing the execution of interdependent scripts that use async can be challenging. A third-party script-loading library such as Alameda or RequireJS can provide a convenient interface for managing script dependencies, while also providing the benefit of asynchronous script loading and execution。

7.cache assets

  • 使用 cache contorl:

    no-cache、no-store、stale-witle-revalidate && max-age
    对于各种资源的缓存策略举例:

  • 使用 cdn 资源。举例:

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> 

8.http2

Techniques that reduce the size of assets are things you should still do on HTTP/2. These are techniques such as minification, server compression, and image optimization. Reducing the size of an asset contributes to lower load times, always and forever.

Techniques that combine files are things you should stop doing on HTTP/2. Although useful in alleviating latency in HTTP/1 client/server interactions, requests are much cheaper in HTTP/2, and combining files can have an adverse effect on your caching effectiveness.
  • http2 不去捆绑资源主要是考虑缓存。在一个tcp连接之下,请求更颗粒化,多次请求,延迟不是问题。不过传递资源始终会经历延时,所以内敛化资源比如 css 还是有效。

  • server push 是个好特性,这篇文章包含 preload hint、server push 和 No optimization 的对比:
    https://www.nginx.com/blog/nginx-1-13-9-http2-server-push/

  1. 使用 gulp 自动化以上任务。
    https://github.com/pluckhuang/useGulp

OLOO in JavaScript

在 Js 里 "OLOO" (objects-linked-to-other-objects) 较 OO (object-oriented):

  • 心智模型更直接
  • 语法更简洁
  • 生成的对象更少
  • 而 ES6中对 Class 的支持,只是可读性更好,本质上还是走原型委托。但是引用的 super 是静态绑定。而且还是会动态改变。

所以如果建模的话,选择 OLOO 。

refer https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/objects-classes/ch6.md#review-tldr

JavaScript 普通函数、箭头函数和this

  • 作为对象属性的普通函数,this 绑定为该对象。

  • 作为回调函数的普通函数,this 绑定为被触发对象。

  • 除了 call、apply、bind 以外能指定 this 参数,其余调用普通函数的地方,this 都绑定为全局对象。

  • 箭头函数没有自己的 this,也就是说没有自己的定义域。进一步说,就是会绑定定义时上层代码块的 this。

function Timer() {
    this.s1 = 0;
    this.s2 = 0;
    // 箭头函数
    setInterval(() => this.s1++, 1000);
    // 普通函数
    setInterval(function () {
        this.s2++;
    }, 1000);
}

假如 var timer = new Timer();
此时 timer.s1 可以正常绑定,.s2 被绑定到了全局对象。

再假如,直接调用函数 Timer(),此时 s1 也被绑定到了全局对象。
  • 即使作为对象方法,箭头函数内部的 this 也是指向的全局对象。所以箭头函数不适合作为函数方法。
  • 作为回调函数的箭头函数,this 绑定为全局对象。所以箭头函数不适合动态指定 this 的场合。
var x = 10;

let foo = {
  x: 20,

  // Dynamic `this`.
  bar() {
    return this.x;
  },

  // Lexical `this`.
  baz: () => this.x,

  qux() {
    // Lexical this within the invocation.
    let arrow = () => this.x;

    return arrow();
  },
};

console.log(
  foo.bar(), // 20, from `foo`
  foo.baz(), // 10, from global
  foo.qux(), // 20, from `foo` and arrow
);

一道有意思的Js 题,sum(1,2)(3,4).sumof()…

看到一道题有点意思:

题目:编写函数方法实现
  • 形式1:sum(1).sumof()
  • 形式2:sum(1,2).sumof()
  • 形式3:sum(1)(2, 3).sumof()
  • 最终求得的结果,需要是各个出现的数字的和。
目前想到的写法:
function sum(...lastArgs) {
    var callback = function(...args) {
        return sum(...[ ...lastArgs, ...args ]);
    };
    callback.sumof = function() {
        return lastArgs.reduce((aggregated, number) => aggregated + number, 0);
    };
    return callback;
}

为什么 promise 结合生成器使用更优雅?

promise 用来执行异步任务。

通过链式调用可以一步接一步的执行任务,那么为什么还要结合生成器呢?

比如这样的:

new promise(...).then(val1 => {resolve(val2)}).then(val2 => resolve()).catch();

变成这样的:

function* xx() {
    const val1 = yield new promise(...);
    const val2 = yield new promise(...);
}

最终产生了 async?
变成这样:

async function xx() {
    const val1 = await new promise(...);
    const val2 = await new promise(...);
    return
}

答案是用【同步写法】执行【异步任务】,这样看代码看的更清楚。而且使用了 async,还包括了自动执行,可以直接调用xx()来得到结果。

JavaScript 函数

  • 函数调用共有4种类型

    • 方法调用模式【作为对象属性], this 绑定为动态执行时的对象。因为方法可以被单独应用,所以this随着变化会变化。

      值得注意的是箭头函数,作为方法时 this 绑定到了 window 对象上了。

      因为内部箭头函数方法会在起初声明时就绑定不再变化。

    • 函数调用模式,this 绑定为 Window 对象或 undefined,取决于是否 “use strict”。

    • 构造器(构造函数)调用模式,this 绑定为动态运行时实际创建的对象。

      值得注意的是箭头函数,此时 this 绑定到了 新创建的这个对象上。

    • this,arguments 可被指定、每个函数都有的的 apply /call 调用模式,2者区别在于参数传递,前者传递一个参数数组,后者可传递多个参数,作为参数列表。

javascript 闭包与模块

闭包 closure :

Observational: closure is a function instance remembering its outer variables even as that function is passed around and invoked in other scopes.

<pre>
    <a href="">Visit the Apress website</a>
    <p>I like <span>apples</span> and oranges.</p>
    <a class="myclass1 myclass2" href="">Visit the W3C website</a>
</pre>

var pre = document.getElementsByTagName("pre")[0].children;
add_the_handlers(pre);
// error 
var add_the_handlers = function (nodes) {
    var i;
    console.log(nodes.length);
    for (i = 0; i < nodes.length; i += 1) {
        nodes[i].onclick = function (e) {
            alert(i);
        };
    }
};
nodes 节点可以绑定到 [0-1-2下标],但是 alert 执行时实际是对闭包环境变量的链接引用,此时 i 已经变成了3,因此最后点击时的 i 总会显示为3.
// ok
var add_the_handlers = function (nodes) {
    var helper = function (i) {
        return function (e) {
            alert(i);
        };
    };
    var i;
    for (i = 0; i < nodes.length; i += 1) {
        nodes[i].onclick = helper(i);
    };
}
helper 创建了一个闭包,通过形参记录了每一个 i,同时 onclick 保持对该函数的引用,保持该词法环境一直存在。
onclick 触发时,每个执行函数都有自己对应的词法环境,每个环境里都有自己的 i 值。
// 更简单写法
var add_the_handlers = function (nodes) {
    console.log(nodes.length);
    for (let i = 0; i < nodes.length; i += 1) {
        nodes[i].onclick = function (e) {
            alert(i);
        };
    }
};
每次循环都会创建新的 i

模块,模块模式。利用函数作用域和闭包创建被绑定对象与私有成员的关联。

举例:

var serial_maker = function () {
    var prefix = '';
    var seq = 0;
    return {
        set_prefix: function (p) {
            prefix = String(p);
        },
        set_seq: function (s) {
            seq = s;
        },
        gensym: function () {
            var result = prefix + seq;
            seq += 1;
            return result;
        }
    }
}

var serialm = serial_maker()
serialm.set_prefix("qqqq")
serialm.set_seq(10000)
serialm.gensym()
->qqqq1000

web-frontend base

html:

some tips:

  • data-: 用户自定义属性
  • base 元素 http-equiv 属性,例如 <meta http-equiv=“refresh” content=“5;http://…”> 是指 5sec 后重新载入指定 url
  • target 属性, 新页面跳转显示方式 [_self, _blank]
  • 删除元素 <s></s>

css:

样式应用总结:

  • 1看层叠次序
  • 2看selector-specificity分数,酌情考虑 !import
  • 3看定义次序
  • 4看继承关系,酌情考虑 inherit
  • css中绝对单位:

  • css中相对单位:

  • 布局相关:

    • float: 浮动[left, right, none],clear:阻止浮动元素堆叠[left, right, both, none]。
    • positioning: 定位元素内容[static, relative, absolute, fixed]
    • display:元素盒类型
      — inline ,元素占据行内的一段内容
      — block,元素占据一行
      — inline-block, 同inline 一样,不同是垂直方向上会有空行
      — box model:padding, margin, border;box-sizing: 尺寸应用到元素盒子哪一部分。
      — 布局:colume 多列布局;flex 弹性盒;table表格

js:

  • === 和 == 等同和相等,看类型与值。
    基本类型只是看值,对象类型看应用【类型】
    基本类型相等测试会类型转换

  • null和undefine,空值和未定义。

  • hasOwnProperty ,排除原型属性。

  • 原型

    • Object.create 构造一个已经存在的对象的新实例。
    • Object.prototype 所有通过对象字面量创建的对象会连接
    • Function.prototype 函数对象会隐藏连接到这上面。
  • 扩充类型的功能,通过原型
    内部 this 被绑定为实际上级对象。

  • 闭包: 内部函数会应用外部函数的上下文环境。