Defined

  • Update - 03/29/2018
    重新看该博文, 发现有些内容当时并没有完全理解, 于此修改, 删除无用原文.
    Keyword: 本文探索浏览器如何渲染, script位置, href src与浏览器加载阻塞相关问题
    相关测试环境: Chrome 65.x

Main()

这边记录一下浏览器的渲染机制/顺序

Base

什么是parse(解析)

What parsing the page [email protected]
In this context, is means converting the HTML source code into DOM nodes like elements and text.
Fetching of dependent resources will also continue, but that’s in addition to the parsing.

了解document.readyState

JavaScript Programmer’s Reference

State Value
uninitialized The object is first instantiated but has not begun loading.
loading The object has commenced loading.
loaded The object has completed loading.
interactive The object is loaded but not yet closed but is ready to handle interaction.
complete The object body has been closed and the loading is finished.

这个是关于IE的

msdn
Note For the script element, readyState is no longer supported. Starting with Internet Explorer 11, use onload.

这段话也从github的注释上看到了.
类似的initLoader在mdn发现啦~

简单的通过readyState进行事件加载:

1
2
3
4
5
document.onreadystatechange = function() {
if (document.readyState == "complete") {
initApplications();
}
}

About Parse

Parse Graphic

browser-render
注: gecko - reflow; webkit - layout
图中有几个问题: 图上底部CSS应该改为: CSSOM; script和css均有通过相关parser

原文图

Browser Parse render 简易流程

照图颜色说话:

  1. 先通过 HTML/SVG/XHTML 生成一个基本的DOM树, 并行发起css, img, js请求, 和是否在HEAD标签无关
  2. CSS下载完成, 开始构建CSSOM(object model)树, 结构和dom相对应
  3. 所有CSS均下载完毕, CSSOM构建完成后, 和DOM相互匹配进行渲染(render), 生成Rendering Tree
    ┏ ———————— ┓
  4. Layout: 将树的节点根据自己所拥有的CSS进行定位(计算所处位置)
  5. Painting: 知道了摆放位置和样式了, 之后就是内容填充了, 利用显卡把内容显示在浏览器中.
    ┗ —reflow/layout— ┛

关于parse约束
When the parser gets to a script tag, DOM construction cannot proceed until the JavaScript finishes executing, and the JavaScript cannot be executed until the CSS is downloaded, parsed, and the CSSOM is available.

DOM构建受限, 直到JS完全执行完毕;而JS执行需要依赖CSSOM的完整建立.

href src 区别以及阻塞相关

相应的链接以及知识点

  1. Difference between SRC and HREF
  2. 图片资源到底会不会阻塞浏览器渲染呢
  3. 浏览器渲染流程

第一点的阻塞规则已经不适用现代浏览器, 所以只需要从语义上来理解这个问题:

  • href: 与本身Reference一个意思, 仅仅表示内容与当前页面的关系
  • src: embed the source, 通俗理解就是将内容放入页面中, 例如img, script
  • link.src: 历史遗留, 不做解释

load state 相关

window.onload && interactive

What is the difference between Window.load and document.readyState
window.load - This runs when all content is loaded, including images.
document.ready - This runs when the DOM is ready, all the elements are on the page and ready to do, but the images aren’t necessarily loaded.

第二篇参考文: window.onload和jquery.ready有什么区别么? - segmentfault
代码演示: // 必须放在头才能了解具体加载

interactive VS onDOMContentLoaded

规范在这: w3
有点懒得去翻译了… 如有疑问请直接翻阅w3文档.

state 等状态更替顺序

readyState.x > Scripts > onDOMContentLoaded or more

性能优化相关

使用performance(timeline) 自己探究

official link 时间顺序查看相关load内容/顺序

在performance界面发现: 虽然css, image, fonts, image同时被请求, 但是这些资源被浏览器打上了priority tag.
加载顺序如下:

fonts(Highest) > CSS(Highest) > JS(High) > image(Low)

html5 Script sync defer

用图来解释:

  • script defer
    script-defer

  • script async
    script-async

async会使当前script的priority为low, 和img同一层次加载(表示不那么重要).

