npm安装方式的区别

npm install moduleName # 安装模块到项目目录下

npm install -g moduleName # -g 的意思是将模块安装到全局,具体安装到磁盘哪个位置,要看 npm config prefix
的位置。

npm install -save moduleName # -save
的意思是将模块安装到项目目录下,并在package文件的dependencies节点写入依赖。

npm install -save-dev moduleName # -save-dev
的意思是将模块安装到项目目录下,并在package文件的devDependencies节点写入依赖。

那么问题来了,在项目中我们应该使用四个命令中的哪个呢?这个就要视情况而定了。下面对这四个命令进行对比,看完后你就不再这么问了。

npm install moduleName 命令

1. 安装模块到项目node_modules目录下。

2. 不会将模块依赖写入devDependencies或dependencies 节点。

3. 运行 npm install 初始化项目时不会下载模块。

npm install -g moduleName 命令

1. 安装模块到全局,不会在项目node_modules目录中保存模块包。

2. 不会将模块依赖写入devDependencies或dependencies 节点。

3. 运行 npm install 初始化项目时不会下载模块。

npm install -save moduleName 命令

1. 安装模块到项目node_modules目录下。

2. 会将模块依赖写入dependencies 节点。

3. 运行 npm install 初始化项目时,会将模块下载到项目目录下。

4. 运行npm install
–production或者注明NODE_ENV变量值为production时,会自动下载模块到node_modules目录中。

npm install -save-dev moduleName 命令

1. 安装模块到项目node_modules目录下。

2. 会将模块依赖写入devDependencies 节点。

3. 运行 npm install 初始化项目时,会将模块下载到项目目录下。

4. 运行npm install
–production或者注明NODE_ENV变量值为production时,不会自动下载模块到node_modules目录中。

总结

devDependencies 节点下的模块是我们在开发时需要用的,比如项目中使用的 gulp
,压缩css、js的模块。这些模块在我们的项目部署后是不需要的,所以我们可以使用 -save-dev 的形式安装。像 express
这些模块是项目运行必备的,应该安装在 dependencies 节点下,所以我们应该使用 -save 的形式安装。

使用原则:

运行时需要用到的包使用–save,否则使用–save-dev。

npm install 会下载dependencies和devDependencies中的模块。它到哪里去找这些模块?其实,当我们执行npm intall
命令时, 会根据package.json/package-lock.json中的依赖去下载模块。

使用Mock.js进行独立于后端的前端开发

解决的问题

开发时,后端还没完成数据输出,前端只好写静态模拟数据。

  • 数据太长了,将数据写在js文件里,完成后挨个改url。

  • 某些逻辑复杂的代码,加入或去除模拟数据时得小心翼翼。

  • 想要尽可能还原真实的数据,要么编写更多代码,要么手动修改模拟数据。

  • 特殊的格式,例如IP,随机数,图片,地址,需要去收集。

  • 超烂的破网速…

以上都不再是问题

接下来体验 拦截ajax请求并返回模拟数据。

概述

Mock.js实现的功能

  1. 基于 数据模板 生成数据

  2. 基于 HTML模板 生成数据

  3. 拦截并模拟 Ajax请求

用法

浏览器:

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
<!-- (必选)加载 Mock -->

<script src="http://mockjs.com/dist/mock.js"></script>

<script>

// 使用 Mock

var data = Mock.mock({

    'list|1-10': [{

        'id|+1': 1

    }]

});

$('<pre>').text(JSON.stringify(data, null, 4))

.appendTo('body')

</script>

_

_

返回值:

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
{

"list": [

    {

        "id": 1

    },

    {

        "id": 2

    },

    {

        "id": 3

    }

    ]

}

JQuery:

配置模拟数据:

1
2
3
4
5
6
7
8
9
Mock.mock('http://g.cn', {

    'name'     : '@name',

    'age|1-100': 100,

    'color'    : '@color'

});

发送Ajax请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$.ajax({

    url: 'http://g.cn',

    dataType:'json'

    }).done(function(data, status, xhr){

    console.log(

    JSON.stringify(data, null, 4)

    )

});

** **

返回数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 结果1

{

"name": "Elizabeth Hall",

"age": 91,

"color": "#0e64ea"

}

// 结果2

{

"name": "Michael Taylor",

"age": 61,

"color": "#081086"

}

_ _


Node.js:

// 安装

npm install mockjs
// 使用

1
2
3
4
5
6
7
8
9
10
11
12
13
var Mock = require('mockjs');

var data = Mock.mock({

    'list|1-10': [{

        'id|+1': 1

    }]

});