Note: Attributes async and defer work only for external scripts. They are ignored if there’s no src.

new feature: Preload

1
<link rel="preload" href="very_important.js" as="script">

针对于用户体验, 可以尝试用link特性来提高parse priority

Reference

building the DOM faster speculative parsing async defer and preload | Mozilla High Priority, modern browser. 需要反复研读.
How browsers work - newly page
浏览器的渲染原理简介-陈皓
CSS渲染优化
JS 一定要放在 Body 的最底部么?聊聊浏览器的渲染机制 - 德来 反复研读才觉得有道理.
该链接关于reflow条件需要去google http://arvindr21.github.io/howBrowserWorks/#/39

PS

本文涉及到满多原理的, 可能存在理解错误的情况, 有问题请email.

Defined

整理gist的时候发现有这个问题, 发现内容还蛮丰富的, 顺便承接上文关于浏览器加载

Main()

什么是parse(解析)

What parsing the page [email protected]
In this context, is means converting the HTML source code into DOM nodes like elements and text.
Fetching of dependent resources will also continue, but that’s in addition to the parsing.

href VS src

该点用于解释script位置的问题.

interactive VS onDOMContentLoaded

规范在这: w3

中文解释如下: 简要概括, 一些内容已经删减!

  • 一旦document停止解析(stop parsing), 则必须执行以下步骤:
  1. document.readyState 改成interactive;
  2. 页面开始run script in list of scripts, 通俗的理解, script标签;
    3.

Reference

Difference between SRC and HREF

Defined

new front chains - 3 ESLint and Prettier

Env: npm5.x

Main()

init

npm init
eslint init or use gist file downbelow

dependence

npm –save-dev install eslint eslint-loader

extends: airbnb

  • install(npm5+) airbnb-extends

    npx install-peerdeps –dev eslint-config-airbnb

  • .eslintrc

    1
    2
    3
    4
    5
    {
    ...
    "extends": "airbnb",
    ...
    }

and it may be too strict, so, I’ll use eslint:recommended instead.

parser: babel-eslint

for ES6 support

  • install

    npm install –save-dev babel-eslint

  • .eslintrc

    1
    2
    3
    4
    5
    {
    ...
    parser: "babel-eslint",
    ...
    }

with webpack

webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
module.exports = {
// ...
module: {
rules: [
{
enforce: "pre",
test: /\.js$/,
exclude: /node_modules/,
loader: "eslint-loader",
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
},
],
},
// ...
}

Lint with scripts

package.json

1
2
3
4
5
"scripts": {
// lint all js file in src folder
"lint": "eslint --ext .js src"
"lint-fix": "eslint --fix --ext .js src"
}

eslint-plugin-react

this will auto install when you initial eslint with react option

rules

propTypes js 类型检测(type detection)

prettier

maybe update lately, here is the link

Reference

Defined

Get the question when looking up for templates engine realization.
And this article mainly focus RegExp.test() and (?!) Negative lookahead condition.

Main()

Code

  • And the explanation

Negative lookahead

Symbol: A(?!B)
Function: Match A whose word behide it is NOT B.

Global Flag

Mainly talking about g flag.

  1. withoutG VS withG2
    test function will save the pattern match session, so the 2nd withG search will return false;
    and global will return back to index 0 to repeat check the str, 3rd is true, of course;
  2. withG, str, repeatStr
    in 2nd loop, withG’s output is not like the withG2 though they are same RegExp, because of the tmpStr reset withG’s match string, so withG’s result always get true even it has global flag.

PS: Same as RegExp.exec()

Reference

test | MDN
regexr

Defined

Came across RegExp Object prob when tring to learning template engine writing.

Main()

From the refer link
I recommend that you do not use the RegExp constructor with a literal string, because in literal strings, backslashes must be escaped. The regular expression \w+ can be created as re = /\w+/ or as re = new RegExp("\\w+"). The latter is definitely harder to read. The regular expression \\ matches a single backslash. In JavaScript, this becomes re = /\\/or re = new RegExp("\\\\").

and the demo code is:

1
2
3
4
let template = 'My age is <span>${age}</span></p>';
console.log(template.replace(/\${age}/, 22)); // It works
console.log(template.replace(new RegExp('\${age}', 'g'), 22)); // Not worked
console.log(template.replace(new RegExp('\\${age}', 'g'), 22)); // It works

PS: I just came across this prob a moment before, but I can remember it today, so Record it.

Reference

regular-expressions

Defined

It really take me time to transfer my all usage habbits from windows to macOS even I did experienced the Linux operation system.

Environment

MacOS Version 10.13.3~

Notice Before

  • Command - Meta - Cmd
  • Option - Alt
  • Key writing order: Ctrl > Shift > Cmd > Alt > X

Main()

App in Use

Classify by demands.

KeyMap:

Key Exchange just like as windows

CapsLock <=> Ctrl

Reson: Great position of command and dual-alt

Shortcuts

Key mapping

  • Command ⌘
  • Shift ⇧
  • Option ⌥
  • Control ⌃
  • Caps Lock ⇪
  • Delete back ⌫

Internal Integration

Customized

  • Chrome Extension
    Browser shortcuts in macOS almost done by Cmd, so need Ctrl to replace

Atom

this sync setting link should be more detailed. Plugin Vim :noh’s replacement key? TODO: find the key
and more shortcuts in here

With Vim plugin

jetBrains XStorm

Got a batter Link - CN
TODO: material design theme, cursor color red change to ?

Accessibility Hack

  • Smooth Dragging with Single Hand: Mouse & TrackPad => Trackpad Option => Enable Dragging
  • create customize shortcuts | Automator
  • Open terminal in thie folder: System > Keyboard > Service > Files and Folder > New Terminal at Folder
  • Close Dashboard: System Settings > Mission Control > Dashboard: off
  • Smooth Finder: Finder > View > View

Reference

best app in Mac | Github
关于lion下触控板“单指双击拖动”的找回方法
更改用户名丧失管理员权限
你可能不知道的 Mac 技巧 - macOS 的窗口、标签与工作区
What keyboard shortcuts move, resize, and maximize windows under Mac OS X? | stackoverflow
more in ZSH | Medium
westwind | finder-shortcuts

Defined

new front 自动工程化 step 2: webpack.
Env: Windows10 + webpack4.x

webpack.config.js

package.json

Quick build shortcuts:

{ “build”: “webpack -p” }

不过现在需要独立安装webpack-cli才能执行上述操作.
而且bundle文件会默认创建在/dist目录下

Base Commands

option decription
webpack -p building for production (min file) - Production Mode
webpack -d including source maps - Debug Mode
webpack –watch for continuous incremental building
webpack –colors making building output pretty

with multi-entries

custom distribute folder | Advanced

Realize with plugins;

in this case, more info with path in NodeJS;
and the path.resolve is just like arr1.concat(arr2, arr3)

with Bable-loader | Backward Compatibility

Module.use and Bable-loader

CSS integration | Normal

CSS file compile into bundle.js, which means style act as like a js Object

1
2
3
4
5
6
7
8
9
10
11
module.exports = {
/* codes ... */
module: {
rules:[
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
},
]
}
};

Webpack style-loader vs css-loader
css-loader: do as url-loader like, just load the css
style-loader: adds CSS to the DOM by injecting a <style> tag

CSS integration | Advanced

React - css module - SASS
实际运用参考: Github-CN
以前看到的BEM style真的被用了上去… 有点痛MindBEMding, 不过这也有一个非常大的优点: performance, 相当于每个style都是唯一, 所以不需要2+级的selector
利用js控制CSS, 也就是所谓的css in js 基础应用 | withou twebapck
CSS Module; 通过名字就能知道核心: module, CSS Module详解 - CN
淘的一个demo 实战参考: webpack-demo

PS: 这一节内容很多, 有点消化不良.

Image Loader | Normal

Base64 limit: only for small/tiny image
just like bable-loader, API page: url-loader | npm

Main.js

1
2
3
let img = document.createElement('img');
img.src = require('./img.png');
document.querySelector('.container').appendChild(img);

The webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module.exports = {
/* codes... */
module: {
rules: {
test: /\.(gif|png|jpg)$/,
use: {
loader: 'url-loader',
options: {
limit: 8192, // 8Mb
}
}
}
},
}

Plugin Mode

take UglifyJs as an example.

Normal plugin list

  • UglifyJs convert x.js into x.min.js
  • html-webpack-plugin create index.html; open-browser-webpack-plugin open default browser tab when webpack loads.
  • user-defined plugin like env

Enviornment flags

with user-defined object as plugin

webpack4.0 new option
The ‘mode’ option has not been set. Set ‘mode’ option to ‘development’ or ‘production’ to enable defaults for this
environment.

flag: --mode development / production in scripts

code split

doc

Chunks

  • Common Chunk
  • Vendor Chunk

Exclude js file

Not being converted into bundle.js
webpack.config.js

1
2
3
4
5
externals: {
// require('data') is external and available
// on the global var data
'data': 'data'
}

finished by 03-03.

Reference

webpack-demos V3.1 | ruanyifeng
webpack | official web site

Defined

为转型成现代化前端开始的一条路. 以Manual形式为以后自己作参考

Main()

config

展示所有配置 list可缩写为ls

npm config list -l

获取具体配置 类似于js取属性

npm config get prefix

列出所有module local/global 目录深度 --depth=x

npm list –global –depth=1

package.json

未注明这个tag写的都是json一级对象的内容.

本地建立 --y为一律yes

npm init

这里涉及到相关license,简图 link

modules

json path:

{ dependencies: && { devDependencies:

在work folder下安装各种pack时会自动创建dependencies或者devDependencies对象用于各种平台适配, 保留了各种version.
dev类似于debug模式, 生产模式禁用.

安装

npm install –save[-dev] xxx

卸载

npm uninstall xxx

检查更新 - wanted表示compatible版本(不需要改动原有代码保证兼容性)

npm outdated

更新 link2

npm update [--save/-S]

关于更新有必要提到更多: 涉及到兼容性问题: 即如果不确定pack的稳定性优先使用~

  • ~1.1.1 Tilde Dependence Range: 1.1.1 <= Version < 1.2.0
  • ^1.1.1 Caret Dependence Range: 1.1.1 <= Version < 2.0.0
  • –save 和~可以一起理解为, 如果minor(1.2.x) 版本测试通过, 可以通过该符号表示最低兼容版本升级.

搜索

npm search xxx

{ scripts:

优点: 定制化 有点像linux里面的alias

1
2
3
4
5
scripts: {
"start": "http-server",
"test": "node test.js"
"dev": "node dev.js"
},

执行script (start可以省略run)

npm run dev

{ version:

Semantic Versioning 个人项目精简一下:
version x.y.z
初始版本应该是0.1.0 因为刚开发出来都是没有bug(暂时没发现)的版本. pre-release就不写了

  • z 基本bug修复
  • y 向下兼容的新功能添加
  • x 大版本更新, 例如大规模API更新/替换等会破坏原有代码结构.

package-lock.json

npm5.x.x版本的产物, 搜索的时候看来是模仿的yarn lock file.作用如下

Everything You Wanted To Know About package-lock.json But Were Too Afraid To Ask
The Goal
The purpose of the package-lock is to avoid the situation described above, where installing modules from the same package.json results in two different installs. Package-lock.json was added in npm version 5.x.x, so if you are using major version 5 or higher, you will see it generated unless you disabled it.

这个json的出现是为了保证在任何开发环境下node_modules永远一致, 不会因为像package.json一样每次安装会出现不同的包而开发出来的文件.

如下文所说:

Because the package-lock specifies a version, location and integrity hash for every module and each of its dependencies, the install it creates will be the same, every single time. It won’t matter what device you are on, or when in the future you install, it should give you the same result every time, which is very useful.

还有一个比较重要的点, 平滑过渡所需要做的:

No more deleting that package-lock just to run npm install and regenerate it

Reference

npm 入门教程 | 众成翻译
Everything You Wanted To Know About package-lock.json But Were Too Afraid To Ask || Medium

Defined

ES6补充内容. 技术对接/转型ING. not support IE, 生产环境需要转换一下.

Main()

根据Refer, 以例子为主作为平时参考.

Why Promise

关于回调地狱(Callback Hell)直到前段时间写的一个项目我才有点意识到是怎么回事情: 一个稍微复杂的前端逻辑, 需要对一件事情在不同阶段/不同状态进行相关处理, 和画逻辑图一个概念, 传统的callback会导致函数一直层级向下直到逻辑处理完毕(minimap显示起来像个>). 而且Promise在开发的时候就更加规范化, 不像自定义的callback自由度很高(乱);每个promise拥有一个状态逻辑处理, 也就是更加模块化.

Base

从传统的callback过度

以onload事件为主的基础promise使用

XHR mode

XHR + 链式调用(调用完返回新的promise对象)

then 链式传值

simple calculation with promise-chain
then 会new一个Promise对象, 并把return作为参数引入

错误样例

针对前面做的补充: 错误样例. 需要注意规范, 利用链式保证对象的准确性.

PS: Releasing Zalgo

这个问题是关于传统callback的async和sync混用问题. 现在看到的大部分方式是以异步方法将同步代码转换为异步代码.
Example: 浏览器setTimeout(callback, 0) nodeprocess.nextTick(callback)
而Promise的规范限制他只能使用异步调用, 所以相关混用问题就不容易出现了.

Reference

promise-mini | gitbook

Nodes

node: DOM > HTML

Normal internal API/property

Property
firstChild
lastChild
childNodes
previousSibling
nextSibling
nodeType
attribute

Node Type

Property value
Node.ELEMENT_NODE 1
Node.TEXT_NODE 3
Node.COMMENT_NODE 7
Node.DOCUMENT_FRAGMENT_NODE 11

Normal operation code

Node大部分操作都是通过对子节点的操作API,也就是说必须获得parentNode

  • select:

    document.querySelector();
    Ele.querySelectorAll();

  • append:

    parentEle.appendChild(childEle);
    parentEle.insertBefore(newEle, referenceEle);

  • prepend:

    1
    2
    3
    function prependChild(newNode, parentNode) {
    parentNode.insertBefore(newNode, parentNode.firstChild);
    }
  • replace:

    parentNode.replaceChild(newChild, oldChild);

  • clone: 不带事件绑定

    Ele.cloneNode(true); // 带上子节点
    Ele.cloneNode(flase[default value]); // 仅复制自身节点

  • create:

    document.createElement(‘div’);
    document.createTextNode(‘text’);

  • delete:

    node.parentNode.removeChild(node);
    node.remove(); // IE not support

  • more with Node control: Link | MDN

firstChild VS firstElementChild

firstChild include other nodes like textNode. Refer #Node Type.

Attr

hasAttribute(attrName);
getAttribute(attrName);
setAttribute(attrName, value);
removeAttribute(attrName);

Node 效率/资源相关

  • 查询
    每个节点都有childNodes属性,,它保存了这个节点所有 直接 子元素

调用childNodes返回的是一个NodeList对象,它极其像数组,但是有一个最关键的地方,它是动态查询的,也就是说每次调用它都会对DOM结构查询,所以对它的使用需要慎重,注意性能

可利用 Node.hasChildNodes() Node.contains() 进行子节点查询

  • 批量创建node – with document.createDocumentFragment
    这个速度差别很大, 性能方面优先考虑
    #nodeType 中, 可以看到fragment node依然存在, 需要注意这个点

PS: the difference between innerText and textContent
the main diff performance:

About classList

Ele.classList.[]

  • add()
  • remove()
  • toggle(String[, condition]) condition: Boolean true/false
  • contains() return: Boolean true/false

About Style

  • get

    window.getComputedStyle(Ele[, pseudoEle]);

  • set

    Ele.style.xxx = ‘xxx’; // attention: camel style
    Ele.setAttr(‘style’, …);

Less code with select

Reference

通俗易懂的来讲讲DOM
JavaScript操作DOM的那些坑