console.log(JSON.stringify(data, null, 4))

_ _


Angular.js:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<!-- 引用 -->

<script src="http://mockjs.com/dist/mock-min.js"></script>

<script
src="http://cdn.staticfile.org/angular.js/1.3.0-beta.13/angular.min.js"></script>

<!-- 兼容angular (mock.js默认不兼容angular,需额外引用兼容包)-->

<script src="./src/mock.angular.js"></script>

<!-- 模拟数据 -->

<script src="./mockData.js"></script>

<!-- 使用 -->

<script>

(function() {

    (function() {

        var app;

        app = angular.module('app', []);

        //使用mockjax方法覆盖Ajax请求

        Mock.mockjax(app);

        return app.controller('appCtrl', function($scope, $http) {

            var box;

            box = $scope.box = [];

            $scope.get = function() {

                $http({

                    url: 'http://www.baidu.com',

                    method: 'POST',

                    params: {a: 1},

                    data  : {b:1}

                }).success(function(data) {

                return box.push(data);

            });

            $http({

                url: 'http://baidu.com'

                }).success(function(data) {

                console.log(data);

                });

            };

        return $scope.get();

        });

    })();

}).call(this);

</script>

_ _

mock数据mockData.js:

1
2
3
4
5
6
7
8
9
Mock.mock('http://www.baidu.com', {

    'name': '@name()',

    'age|1-100': 100,

    'color': '@color'

});

** **


语法

Mock.js 的语法规范包括两部分:

  1. 数据模板定义(Data Temaplte Definition,DTD)

  2. 数据占位符定义(Data Placeholder Definition,DPD)

数据模板定义 DTD

数据模板中的每个属性由 3 部分构成:属性名、生成规则、属性值:

// 属性名 name

// 生成规则 rule

// 属性值 value

‘name|rule’: value

注意:

  • 属性名 和 生成规则 之间用 | 分隔。

  • 生成规则 是可选的。

  • 生成规则 有 7 种格式:

    1. ‘name|min-max’: value

    2. ‘name|count’: value

    3. ‘name|min-max.dmin-dmax’: value

    4. ‘name|min-max.dcount’: value

    5. ‘name|count.dmin-dmax’: value

    6. ‘name|count.dcount’: value

    7. ‘name|+step’: value

  • 生成规则 的 含义 需要依赖 属性值 才能确定。

  • 属性值 中可以含有 @占位符。

  • 属性值 还指定了最终值的初始值和类型。

生成规则和示例:

1. 属性值是字符串 String
  1. ‘name|min-max’: ‘value’ 通过重复 ‘value’ 生成一个字符串,重复次数大于等于 min,小于等于 max。

  2. ‘name|count’: ‘value’ 通过重复 ‘value’ 生成一个字符串,重复次数等于 count。

2. 属性值是数字 Number
  1. ‘name|+1’: 100 属性值自动加 1,初始值为 100

  2. ‘name|1-100’: 100 生成一个大于等于 1、小于等于 100 的整数,属性值 100 只用来确定类型。

  3. ‘name|1-100.1-10’: 100 生成一个浮点数,整数部分大于等于 1、小于等于 100,小数部分保留 1 到 10 位。

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
{

'number1|1-100.1-10': 1,

'number2|123.1-10': 1,

'number3|123.3': 1,

'number4|123.10': 1.123

}

// =>

{

"number1": 12.92,

"number2": 123.51,

"number3": 123.777,

"number4": 123.1231091814

}
3. 属性值是布尔型 Boolean
  1. ‘name|1’: value 随机生成一个布尔值,值为 true 的概率是 1/2,值为 false 的概率是 1/2。

  2. ‘name|min-max’: value 随机生成一个布尔值,值为 value 的概率是 min / (min + max),值为 !value 的概率是 max / (min + max)。

4. 属性值是对象 Object
  1. ‘name|min-max’: {} 从属性值 {} 中随机选取 min 到 max 个属性。

  2. ‘name|count’: {} 从属性值 {} 中随机选取 count 个属性。

5. 属性值是数组 Array
  1. ‘name|1’: [{}, {} …] 从属性值 [{}, {} …] 中随机选取 1 个元素,作为最终值。

  2. ‘name|min-max’: [{}, {} …] 通过重复属性值 [{}, {} …] 生成一个新数组,重复次数大于等于 min,小于等于 max。

  3. ‘name|count’: [{}, {} …] 通过重复属性值 [{}, {} …] 生成一个新数组,重复次数为 count。

6. 属性值是数组 Function

‘name’: function(){} 执行函数 function(){},取其返回值作为最终的属性值,上下文为 ‘name’ 所在的对象。

数据占位符定义 DPD

占位符 只是在属性值字符串中占个位置,并不出现在最终的属性值中。占位符 的格式为:

@占位符

@占位符(参数 [, 参数])

注意:

  1. 用 @ 来标识其后的字符串是 占位符。

  2. 占位符 引用的是 Mock.Random 中的方法。

  3. 通过 Mock.Random.extend() 来扩展自定义占位符。

  4. 占位符 也可以引用 数据模板 中的属性。

  5. 占位符 会优先引用 数据模板 中的属性

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
{

name: {

first: '@FIRST',

middle: '@FIRST',

last: '@LAST',

full: '@first @middle @last'

}

}

// =>

{

"name": {

"first": "Charles",

"middle": "Brenda",

"last": "Lopez",

"full": "Charles Brenda Lopez"

}

}

常用方法

Mock.mock( rurl?, rtype?, template|function(options) )

根据数据模板生成模拟数据。

参数的含义和默认值如下所示:
  • 参数 rurl:可选。表示需要拦截的 URL,可以是 URL 字符串或 URL 正则。例如 //domain/list.json/、’/domian/list.json’。

  • 参数 rtype:可选。表示需要拦截的 Ajax 请求类型。例如 GET、POST、PUT、DELETE 等。

  • 参数 template:可选。表示数据模板,可以是对象或字符串。例如 { ‘data|1-10’:[{}] }、‘@EMAIL’。

  • 参数 function(options):可选。表示用于生成响应数据的函数。

  • 参数 options:指向本次请求的 Ajax 选项集。

Mock.mockjax(library)

覆盖(拦截) Ajax 请求,目前内置支持 jQuery、Zepto、KISSY。

Mock.Random

Mock.Random 是一个工具类,用于生成各种随机数据。Mock.Random 的方法在数据模板中称为“占位符”,引用格式为 @占位符(参数 [, 参数]) 。

Mock.tpl(input, options, helpers, partials)

基于 Handlebars、Mustache 的 HTML 模板生成模拟数据。

方法使用详情请参考mock.js文档


参考

演示: mock-demo

演示: mock-angular-demo

参考: mock.js

源码: mock-angular

什么样的浏览器内核,才敢说是“自主研发”?内核科普长文

宣称国内“自主研发”的红芯浏览器,在宣布获得 C 轮 2.5 亿投资之后,被大家所关注。微博用户 @Touko
在将其安装包加压后发现,所谓的自主研发,不过是将 Chrome 浏览器进行了一次 “换肤” 处理。

红芯浏览器当天晚上就将官网上下载渠道给关闭了,理由是技术部门自查,后续发公告承认内部使用 Chrome 内核,在开源的 Chrome
内核的基础之上,进行二次开发。

最后“红芯公司”也就此次事件进行道歉,称其夸大的自主研发,并承认确实是在开源的 Chromium 之上进行的二次开发,算是尘埃落定了。

不过话说回来,在技术领域如何才能被大家承认是浏览器内核的“自主研发”?让我们借此机会,回顾一下浏览器内核的发展历史。

什么是浏览器内核

首先应该弄清楚,浏览器的构成。

简单来说,浏览器可以分为两个部分:Shell 和内核。Shell
就是指的浏览器的外壳,例如:菜单、工具栏等为浏览器提供便捷的用户可操作界面、参数配置等等。Shell
其实都是很丰富的,国内的大部分浏览器,其实就是拿现有的内核,定制不同的 Shell,而一些有能力的会在内核之上做一些定制化的修改。

对于浏览器而言,内核才是它的核心。浏览器内核也可以被分为两部分:

  • 渲染引擎(Rendering Engine)

  • JS引擎(JS Engine)

渲染引擎主要负责将网页内的元素(HTML、CSS、图像)等渲染成它对应的样子,输出至显示器或打印机。而不同的浏览器,渲染的效果是有差异的,这就是为什么前端工程师要对不同的浏览器进行适配的原因。

JS 引擎则是解析 JavaScript 语言,执行 JavaScript 来实现网页的动态效果和逻辑。

最初渲染引擎和 JS 引擎并没有区分的很清晰,而后来 JS 引擎越来越独立,后期说到浏览器内核就是单纯的指渲染引擎。

除了一些小众的非商用的免费内核,比较常见的浏览器内核可以分为四种:Trident、Gecko、Blink、WebKit。接下来我们分别介绍他们。

Trident(IE 内核)

Trident 的前身是微软的 Mosaic(历史上第一款浏览器),Trident 就是在 Mosaic 代码的基础之上修改而来,对外输出的产品就是微软的
IE,所以它也被称为 “IE 内核”。

Trident 一款开放的浏览器内核,在当初来看,其内核设计的相当成熟,而它又作为 Windows 的系统内置浏览器,使得 Trident
在很长的一段时间内一家独大。导致有点膨胀,这直接导致两个后果。

  • 与 W3C 标准严重脱节,这也是为什么前端工程师抵触做适配 IE 这件事情。

  • 本身存在了大量 Bug 以及安全性的问题,没有被重视和得到解决。

IE 的膨胀也致使很多用户转向了其他浏览器,Firefox 和 Opera
就是在那个时间段崛起的。当选择不再单一的时候,许多开发人员也就开始注意网页标准和非 IE 浏览器的渲染效果问题。

说到 IE 浏览器,再说点冷知识,IE 在 Mac OS 下在版本「Internet Explorer for Mac」,其内核使用的并非 Trident
内核,而是 Tasman 内核。与 Trident 相比,Tasman 内核对网页标准,有更好的支持。这个事情知道一下就好了。

IE 浏览器从开始的膨胀到现在的开放态度、拥抱标准,这一路走来,其实是经历了很多次大的改动,例如 IE8 的 JS 引擎是 JScript,IE9
则开始使用 Chakra,这两个版本区别很大,Chakra 无论在速度和标准方面都很出色,IE9
算是一个大版本的改动,之下已经形成断层,这也是为什么很火的前端框架 VUE 也只敢对 IE 说兼容到 IE9+。

Trident 在国内的使用还是占很大的市场的,大部分所谓的双核浏览器,其中一核指的正是 Trident ,就是所谓的“兼容模式”。

Gecko (Firefox内核)

Gecko 原本是网景浏览器(Netscape)所采用的内核,后来 Mozilla Firefox(火狐浏览器)也采用了该内核。并且在使用 Gecko
内核的浏览器当中,因为 Firefox 的市场占有率最高,有时也会将它称为 Firefox 内核。

Gecko 引擎和 IE 也有一些渊源,正是因为 IE 的膨胀,也导致了微软内部一些开发人员对其不满,他们选择离开微软和当时已经停止更新的 Netscape
团队中的一些成员,一起创建了 Mozilla。以当时的 Mosaic 内核为基础重新编写内核,这才有了后来的 Gecko。而 Gecko
又是完全开源的,因此可开发的程度很高,导致大量的程序员在其之上编写代码、增加功能,当时出现了一大批以 Gecko 为内核的浏览器,但是只有 Firefox
被大家记住了。

WebKit(Safari内核)

WebKit 的前身是 KDE 小组的 KHTML,WebKit 所包含的 WebCore(渲染引擎)和 JSCore 引擎来自 KDE 的 KHTML 和
KJS。

当年 Apple 公司比较了 Gecko 和 KHTML 后,选择了 WebKit,因为它拥有更清晰的源码结构和极快的渲染速度。Apple 将 KHTML
发扬光大,推出了以 KHTML 为基础的改进型 WebKit 引擎,并使用在自己的浏览器 Safari 之上。

虽然 WebKit 的鼻祖是 Safari,但是很多时候我们提到它就会联想到 Chrome,其实早年间 Chrome 确实使用的是 WebKit 内核,它将
WebKit 内核深入人心了,后面我们再详细介绍。

Chromium/Blink(Chrome 内核)

Google 在 2008 年发布了 Chrome 浏览器,使用的内核被命名为 Chromium。

Chromium 在 WebKit 的基础上将代码进行重构,大大的提高了编译的速度,因此渲染引擎渲染的页面效果也与 WebKit
有一些出入。正是因为有此渊源,所以一些地方会将 Chromium 和 WebKit 放在一起讨论,而另外一些地方将他们区分开来讲,其实都是有一定道理的。

之后 Google (丹麦)还自己研发了 V8 引擎,用于 JS 的解析和执行,这就是后来 Node.js 的运行环境。Google 将 V8
引擎替换到原本 WebKit 的 JSCore,为 Chrome 带来了更快的 JavaScript 运算速度。

Chromium 虽然是 Fork 自 WebKit,但是其实他们是两个项目,又因为 Google 和 Apple
两家公司本身在很多领域存在竞争关系,双方也并没有想将浏览器方向上的技术完全共享。双方各自发展,最终由于 Apple 推出的 WebKit2 与 Google
的 Chromium 的沙箱设计存在冲突,导致强行合入会增加复杂性,索性 Google 就决定从 WebKit 中衍生出自己的 Blink 引擎。

说到底,都是基于 WebKit 切出来的子分支代码,独立开发了一段时间后,最后发现差异太大,导致代码合回去成本太高,索性各自独立发展。

Blink 引擎后期已经由 Google 和 Opera Software 共同研发,它在 WebKit
代码的基础上研发出更加快速和简约的渲染引擎,并逐步脱离 WebKit 的影响。据说为此 Blink 删除了 880w 行 WebKit
的代码,最终发展出一个独立的浏览器内核。

前面讲到国内双核浏览器中,其中一核使用 IE 的 Trident,将其定义为 “兼容模式”,而另外一核基本上使用的都是
Chromium,被称为“极速模式”。

再说说移动端

移动端的浏览器内核,主要说的是系统内置浏览器内核。

前面提到的四个内核,均在移动端上有对应的产品。而针对平台来说,iOS 平台主要是 WebKit,Android 4.4 之前的浏览器内核是 WebKit,而
Android 4.4 之后切换到 Chromium/Blink。

腾讯推出的 X5 内核,实际上就是基于 WebKit 内核进行的二次开发,并且处于一种假“双内核”模式,在 WebKit 内核加载失败的情况下,会使用原生的
Blink 内核。X5 内核被用在腾讯旗下的产品上,例如:微信、QQ,一定程度上解决了它自身 Android、iOS 两个版本的渲染差异,以及
Android 版本碎片导致内核版本差异出现的渲染差异。

内核发展图谱

Trident 和 Gecko 都还算是比较单纯,就是从一个版本一直开发,增加功能。

而 WebKit 就相对来说,有更多的关系纠缠在里面。

在这个图中,其实并没有体现出内核的升级和变迁,和一些细节的替换,其实每一次迭代都伴随这大量的代码投入、功能改动和优化。此图只是为了大家对 WebKit
的发展有一个了解。

在上图中,是将渲染引擎和 JS 引擎单独区分开,其实也是为了说明发展的历程。在文章的开头也说了,现在谈到浏览器内核,一般都是在泛指渲染引擎内核。所以
Apple 开发的 WebKit 其实就是 KED 小组开发的 (KHTML,KJS) 的分支(WebCore,JSCore)。而 Google 实际上认为
WebKit 中的 JSCore 有一些不足的地方,所以才自己搞了一个 V8 JS 引擎,这就是为什么 Chrome 敢说比 Safari 在某些 JS
效率的测试中,表现更好的原因,基本上也是看到了 JSCore 的不足,在巨人的肩膀上做更好的优化。

浏览器现状

以国内的浏览器现状来说,大部分公司出的浏览器无外乎这几个浏览器内核的组合,所谓的双核或多核浏览器,通常都是 Trident 配合 WebKit 或者
Blink,在其中做二次开发,并且可以在多核之间进行切换,以适应不同的场景。

360 浏览器算是国内比较早投入到浏览器市场的产品,据 360 发表的题为《中国为什么没有自主研发的浏览器内核?》一文中提到,Google 在研发
Chromium 的时候,投入了最少
30亿美元的研发成本以及上百亿的推广成本。而国内,没有同等实力的公司去投入这样的研发和推广资金,去打造自主研发的浏览器内核。

此外,今天 Chromium 和
Gecko(Firefox)本身就是一个开源项目,产品由社区共制,从授权协议上看,它们也鼓励基于已有技术去做技术创新,而不是重复的发明轮子。所以准守开源标准去做一个浏览器并不可耻,强如
Chromium
本身也是基于大量的开源项目累计起来,才有了现在的体量和市场,这就是开源的力量。比起开源项目被美国人控制,更应该担心的是标准本身缺少话语权。毕竟浏览器的每一行代码,都要受
W3C、CABForum 组织,RFC 协议规范。内核引擎里每一行代码,都要受到对应的行业标准所约束。

看了浏览器内核的发展历史,你应该知道为什么 Google 在 WebKit 基础之上研发的 Blink 没人诟病,而国内红芯内核所谓的 “自主研发”
到最后就是一个笑话了吧。

本文由 承香墨影 整理,参考:

《主流浏览器介绍》:http://web.jobbole.com/84826/

《各主流浏览器内核介绍》:http://www.cnblogs.com/vajoy/p/3735553.html

百度百科-X5内核:https://baike.baidu.com/item/X5%E5%86%85%E6%A0%B8/14083554

维基百科。

360:中国为什么没有自主研发的浏览器内核?

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×