C#设计模式(01) - 单例模式(Singleton Pattern)

一、引言

看了李建忠老师的讲的设计模式已经有一段时间了(这段时间大概有一年多了),自己还没有写过自己的、有关设计模式的文章。这次想写一些关于设计模式的文章,用自己的理解和代码来写,算是复习一遍。写作的过程中也会多看看其他大牛的文章,争取让自己的理解正确,否则把大家带跑偏了,就是我的过错了。今天就开始我们第一个设计模式,该模式是:【单例模式】,英文名称:Singleton Pattern,这个模式很简单,一个类型只需要一个实例,他是创建型的设计模式。为什么叫“创建型”设计模式呢,因为他们有分类。当然了分类的方式不一样,分类的结果也就不一样。

从目的来看:
  • 创建型(Creational)模式:负责对象创建
  • 结构型(Structural)模式:处理类与对象间的组合
  • 行为型(Behavioral)模式:类与对象交互中的职责分配
从范围来看:
  • 类模式处理类与子类的静态关系

  • 对象模式处理对象间的动态关系

以上就是分类的方式,我们按大多数的分类,采用“从目的来看”的分类来对设计模式进行分类,我们就开始今天的学习吧。

二、单例模式的介绍

2.1、动机(Motivate)

在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。

如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?

这应该是类设计者的责任,而不是使用者的责任

2.2、意图(Intent)

保证一个类仅有一个实例,并提供一个该实例的全局访问点。–《设计模式GoF》

2.3、结构图(Structure)

2.4、模式的组成

单件实例(Singleton):这个模式里面只有一个类型,就是Singleton类型,并且这个类只有一个实例,可以通过Instance()方法获取该类型的实例。

2.5、单件模式的代码实现

既然是单实例,肯定会涉及到多线程的问题,我们就一步一步的来写代码,我们先看看单线程Singleton模式的实现,代码如下:

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
/// <summary>
/// 单例模式的实现
/// </summary>
public sealed class Singleton
{
// 定义一个静态变量来保存类的实例
private static Singleton uniqueInstance;

// 定义私有构造函数,使外界不能创建该类实例
private Singleton()
{

}

/// <summary>
/// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点
/// </summary>
/// <returns></returns>
public static Singleton GetInstance()
{
// 如果类的实例不存在则创建,否则直接返回
if (uniqueInstance == null)
{
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}

私有的实例构造器是屏蔽外界的调用,上面的单例模式的实现在单线程下确实是完美的,也很好的满足了我们单线程环境的需求。

单线程单例模式的几个要点:

  1. Singleton模式中的实例构造器可以设置为protected以允许子类派生。
  2. Singleton模式一般不要支持ICloneable接口,因为这可能会导致多个对象实例,与Singleton模式的初衷违背。
  3. Singleton模式一般不要支持序列化,因为这也有可能导致多个对象实例,同样与Singleton模式的初衷违背。
  4. Singletom模式只考虑到了对象创建的工作,没有考虑对象销毁的工作。为什么这样做呢,因为Net平台是支持垃圾回收的,所以我们一般没有必要对其进行销毁处理。
  5. 不能应对多线程环境:在多线程环境下,使用Singleton模式仍然有可能得到Singleton类的多个实例对象

如果放在多线程环境下,问题就出来了。因为在两个线程同时运行GetInstance方法时,此时两个线程判断(uniqueInstance ==null)这个条件时都返回真,此时两个线程就都会创建Singleton的实例,这样就违背了我们单例模式初衷了。要想解决这个问题,只要让GetInstance方法在同一时间只运行一个线程运行就好了,让我们看看多线程Singleton模式的实现,代码如下:

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
/// <summary>
/// 单例模式的实现
/// </summary>
public sealed class Singleton
{
// 定义一个静态变量来保存类的实例
private static volatile Singleton uniqueInstance;

// 定义一个标识确保线程同步
private static readonly object locker = new object();

// 定义私有构造函数,使外界不能创建该类实例
private Singleton()
{
}

/// <summary>
/// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点
/// </summary>
/// <returns></returns>
public static Singleton GetInstance()
{
// 当第一个线程运行到这里时,此时会对locker对象 "加锁",
// 当第二个线程运行该方法时,首先检测到locker对象为"加锁"状态,该线程就会挂起等待第一个线程解锁
// lock语句运行完之后(即线程运行完之后)会对该对象"解锁"
lock (locker)
{
// 如果类的实例不存在则创建,否则直接返回
if (uniqueInstance == null)
{
uniqueInstance = new Singleton();
}
}

return uniqueInstance;
}
}

上面这种解决方案确实可以解决多线程的问题,但是上面代码对于每个线程都会对线程辅助对象locker加锁之后再判断实例是否存在,对于这个操作完全没有必要的,因为当第一个线程创建了该类的实例之后,后面的线程此时只需要直接判断(uniqueInstance==null)为假,此时完全没必要对线程辅助对象加锁之后再去判断,所以上面的实现方式增加了额外的开销,损失了性能,为了改进上面实现方式的缺陷,我们只需要在lock语句前面加一句(uniqueInstance==null)的判断就可以避免锁所增加的额外开销,这种实现方式我们就叫它 “双重锁定(Double Check)”,下面具体看看实现代码的:

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
/// <summary>
/// 单例模式的实现
/// </summary>
public sealed class Singleton
{
// 定义一个静态变量来保存类的实例
private static volatile Singleton uniqueInstance;

// 定义一个标识确保线程同步
private static readonly object locker = new object();

// 定义私有构造函数,使外界不能创建该类实例
private Singleton()
{
}

/// <summary>
/// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点
/// </summary>
/// <returns></returns>
public static Singleton GetInstance()
{
// 当第一个线程运行到这里时,此时会对locker对象 "加锁",
// 当第二个线程运行该方法时,首先检测到locker对象为"加锁"状态,该线程就会挂起等待第一个线程解锁
// lock语句运行完之后(即线程运行完之后)会对该对象"解锁"
// 双重锁定只需要一句判断就可以了
if (uniqueInstance == null)
{
lock (locker)
{
// 如果类的实例不存在则创建,否则直接返回
if (uniqueInstance == null)
{
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}

volatile修饰:编译器在编译代码的时候会对代码的顺序进行微调,用volatile修饰保证了严格意义的顺序。一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。

三、C#中实现了单例模式的类

现在我们看看,如何使用C#语言的特性来实现单例的Singleton模式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//Singleton模式的实现
public sealed class Singleton
{
public static readonly Singleton instance=new Singleton();

private Singleton(){}
}

以上是内联初始化(生成的同时进行初始化)的单例模式,它等同于:

```csharp
public sealed class Singleton
{
public static readonly Singleton instance;

//静态构造函数,CLR只执行一次
static Singleton()
{
instance=new Singleton();
}

//私有构造函数,防止外界调用
private Singleton(){}
}

内联初始化其实是把静态的字段放到静态构造器去初始化。只要想访问静态字段,必定已经在之前执行了静态构造器。这样也能够精确地保证使用的时候一定能拿到实例,如果不使用也不会实例化对象,也就是延时加载的功能。他同样能够支持多线程环境,因为只可能有一个线程执行静态构造器,不可能有多个线程去执行静态构造器,感觉就是程序已经自动为我们加锁了。

它的一点弊端就是它不支持参数化的实例化方法。在.NET里静态构造器只能声明一个,而且必须是无参数的,私有的。因此这种方式只适用于无参数的构造器。

需要说明的是:HttpContext.Current就是一个单例,他们是通过Singleton的扩展方式实现的,他们的单例也并不是覆盖所有领域,只是针对某些局部领域中,是单例的,不同的领域中还是会有不同的实例。

四、Singleton模式的扩展

  1. 将一个实例扩展到n个实例,例如对象池的实现。(n不是指无限个实例,而是固定的某个数)
  2. 将new构造器的调用转移到其他类中,例如多个类协同工作环境中,某个局部环境只需要拥有某个类的一个实例。
  3. 理解和扩展Singleton模式的核心是“如何控制用户使用new对一个类的实例构造器的任意调用”。

五、单例模式的实现要点

  1. Singleton模式是限制而不是改进类的创建。
  2. Singleton类中的实例构造器可以设置为Protected以允许子类派生。
  3. Singleton模式一般不要支持Icloneable接口,因为这可能导致多个对象实例,与Singleton模式的初衷违背。
  4. Singleton模式一般不要支持序列化,这也有可能导致多个对象实例,这也与Singleton模式的初衷违背。
  5. Singleton只考虑了对象创建的管理,没有考虑到销毁的管理,就支持垃圾回收的平台和对象的开销来讲,我们一般没必要对其销毁进行特殊的管理。
  6. 理解和扩展Singleton模式的核心是“如何控制用户使用new对一个类的构造器的任意调用”。
  7. 可以很简单的修改一个Singleton,使它有少数几个实例,这样做是允许的而且是有意义的。

单例模式的优点:

  1. 实例控制:Singleton 会阻止其他对象实例化其自己的 Singleton 对象的副本,从而确保所有对象都访问唯一实例
  2. 灵活性:因为类控制了实例化过程,所以类可以更加灵活修改实例化过程

单例模式的缺点:

  1. 开销:虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
  2. 可能的开发混淆:使用 singleton 对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用 new 关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
  3. 对象的生存期:Singleton 不能解决删除单个对象的问题。因为它包含对该静态的私有字段的引用,静态字段是不能被CLR回收内存的,该实例会和应用程序生命周期一样长,一直存在。

单例模式的使用场合:

  1. 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
  2. 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。

六、总结

到这里,单例模式就介绍完了,这个模式很简单,理解起来也不是很难,只要把握住代码的实现技巧,一般问题都不大,但是要找好使用的时机,如果使用错误,一些逻辑错误比较难排查。

本文链接: https://netlover.cn/2018/08/18/csharp-singleton-pattern.html

C#设计模式(07) - 桥接模式(Bridge Pattern)

一、引言

今天我们要讲【结构型】设计模式的第二个模式,该模式是【桥接模式】,也有叫【桥模式】的,英文名称:Bridge Pattern。大家第一次看到这个名称会想到什么呢?我第一次看到这个模式根据名称猜肯定是连接什么东西的。因为桥在我们现实生活中经常是连接着A地和B地,再往后来发展,桥引申为一种纽带,比如:丝绸之路是连接亚洲和欧洲的桥梁。有了桥,我们出行方便了,从一个地方到另一个地方在有桥的情况更方便了(此处不许抬杠,当然是需要桥的情况)。桥是针对桥的使用环境来说的,解决了跨越和衔接的问题。在设计模式中的【桥模式】也有类似的概念,是连接了两个不同维度的东西,而且这两个维度又有强烈的变化,什么叫强烈呢,经常变化,什么是经常呢?哈哈,自己理解吧。

二、桥接模式的详细介绍

2.1、动机(Motivate)

在很多游戏场景中,会有这样的情况:【装备】本身会有的自己固有的逻辑,比如枪支,会有型号的问题,同时现在很多的游戏又在不同的介质平台上运行和使用,这样就使得游戏的【装备】具有了两个变化的维度——一个变化的维度为“平台的变化”,另一个变化的维度为“型号的变化”。如果我们要写代码实现这款游戏,难道我们针对每种平台都实现一套独立的【装备】吗?复用在哪里?如何应对这种“多维度的变化”?如何利用面向对象技术来使得【装备】可以轻松地沿着“平台”和“型号”两个方向变化,而不引入额外的复杂度?

2.2、意图(Intent)

将抽象部分与实现部分分离,使它们都可以独立地变化。 –《设计模式》Gof

桥模式不能只是认为是抽象和实现的分离,它其实并不仅限于此。其实两个都是抽象的部分,更确切的理解,应该是将一个事物中多个维度的变化分离。

2.3、结构图(Structure)

2.4、模式的组成

桥接模式的结构包括Abstraction、RefinedAbstraction、Implementor、ConcreteImplementorA和ConcreteImplementorB五个部分,其中:

  1. 抽象化角色(Abstraction):抽象化给出的定义,并保存一个对实现化对象(Implementor)的引用。
  2. 修正抽象化角色(Refined Abstraction):扩展抽象化角色,改变和修正父类对抽象化的定义。
  3. 实现化角色(Implementor):这个角色给出实现化角色的接口,但不给出具体的实现。必须指出的是,这个接口不一定和抽象化角色的接口定义相同,实际上,这两个接口可以非常不一样。实现化角色应当只给出底层操作,而抽象化角色应当只给出基于底层操作的更高一层的操作。
  4. 具体实现化角色(Concrete Implementor):这个角色给出实现化角色接口的具体实现。

在桥接模式中,两个类Abstraction和Implementor分别定义了抽象与行为类型的接口,通过调用两接口的子类实现抽象与行为的动态组合。

2.5 、桥接模式的具体代码实现

今天我们就以数据库为例来写该模式的实现。每种数据库都有自己的版本,但是每种数据库在不同的平台上实现又是不一样的。比如:微软的SqlServer数据库,该数据库它有2000版本、2005版本、2006版本、2008版本,后面还会有更新的版本。并且这些版本都是运行在Windows操作系统下的,如果要提供Lunix操作系统下的SqlServer怎么办呢?如果又要提供IOS操作系统下的SqlServer数据库该怎么办呢?这个情况就可以使用桥接模式,也就是Brige模式。我们就来看看具体的实现吧!

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
namespace 桥接模式的实现
{
/// <summary>
/// 该抽象类就是抽象接口的定义,该类型就相当于是Abstraction类型
/// </summary>
public abstract class Database
{
//通过组合方式引用平台接口,此处就是桥梁,该类型相当于Implementor类型
protected PlatformImplementor _implementor;

//通过构造器注入,初始化平台实现
protected Database(PlatformImplementor implementor)
{
this._implementor = implementor;
}

//创建数据库--该操作相当于Abstraction类型的Operation方法
public abstract void Create();
}

/// <summary>
/// 该抽象类就是实现接口的定义,该类型就相当于是Implementor类型
/// </summary>
public abstract class PlatformImplementor
{
//该方法就相当于Implementor类型的OperationImpl方法
public abstract void Process();
}

/// <summary>
/// SqlServer2000版本的数据库,相当于RefinedAbstraction类型
/// </summary>
public class SqlServer2000 : Database
{
//构造函数初始化
public SqlServer2000(PlatformImplementor implementor) : base(implementor) { }

public override void Create()
{
this._implementor.Process();
}
}

/// <summary>
/// SqlServer2005版本的数据库,相当于RefinedAbstraction类型
/// </summary>
public class SqlServer2005 : Database
{
//构造函数初始化
public SqlServer2005(PlatformImplementor implementor) : base(implementor) { }

public override void Create()
{
this._implementor.Process();
}
}

/// <summary>
/// SqlServer2000版本的数据库针对Unix操作系统具体的实现,相当于ConcreteImplementorA类型
/// </summary>
public class SqlServer2000UnixImplementor : PlatformImplementor
{
public override void Process()
{
Console.WriteLine("SqlServer2000针对Unix的具体实现");
}
}

/// <summary>
/// SqlServer2005版本的数据库针对Unix操作系统的具体实现,相当于ConcreteImplementorB类型
/// </summary>
public sealed class SqlServer2005UnixImplementor : PlatformImplementor
{
public override void Process()
{
Console.WriteLine("SqlServer2005针对Unix的具体实现");
}
}

public class Program
{
static void Main()
{
PlatformImplementor SqlServer2000UnixImp = new SqlServer2000UnixImplementor();
//还可以针对不同平台进行扩展,也就是子类化,这个是独立变化的

Database SqlServer2000Unix = new SqlServer2000(SqlServer2000UnixImp);
//数据库版本也可以进行扩展和升级,也进行独立的变化。

//以上就是两个维度的变化。

//就可以针对Unix执行操作了
SqlServer2000Unix.Create();
}
}
}

代码都很简单,也有详细的备注,就不多说了。

三、桥接模式的实现要点:

  1. Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。
  2. 所谓抽象和实现沿着各自维度的变化,即“子类化”它们,得到各个子类之后,便可以任意组合它们,从而获得不同平台上的不同型号。
  3. Bridge模式有时候类似于多继承方案,但是多继承方案往往违背了类的单一职责原则(即一个类只有一个变化的原因),复用性比较差。Bridge模式是比多继承方案更好的解决方法。
  4. Bridge模式的应用一般在“两个非常强的变化维度”,有时候即使有两个变化的维度,但是某个方向的变化维度并不剧烈——换言之两个变化不会导致纵横交错的结果,并不一定要使用Bridge模式。

桥接模式的优点:

  1. 把抽象接口与其实现解耦。
  2. 抽象和实现可以独立扩展,不会影响到对方。
  3. 实现细节对客户透明,对用于隐藏了具体实现细节。

桥接模式的缺点:

  1. 增加了系统的复杂度

桥接模式的使用场景:

  1. 如果一个系统需要在构件的抽象化角色和具体化角色之间添加更多的灵活性,避免在两个层次之间建立静态的联系。
  2. 设计要求实现化角色的任何改变不应当影响客户端,或者实现化角色的改变对客户端是完全透明的。
  3. 需要跨越多个平台的图形和窗口系统上。
  4. 一个类存在两个独立变化的维度,且两个维度都需要进行扩展。

四、.NET 中桥接模式的实现

学习中。。。,如果谁有好的代码分享,也可以贴出来。

五、总结

今天的文章就写到这里了,现在小结一下。桥接模式它是连接客户端代码和具体实现代码的一座桥梁,同时它也隔离了实现代码的改变对客户代码的影响。在【意图】中所说的抽象和实现,这两个部分其实都是高度抽象的,前面“抽象”是指定义的针对客户端的接口,客户端其实使用的是Abstract类型或者是RefinedAbstract类型,这两个类型只是接口,具体的实现委托给了Implementor类型了,Abstract类型子类化的扩展也演变成Implementor子类化的变化。我个人的理解,Abstract类型和其子类型在客户端代码和真正实现的代码之间起到了桥梁的作用,隔离了Implementor实现代码的变化,让客户端更稳定,所以【意图】才说是讲抽象部分和它的实现部分隔离。大家好好理解一下吧,刚开始有点绕。

本文链接: https://netlover.cn/2018/08/18/csharp-bridge-pattern.html

中国未来真正的30个商业模式

1、中国未来产业分为三种:

一维世界正在推倒重建,二维世界被划分完毕(BAT掌控),三维世界正在形成,高维挑战低维总有优势。所以网店可以冲散实体店,而微信的对手一定在智能领域诞生。

2、中国当下的企业分为三个等级:

今后企业的出路唯有升级成平台,平台化的本质就是给创造者提供创造价值的机会。

3、中国互联网进化论:

PC互联网解决了信息对称,移动互联网解决了效率对接,未来的物联网需要解决万物互联:数据自由共享、价值按需分配。我们认为互联网+的本质就是搭建一个底层建筑,使上面的每一个人都可以迅速找到目标。无论是找客户、找恋人还是找伙伴。

4、中国电子商务进化论:

PC互联网解决了信息对称,移动互联网解决了效率对接,未来的物联网需要解决万物互联:数据自由共享、价值按需分配。互联网+的本质就是搭建一个底层建筑,使上面的每一个人都可以迅速找到目标。无论是找客户、找恋人还是找伙伴。

5、中国的电子商务正在改变城市格局:

“北上广深”正在变成“北上深杭”。传统贸易的衰落将广州拉下马,跨境电商的兴起将杭州扶上位,未来中国的城市格局应该是“北京的权力调控+上海的金融运作+深圳的智能科技+杭州的电子商务”。

6、中国经济结构进化论:

从“按计划生产、按计划消费”,到“按市场生产,按利润分配”,再到“按消费生产,按价值分配”,笔者认为未来中国一定会“按需求生产,按需求分配”,满足人的一切需求,这就是共产主义。

7、中国产业链的流向正在逆袭:

传统经销商这个群体将消失,而能够根据消费者想法而转化成产品的设计师将大量出现。

8、中国广告业态的进化论:

传统广告总是依靠媒介的力量去影响人,比如央视的招投标。后来的互联网广告开始依靠技术实现精准投放,比如按区域、按收入、按时段投放。再后来社交媒体的崛起使好的广告能自发传播,而未来最好的广告一定产品本身,最好的产品也一定具备广告效应。

9、中国商业角逐的核心先后经历了:

房地产经营的就是地段,传统互联网经营的就是流量,自媒体经营的是粉丝。而未来是“影响力”和“号召力”之争,“核心粉丝”的瞬间联动是未来商业的“引力波”。

10、中国媒体的进化论:

媒体正在由集中走向发散,由统一走向制衡。自媒体的兴起将产生两大结果,第一激起了很多人的创作热情,文字作为人的一种基本属性终于被找回,感性的一面被激发,可以滋润这个越来越机械化的世界。第二,中国的话语权开始裂变,普通民众迫切要求参与公共事务的决策权,比如春晚到底该邀请谁。而未来人人都是一个自媒体,信息流的产生让媒体消亡。

11、中国将越来越细分:

行业将越来越垂直、协作越来越完善。因此传统的木桶原理不再成立,以前我们总在弥补自己短板,因为你的短板限制了你的综合水平,是今后我们将不断延展自己长处,因为你的长处决定了你的水平。我们认为你只需要将自己擅长的一方面发挥到极致,就会有其它人跟你协作,这叫长板原理。

12、新的社会架构讲究的是“规则”而不是“关系”:

中国社会的传统关系网被不断撕裂,以价值分配为关系、新的链接正在形成,每个人都是一个节点,进行价值传输。新的社会架构讲究的是“规则”而不是“关系”。而你所处的地位和层级,是由你所带来的价值决定的。

13、中国人正在由外求变成内求:

外求即就求关系、求渠道、求资源、求人脉,求机会,内求即坦诚面对自己内心最真实的一面,激发起兴趣、热情、希望、理想,当你做好你自己,外界的东西就会被你吸引过来,这就是所谓的求人不如求己。

14、信用无价:

对于未来每个人来说,有一个东西会变的很重要,那就是信用。行为——信用——能力——人格——财富。在大数据的帮助下,你的行为推导出了你的信用值,然后以信用度是支点,能力为杠杆,人格为动力,联合撬动的力量范围,就是你所掌控世界的大小。

15、传统社会的总财富是这样创造出来的:

人们依托固定公司,在固定时间、固定地点重复固定的劳动,属于被动式劳动。未来社会的总财富是这样创造出来的:人们依靠自身特长,点对点的对接和完成每一个需求,充分融入到社会每一个环节,属于主动式创造。因此整个社会财富将实现裂变式增长。

16、中国99%的公司和集体都将消失,各种垂直的平台将诞生:

大量自由职业兴起。中国社会的组织结构从公司+员工,变成平台+个人。每个人都将冲破传统枷锁的束缚,获得重生的机会,关键就看你是否激发了自身潜在的能量。这才是一场真正解放运动。

17、未来每一个人都是一个独立的经济体:

即可以独立完成某项任务,也可以依靠协作和组织去执行系统性工程,所以社会既不缺乏细枝末节的耕耘者,也不缺少具备执行浩瀚工程的组织和团队。

18、未来如何拥有自己的产品?

当你有一个想法时,你可以先表达出来,然后在平台上进行展示(这样的平台会越来越多),然后吸引喜欢的人去下单,拿到订单后可以找工厂生产(不用担心量太少,今后的生产一定会精细化和定制化),然后再送到消费者手里。

19、中国今后将无工可打:

打工的本质是定价出卖自己的劳动力,并不承担结果。随着雇佣时代的结束,你必须主动思考和去解决问题,并竭力发挥自己的特长,为社会和他人创造价值,否则你就没有存在的价值。笔者认为中国人的工作方式正在从“谋生”到“创造”升级。

20、中国今后将无生意可做:

传统社会只所有生意可做,是因为信息的不对称使社会的“供给”和“需求”始终是错位的,这就需要商人的商业行为去对接他们,并从中谋利。而互联网搭建起的商业基础会越来越完善,今后两者可以随时精准连接。所有的中间环节都没有了,赚差价的逻辑也就不存在了。“经商”一词需要再定义,温州人的那一套思维彻底落伍了。

21、中国的社会结构将越来越精密细致:

以前每一个“需求”和“供给”都是由企业完成,今后都是由个人完成,可以做一个这样的比喻:如果经济是一场血液循环,那么今后它的毛细血管会更加丰富,输送和供氧能量会更加强大。

22、中国人找回信仰的逻辑是这样的:

具体来说就是:中国正在建立一套完善而合理的社会秩序,让每个人都能各尽其才,各取所需。在此基础上形成了新秩序,而秩序的运转将产生新的精神,比如契约精神。精神的碰撞激发起内心的向往,一旦我们心有所属,这就是信仰。

23、法治的最高境界是人治,人治的最高境界是无治:

什么才是无治?即依靠利益关联进行互相制衡,在互联网时代,每个人都与外界有无数个连接点,依靠这些连接点,每个人的处境都将直接绑定自己的行为,贪婪、懒惰、无知作为人性的负面,都将被自然克制。

24、中国商业未来十年内的主题都将离不开,“跨界互联”:

以互联网+为基础,不同行业之间互相渗透、兼并、联合,从而构成了商业新的上层建筑。不同业态将互相制衡,最终达到一种平衡的状态,从而形成新的商业生态系统。

25、中国未来社会的完善,离不开一批有“匠心”的人:

也就是那些脚踏实地的人。比如工匠、程序员、设计师、编剧、作家、艺术家等等,因为互联网已经把社会的框架搭建完成,剩下的就是灵魂填充!所以即便是普通的工作岗位,他们的社会地位也将获得提升,将获得尊重。

26、中国精神文明的红利期正在到来:

传统的物质文明进展步伐已经开始放慢,因为工业化已经将社会各项硬性设施布局完善,物质的野蛮增长期已经过去,而互联网又已经把所有的链接搭建完毕,柔性内容开始凶猛增长,新文化行业是一个增长点。

27、中国今后的私有财产会更加神圣:

每个人的行为都会围绕利益展开,而且目标简单而明确,财富分配不再需要依靠政府主导,而是一种天然的价值回馈。汇聚大家之私,即成社会之公,此乃民富国强。

28、中国未来只有三种角色,自下而上依次是:

价值提供者是依靠个体劳动创造直接财富,比如:司机、医生、律师等等,影响力大了可以靠名声创富,比如明星、作家、大导演、名主持等等。价值整合者是依靠配置社会资源间接创造财富,主要指的是企业家和各种组织的领导者,他们促进社会资源向最需要的地方流动。价值放大者是依靠平台或财富的力量去撬动企业和项目的成长,他们往往是大平台的拥有者或财团掌控者,比如马云、马化腾、李彦宏、巴菲特、孙正义等等,他们促使社会财富呈爆发式增长。三个阶层不是固化的,而是可以流动的。

29、中国人的财富形式先后经历了:

四个阶段,未来的财富形式一定是估值或市值,趋于虚拟和抽象,只是一个数字。即:你拥有多少财富,并不代表你就可以随便花这些钱,而是代表你有支配这些钱的权力,财富多少意味着调动资源的大小。究其本质,是整个社会越来越共享化、公开化、公共化。

30、中国未来将建立一个伟大的“超级互联网公司”:

将BAT收入囊中,通过高效协作和行业细分,来优化配置社会的各种资源,包括各种大大小小的、边边角角的零部件,不浪费一个螺丝、不放弃一个灵魂,将整个社会带入价值创造和吸收的大循环,这就接近我们说的共产主义。

本文链接: https://netlover.cn/2018/08/17/30shangyemoshi.html

区块链就是未来,也是一种回到互联网本来意义的方式

区块链就是未来,也是一种回到互联网本来意义的方式。

这组词序并没有任何意义,真正让它们有价值的地方在于,这个词序是由一个被称为 MetaMask 的软件专门为我一个人生产的。

用密码学(cryptography)术语表达,就是助记词(seed phrase)。这组词汇读起来感觉毫无连贯性而言,却可以转变成一把钥匙,打开数字银行账户,或者进行在线认证。而且只需几步就完成了。

电脑在屏幕上告诉我要保证我的助记词的安全:写下来或者放在电脑上一个安全的地方。我匆匆的将 12 个单词写在便签纸上,然后点击了一个按钮,就变成了 64 个看起来毫无规律可言的字符:

1b0be2162cedb2744d016943bb14e71de6af95a63af3790d6b41b1e719dc5c66

这在密码学中被称为「密匙」:这是一种身份验证的方式,但与现实生活中拿钥匙开锁的方式有很大的不同。我的助记词每次都可以产生准确的字母顺序,但如何对钥匙的初始词组进行反工程尚不可知,这就是为什么将种子词放在一个安全的地方是一件很重要的事情。

密匙的字母会进行两次的转变,创造一串新的字符:

0x6c2ecd6388c550e8d99ada34a1cd55bedd052ad9

这一串字符就是我的以太坊(Ethereum)区块链的地址。

在过去一年间,加密货币比特币的价值增长了超过 1000%,以太坊与比特币属于同一类货币。

以太坊拥有自己的货币,最著名的就是以太币,但这个平台不仅拥有钱,它的范围更加广泛。你可以把的以太坊的地址看成类似银行账户、邮箱地址或者一个社保号。

目前,它在的电脑上就是一串毫无意义的字符,但只要我想进行任何的交易,比如参与一个众筹活动或者进行一个在线的公投,这个地址就会传给出一个临时的计算机网络,对交易进行验证。验证的结果会再一次传到更大范围的网络,会有更多的机器进入一种竞争的状态,进行复杂的数学运算,胜出者会单独对这笔交易进行记录,在以太坊的历史上,每笔交易都进行了规范的记录。

因为这些交易都是通过一种有序的数据「块」进行登记,所以这个记录就被成为区块链。

完成整个交易只需要几分钟的时间。从我的角度来看,这种体验与平常的网络生活并没有多大的差别。

但从技术层面来看,确实相当的神奇,有一些东西在 10 年前几乎是难以想象的。在不依赖传统机构建立信任的情况下,我成功的完成了一笔安全交易。没有中间商;没有社交媒体网络收集我本次交易的数据以便更好的进行广告的精准推送;没有信用机构跟踪这次活动以便进行经济可信状况的建构。

是这个平台让所有的这一切成为了可能吗?

不过,没有人拥有这个平台。没有风投资本家投资以太坊,因为根本没有这个公司。

作为一种组织形式,以太坊比任何一家私营公司都更加的民主。没有专制领导的咆哮。只要加入这个社区,做一些工作,你就是在帮助驾驶以太坊这艘航船。

同比特币以及其他大多区块链平台一样,以太坊更像是一个蜂巢,而非一个正式的实体。它的界线很模糊,是一种扁平化的等级制度。

还有另外一面:在这个蜂巢中,有一些人通过他们的劳动,所积累的账面净值已达到数十亿美元,2017 年一月一日,以太币的价值只有 8 美元,而一年以后,这个价值就达到了 843 美元。

对于这种转变,你可能会是一种蔑视的态度,觉得不值一提。毕竟,比特币和以太币价值失控性的增长绝对是非理性蔓延的典型案例。这种神秘的技术突破目前看起来与登录网站进行信用卡还款并没有什么不同之处,我们为什么要关心这样一种技术呢?

但这种蔑视是一种目光短浅的做法。

从互联网发展的历史中,我们学习到了一件事情,这种软件架构看似神秘,可这种技术一旦发展成更加宽泛的计算,则会释放出深远的力量,影响全球。

如果邮件标准在 20 世纪 70 年代予以采用,将公匙和密匙作为一种默认设置,从索尼到 John Podesta(前美国国务卿希拉里竞选总干事)的每个人都将不会再受到大规模邮件被黑的困扰,数百万的普通用户也不用再身份盗用的问题。

如果,万维网的发明人 Tim Berners-Lee 在最初的标准中采纳定位社交身份协议,今天我们可能就没有 Facebook 了。

以太坊这类区块链背后坚定的信仰者认为,分布式的信任网络是软件架构的一个进步,历史一定会证明它的伟大意义。这种期望进一步推涨了加密货币的价值。

但是,比特币泡沫很可能最终会成为区块链真正意义上的一个狂欢。很多追捧者认为,对这种新技术的期许并不在于到取代我们现有的货币,而是取代我们当前对互联网的观念,同时将网络世界拉回到一个去中心化的平等体制。

如果你相信这些追捧者的言论,区块链就是未来。但这也是一种回到互联网本来意义的方式。

在无限的资源和全球连接这种乌托邦梦想的激励下,在过去的这些年,互联网似乎变成了一个替罪羊:成为了我们所面临的一切社会问题的根源。

俄罗斯黑客在 Facebook 上利用虚假新闻瓦解了民主体制;推特和 Reddit 上仇恨言论肆虐;极客精英们的巨大财富使得收入不平等状况加剧。

对于我们很多在互联网初期就开始使用网络的人来说,最近的几年让我们有一种堕落之感。

互联网本来承诺成为由大量小报、博客、自建的百科等新媒体;二十世纪主导大众文化的信息巨头本应该让位给更加去中心化的体制,一种合作性的网络而不再是一个具有等级制度的传播渠道,反映出互联网本身的点对点架构。

然而今天的网络不再是乌托邦,充斥着金融泡沫、垃圾信息和无数的其它问题。但是,人们总猜想堕落的背后隐藏着进步

去年,这样的侥幸最终坍塌。在互联网,怀疑并不是什么新的事物。不同之处在于,批评的声音更多的是来自以前对网络极度推崇的人。

「我们想要对互联网进行修补,」Walter Isaacson 说。他是乔布斯传记的作者,这句话是他在川普当选几周后写的一篇文章中所说。

「经过 40 年的发展,互联网开始腐化,不仅仅是互联网还有我们。」谷歌前战略官 James Williams 告诉《卫报》:「注意力经济的活力正结构性的危害人类的意志。」

纽约顶级的风投公司 Union Square Ventures 的管理合伙人 Brad Burnham 在博客上抱怨数字时代的准垄断所导致的额外危害:

「在 Facebook 无差异化的内容洪流中,出版社发现自己正变成商品内容供应商。谷歌搜索算法的一个微小变化就能导致一家网站财富的流失。当亚马逊决定在中国直接采购商品并重新规划自己商品的需求时,制造商只能眼睁睁的看着销售下滑。」(Burnham 的公司投资了我在 2006 年成立的公司;等到 2011 年公司被出售时,我们之间并没有财务关系。)

甚至是网络的发明人 Berners-Lee 也写了一篇博客表明自己的忧虑,以广告为基础的社交媒体和搜索引擎创造了一种环境,「让人震惊或者专门为吸引偏见所发布的虚假信息,像野火一样在网络上肆意传播。」

对于大多数评论家来说,解决这些巨大的结构性问题的办法就是,要么提出关于这些工具危险性的新忠告,比如掉我们的智能手机,让孩子们远离社交媒体,要么只能借助于强有力的监管和反垄断手腕:使科技巨头与其他对公共利益至关重要的行业(如早先的铁路或电话网络)一样受到审查。

这两个想法都值得赞扬:我们可能应该制定一套新的习惯来管理我们如何与社交媒体进行互动。看起来像 Google 和 Facebook 这样强大的公司就应该像电视网络一样面临相同的监管审查,这完全是明智的做法。

但这些干预措施不太可能解决网络世界面临的核心问题。

毕竟,在上世纪 90 年代不仅仅是司法部的反垄断部门质疑微软的垄断权力,同时也出现了新的软件和硬件,比如网络、开源软件和苹果产品,这些都破坏了微软的主导地位。

以太坊(Ethereum)这样的平台背后的区块链布道者认为,软件、密码和分布式系统方面的一系列先进技术,有能力解决当今的数字问题。比如,在线广告的腐蚀性激励机制;Facebook、谷歌和亚马逊的准垄断;俄罗斯的误报运动。

如果他们成功了,他们的发明可能会比任何反垄断规则更有效地挑战科技巨头的霸权。他们甚至声称,为资本主义的赢家通吃模式提供了一个替代方案,而不会把财富不平等推到了强盗贵族时代以来没有见过的高度。

这一补救措施在任何普通科技消费者了解的产品中都尚不可见。到目前为止,唯一一个进入主流认可的区块链项目就是比特币,但它正处于一个投机泡沫中。

这场泡沫使得连上世纪 90 年代的互联网 IPO 热潮看起来都只能算是邻居的车库拍卖。这里存在着困扰所有试图理解区块链人的一个认知冲突:这场很可能发生的革命的潜在力量正在被它所吸引的人群积极地削弱,这群人是名副其实的骗子、假先知和雇佣兵。

这已经不是第一次了,那些追求开放和去中心化网络的技术专家们发现自己被一群想一夜暴富的机会主义者所包围。

问题在于,泡沫破灭后,区块链的真正承诺能否持久。

对一些现代科技史的学生来说,互联网的衰落是不可避免的历史剧本。

就像 Tim Wu 在他 2010 年出版的书中提出的「总开关」那样,所有主要的 20 世纪信息技术都有一个相似的发展模式。从一开始爱好者和出于好奇心和社团的玩具,到最后终结于跨国公司对股东价值最大化的持续关注。Wu 称这种模式为周期,至少在表面上,互联网以令人信服的准确度符合这样的周期。

互联网最初是由政府资助的学术研究项目和业余爱好组成的大杂烩。但万维网首次进入大众想象中的 20 年后,它在谷歌、Facebook 和亚马逊——也间接地从苹果公司——这些在资本主义史上最强大、最有价值的公司中诞生了。

区块链的倡导者并不接受这一周期的必然性。

他们认为,事实上,互联网的根本比以前的信息技术更彻底地开放和分散,而且如果我们成功地坚持这种根本,它本可以保持这种状态。网络世界就不会被少数信息时代的巨头主宰;我们的新闻平台也不会这么容易受到操纵和欺诈;身份盗窃将远不这么常见;广告收入也将分布在更广泛的媒体领域。

要理解其中的原因,我们可以将互联网看作是相互堆叠在一起的两种完全不同的系统,就像考古挖掘中的地质层一样。

其中一层是由 20 世纪 70 年代和 80 年代开发的软件协议组成的,并在 90 年代达到了临界数量,至少在受众方面是如此。(协议是通用语言的软件版本,是多台计算机同意彼此通信的一种方式。有一些协议控制着互联网原始数据的流通,有一些协议控制发送电子邮件消息,以及有一些协议定义网页地址。)

然后在他们之上,是另一层基于网络的服务——Facebook、谷歌、亚马逊、Twitter——在接下来的十年里,基本上都是这些服务掌控互联网世界。

第一层——我们称为 InternetOne——是建立在开放协议之上的,而开放协议则依次由学术研究人员和不归属与任何人的国际标准组织定义和维护。

事实上,最初的开放性仍然存在于我们周围,以一种我们可能不太能意识到的方式。电子邮件仍然是基于开放协议 POP、SMTP 和 IMAP;网站仍然使用开放协议 HTTP 服务;比特仍然通过互联网的原始开放协议 TCP/IP 传输。

你完全不需要了解这些软件协议是如何在技术上运转的,就可以直接享受它们带来的好处。他们共有的关键特征就是任何人都可以免费使用。

如果你想建立一个网页,你不需要向拥有 HTTP 协议的公司支付授权费;如果你想用 SMTP 发送电子邮件,你不必向广告商出售你的部分身份。与维基百科一样,互联网的开放协议是人类历史上最令人印象深刻的基于人民群众的产品。

要理解这些协议的好处是多么巨大而又难以察觉,那就想象一下其中一个关键标准没有被开发出来会是怎么样。

例如,我们用来定义地理位置的开放标准 GPS。

全球定位系统(GPS)最初由美国军方开发,在里根政府时期首次被用于民用。在大约 10 年的时间里,它主要被航空工业使用,直到个人消费者开始在汽车导航系统中使用它。

现在我们有了智能手机,可以从我们头顶的 GPS 卫星接收到信号,我们利用这一非凡的力量做了各种事情,从寻找附近的餐馆、玩 Pokemon Go,到协调救灾力量,无所不包。

但是,如果当年军方把全球定位系统排除在公共领域之外又会怎样呢?

那么,估计在 20 世纪 90 年代的某个时候,表明消费者对建立精确的地理坐标感兴趣的一个市场信号可能会流向硅谷和其他科技中心的创新者,因为这样就可以把这些位置投影到数字地图上了。

竞争对手之间肯定会有几年激烈的竞争,他们都会把自己的专用卫星送入轨道,推进自己的独特协议。但考虑到从单一常见的方法验证位置的效率,最终市场会选定一个占主导地位的模型。

我们就叫那个假想的公司 GeoBook 吧。

最初,对于试图在硬件和软件中建立定位意识的消费者和其他公司来说,全面拥抱 GeoBook 将是一种飞跃。但慢慢地,一个更黑暗的故事将会出现:

一个能够追踪全球数十亿人动向的单独一家私人公司,会建成一个基于我们移动位置的广告巨头。任何试图构建地理感知应用程序的初创企业在强大的 GeoBook 面前都很脆弱。适当的愤怒论战将会被写来谴责天空中这个老大哥的公众威胁。

但这一切都没有发生,原因很简单。

地理定位,就好像网页和电子邮件地址和域名的位置一样,是一个我们用开放协议解决了的问题。正因为这是一个我们没遇到的问题,我们很少考虑到 GPS 是有多么出色地完成了工作,以及在它的基础上开发了多少不同的应用。

开放的,分散的网络在 InternetOne 层上非常活跃而且运转良好。但是自从我们在 90 年代中期在万维网上安定下来之后,我们就很少采用新的开放标准协议了。

在 1995 年之后,技术专家所解决的最大的问题——许多是围绕着身份、社区和支付机制——都留给了私营部门去解决。这在本世纪初带来了一个强大的互联网服务层,我们可以称之为 InternetTwo。

尽管互联网开放协议的发明者们极具聪明才智,但他们没有把一些关键元素放进开放协议。这些元素后来被证明对网络文化的未来至关重要。也许最重要的是,他们没有建立一个安全的开放标准来在网络上确定人类的身份。

信息的单位可以被定义——网页、链接、消息——但是人们没有自己的协议:没有办法定义和分享你的真实姓名、你的位置、你的兴趣,或者(也许最重要的是)你和其他网民的关系。

事实证明这是一个主要的疏忽,因为身份正是一个能从公认的解决方案中获益的问题。

它是以太坊的创始人 Vitalik Buterin 所描述的「基础层」基础设施:诸如语言、道路和邮政服务、商业和竞争发生的平台实际上都是通过在公共领域的底层来支持实现的。

在线下,我们没有一个开放的市场来购买实体护照或社保号码;我们有一些大多由国家力量支持的著名权威机构,用这些权威来想别人证明我们就是我们所声称的那个人。

但在网络上,私人部门突然介入,填补了这一真空。因为身份具有普遍问题的特征,所以市场受到了很强的激励要以一个共同的标准来界定你自己和你认识的人。

经济学家们称之为「报酬递增」或「网络效应」的自我强化反馈循环开始生效,经过一段时间在涉及如 Myspace 和 Friendster 的社交媒体初创企业的实验后,市场决定了什么才是本质上明确你自己和你所认识的人的专有标准。

这个标准就是 Facebook。

Facebook 的用户超过 20 亿,它的规模远远超过了上世纪 90 年代末互联网泡沫顶峰时期的整个互联网。成立仅 14 年,用户的增长就使它成为世界上第六大最有价值的公司。

Facebook 是可以划分 InternetOne 经济和 InternetTwo 经济的鸿沟的终极体现。没有一家私营公司拥有定义电子邮件、GPS 或开放网络的协议,但是有一个公司拥有能够定义今天的 20 亿人社会身份的数据——而有一个人,名叫 Mark Zuckerberg,拥有该公司的绝大多数表决权。

如果你认为集中式网络的兴起是一个不可避免的循环,而早期网络开放协议的理想主义是一种青少轻狂的错误意识,那么我们就没什么理由再去烦恼我们是怎么放弃了 InternetOne 时期的愿景。究竟是我们现在生活在一个堕落的国家,没有办法回到伊甸园,还是说伊甸园本身就是一种必将被集权破坏的幻想。

无论在哪种情况下,试图恢复 InternetOne 的架构都没有意义;我们唯一的希望是通过监管和反垄断行动,利用国家的力量来控制这些企业巨头。

这是古老的 Audre Lorde 格言的变体:「主人的工具永远不会拆除主人的房子。」你不能通过提供更多的技术解决方案来解决技术为我们创造的问题。你需要在软件和服务器领域之外找到足以匹敌的外来力量才能瓦解垄断集团。

但是在这个类比中,主人的房子是一个双层小楼。上层建筑确实是无法用建造它的工具来拆除的,但是那下面的开放协议仍然有潜力去建造更好的东西。

对开放协议复兴最有说服力的倡导者之一 Juan Benet 是一个出生在墨西哥的程序员。

他现在住在位于加州帕洛阿尔托市郊的一个小巷的三居室出租屋里,住户就是他和他的女友、另一个程序员,加上一个不停变化的客人,一些客人属于 Benet 的组织:协议实验室(Protocol Labs)。

在九月的一个温暖的日子里,Benet 穿着一件黑色的协议实验室卫衣在门口迎接我。这个空间的内部让人想起了 HBO 的「硅谷」里的孵化器/联谊会会堂。它的客厅被一排黑色的电脑显示器所霸占。

在门厅里,「欢迎来到瑞文戴尔(Rivendell)」的字样在白板上潦草地写着,这是对「指环王」里艾雯城(Elven city)的一种致敬。「我们把这房子叫做瑞文戴尔,」贝内特不好意思地说,「但这不是一个很好的瑞文戴尔。这里没有足够的书、瀑布或是精灵。」

Benet 现年 29 岁,他认为自己是上世纪 90 年代末和 21 世纪初曾短暂繁荣过的第一场 P2P 革命的孩子,那场革命在很大程度上是由像 BitTorrent 这样通常是非法地传播媒体文件的网络推动的。

那场最初的繁荣在很多方面都是互联网分散的开放协议根源的逻辑延伸。互联网已经表明,你可以在基于群众的网络中可靠地发布文档。像 BitTorrent 或 Skype 这样的服务将这种逻辑带到下一个层次,允许普通用户在互联网上添加新功能:创建一个分布式的(主要是盗版的)媒体库,就像用 BitTorrent 那样。或者帮助人们通过互联网拨打电话,就像使用 Skype 一样。

Benet 坐在瑞文戴尔里的客厅/办公室里告诉我,他认为随着 Skype 和 BitTorrent 的兴起,21 世纪初就像是「P2P 的『盛夏』」——它的黄金时期。

「但后来,P2P 就撞上了一堵墙,因为人们开始喜欢集中的架构。」他说,「部分由于 p2p 业务模式是由盗版驱动的。」

斯坦福大学计算机科学专业的毕业生 Benet 以一种让人想起 Elon Musk 的方式说话:当他说话的时候,他的眼睛扫视着你头顶上的一片空气,就像他在看一个看不见的提词器来寻找措辞一样。

他对协议实验室正在发展的技术充满热情,但也热衷于将其置于更广阔的环境中。对于 Benet 来说,从分布式系统到更集中的方法的转变,几乎没有人能预料到。

「游戏规则、管理所有这些技术的规则非常重要。」他说,「我们现在所构建的结构将会描绘出未来 5 年或 10 年后截然不同的图景。」

他接着说:「当时我很清楚,P2P 是一件特别的事情。但当时我并不清楚的它的风险有多高。我当时没有意识到我必须接过接力棒,现在轮到我来保护它了。

协议实验室正是 Benet 试图接下这根接力棒的尝试,它的第一个项目是对互联网文件系统的彻底改革,这个系统包括我们用来定位网络上网页位置的基本方案。

Benet 把他的系统称为 IPFS,这是「星际文件系统(InterPlanetary File System)」的缩写。

当前的协议 HTTP 将网页从一个单一的位置下载下来,并且没有内置的机制来归档在线页面。而 IPFS 允许用户从多个位置同时下载一个页面,并包括程序员所称的「历史版本控制」,这样过去的迭代就不会从历史记录中消失。

为了支持该协议,Benet 还创建了一个名为 Filecoin 的系统,该系统将允许用户有效地出租未使用的硬盘空间。(你可以把它想象成一种数据的 Airbnb)

「现在,地球上有无数待机或闲置的硬盘驱动器,以至于它们的所有者只是在赔钱,」Benet 说,「因此,你可以将大量的供应带上线,这将降低存储成本。」

但正如它的名字所暗示的,协议实验室的雄心远不止这些项目,Benet 的更大使命是在未来几年支持许多新的开源协议。

为什么互联网会从开放走向封闭?

一部分解释在于「不作为」这一原罪:当新一代的程序员开始着手解决 InternetOne 未解决的问题时,只要程序员保持系统闭源,就会有几乎无限的资金来源进行投资。

InternetOne 开放协议成功的秘诀在于,它们是在大多数人都不关心网络网络的时代发展起来的,因此他们能够悄悄地达到临界数量,而不必对付富有的企业集团和风险资本家。

不过,到 21 世纪中期,像 Facebook 这样有前途的新公司,即使在成为家喻户晓的品牌之前,也能吸引数百万美元的融资。而且,私人部门的资金确保了公司的关键软件保持关闭状态,以便为股东获取尽可能多的价值。

然而,正如风险投资家 Chris Dixon 指出的那样,还有另外一个在本质上比金融更具有技术性的因素。

「假设你想建立一个开放的 Twitter,」Dixon 坐在 Andreessen Horowitz 纽约办公室的会议室里解释说,他是那里的一位普通合伙人。「我在 Twitter 上叫做 @cdixon,那你怎么存储这个信息呢?你需要一个数据库。」

像 Facebook 或 Twitter 这样的封闭架构将用户的所有信息——他们的操作、他们的点赞和照片、他们在网络上与其他个人的关系图谱——放入一个由公司维护的私有数据库中。每当你查看你的 Facebook 新闻提要时,你都可以访问这个数据库非常小的一部分,只看到与你相关的信息。

运转 Facebook 的数据库是一个难以想象的复杂操作,依赖于遍布全球的成千上万的服务器,由地球上最杰出的工程师们监管。从 Facebook 的角度来看,他们为人类提供了一项宝贵的服务:为地球上几乎所有人创建一个共同的社交图谱。

他们不得不出售广告来支付提供这项服务的成本——以及他们的网络的规模赋予他们的影响世界各地二十亿人的思想的惊人力量——是为了这共享社交图谱要付出的一项虽然不好,但也不可避免的代价。

这种权衡在 21 世纪中期确实是有道理的;创建一个能够追踪数以亿计的人之间的相互作用的数据库——更不用说 20 亿了——是只有一个组织才能解决的问题。

但是正如 Benet 和他那些区块链传道伙伴们急于证明的那样,这样的合理性可能不再存在了。

那么,当大型科技公司已经吸引了数十亿用户,并坐拥数千亿美元现金的时候,你如何才能在这个时代让新的基础协议被有意义地采纳呢?

如果你恰好相信互联网在其当前的化身中对社会造成了重大的、日益严重的危害,那么这个看似深奥的问题——让人们采用新的开源技术标准的困难——最终会产生重要后果。

如果我们想不出一种方法来引入新的、能与现有架构匹敌的基础架构,那么我们就会被永远困在现在的互联网。

我们所能期望的最好的结果就是政府干预,以减少 Facebook 或谷歌的影响力,或者是某种来自消费者的反抗,鼓励市场转向更少霸权的在线服务,这就相当于是为了当地农民的市场销路而放弃大型农业设施的数字版。

这两种方法都不会颠覆 InternetTwo 的基本推动力。

2008 年,在 Zuckerberg 为他正在成长的公司开设了第一家国际总部后不久,第一个对封闭协议时代有意义的挑战的蛛丝马迹出现了。

一名(或一群)神秘的程序员以 Satoshi Nakamoto 的名义给密码学的学术社区成员们的电子邮箱分发了一篇论文。这篇论文被叫做「比特币:点对点的电子现金系统」,在其中,Nakamoto 为一种数字货币概述了一个巧妙的系统,它不需要集中的可信权威来验证交易。

当时,Facebook 和比特币似乎属于完全不同的领域——一个是风投支持下蓬勃发展的社交媒体初创公司,让你分享生日祝福、与老朋友联系,而另一个则是一个不知名的电子邮件列表中的关于加密货币的错综复杂的方案。

但 10 年后,Nakamoto 在这篇论文中提出的想法已经对像 Facebook 这样的互联网巨头的霸主地位构成了最重大的挑战。

比特币的悖论之处在于,它很有可能成为一项真正革命性的突破,同时也是作为货币的一种巨大失败。

正如我所写的那样,在过去的五年里比特币的价值增长了近 100,000%,为早期投资者赚了一大笔钱,但也将其标榜为一种极不稳定的支付机制。而创造新比特币的过程也被证明需要惊人的能量消耗。

历史充满了新技术的故事,而最后这些新技术的最初应用与最终用途已经没什么关联了。所有对比特币作为支付系统的关注,可能同样会被证明是这样的一种干扰,是技术领域里会丢了西瓜的「芝麻」。

Nakamoto 在最初的宣言中把比特币定位为「点对点电子现金系统」,但在它的核心,他(或她或他们)提出的创新其实具有更一般的结构,这个结构有两个关键特征。

首先,比特币提供了一种证据,证明你可以创建一个安全的数据库——区块链——分散在成百上千的计算机上,而没有一个权威机构来控制和验证数据的真实性。

其次,Nakamoto 设计了比特币,以使维持分布式账本的工作本身就能得到少量的、越来越稀有的比特币支付。如果你将你计算机处理能力的一半投入到帮助比特币网络完成计算——从而抵御黑客和骗子——你就得到了一小块比特币。

Nakamoto 设计了这个系统,这样比特币就会随着时间的推移变得越来越难以获得,从而确保了系统中一定数量的稀缺性。如果你在早期帮助比特币保持数据库的安全,你将比后来的人赚更多的比特币。这个过程被称为「挖矿」。

基于我们理解的目的,请忘记一切关于比特币热的其他事情,就记住这两件即可:

Nakamoto 带来这个世界的是一种能在数据库没有管理员的情况下对内容达成一致认可的方法,以及一种不通过正式工资或是分得股权就能奖励那些帮助使数据库变得更有价值的人们的方法。这两种想法一起解决了分布式数据库问题和资金问题。

突然之间,一种在 Facebook 和 Twitter 的幼年时期不存在的,支持开放协议的方法出现了。

这两个功能现在已经被复制到了数十个受到比特币启发的新系统中。其中一个系统就是以太坊,这是 Vitalik Buterin 在他 19 岁时在一篇白皮书中提出的。以太坊确实有它的货币,但是以太坊的设计核心并不是为了方便电子支付,而是要让人们在以太坊区块链上运行应用程序。

目前,有数百个以太坊应用程序正在开发中,从预测市场到 Facebook 的克隆,再到众筹服务。几乎所有的产品都处于内测前阶段,还没有准备好供消费者使用。尽管应用程序处于萌芽状态,但以太货币已经出现了微型比特币泡沫,很可能为 Buterin 带来巨额财富。

这些货币可以被明智地运用。

Juan Benet 的 Filecoin 系统将依赖于以太坊技术,并奖励那些使用它的 IPFS 协议,或者帮助维护它所需要的共享数据库的用户和开发人员。协议实验室正在创建自己的加密货币,也称为 Filecoin,并计划在未来几个月在公开市场上出售部分 Filecoin。(在 2017 年的夏天,该公司通过向认证投资者提供 Benet 所说的代币「预售」,在头 60 分钟内筹集了 1.35 亿美元。)

许多加密货币首先是通过一种被称为「首次硬币发行(I.C.O)」的程序向公众供应的。这 I.C.O. 的缩写形式是故意在呼应定义了上世纪 90 年代第一次互联网泡沫的「首次公开发行(I.P.O.)」。但两者之间有一个关键的区别。

投机者可以在 I.C.O. 中买入,但它们并不是像在传统的 I.P.O. 中那样购买私人公司的股权及其专有软件。

之后,数字货币将继续被创造出来以换取劳动力——在 Filecoin 的情况下,也就是指那些帮助维持 Filecoin 网络的人们。帮助改进该软件的开发人员可以获得这些 Filecoin,普通用户也可以通过提供多余的硬盘空间来扩展网络的存储容量以获得 Filecoin。Filecoin 是一种信号,表明某人在某个地方为这个网络增加了价值。

像 Chris Dixon 这样的倡导者已经开始用「代币(tokens)」而不是硬币(coins)来指代这种劳动力交易中的补偿,以强调这样的技术并不一定是为了破坏现有的货币系统。

「我很喜欢这个代币的象征意义,因为它很清楚地表明它就像一个电玩城。」他说,「你去游乐场玩,在那里你可以使用这些代币。但我们并不是要取代美国政府。它不是真正的货币;它是一种在这个世界里的伪货币。」

MetaMask 的创始人 Dan Finlay 也响应了 Dixon 的观点。他说:「对我来说,最有趣的是我们已经开始规划新的价值体系。他们根本不需要模仿像金钱这样的现有体系。」

无论真假,I.C.O. 的想法已经激发了大量的影子发售,其中一些是由不太可能是区块链狂热者的名人代言的,比如 DJ Khaled、Paris Hilton 和 Floyd Mayweather。

在一篇发表于 2017 年 10 月的博客文章中,联合广场创业公司的创始人以及区块链革命的早期倡导者 Fred Wilson 强烈反对 I.C.O 的扩张。「我讨厌它,」威尔逊写道,并补充道大部分的 I.C.O. 都「是诈骗。而那些在社交媒体上为此站台的名人和其他人的这种行为很糟糕,可能已经违反了证券法。」

对于 I.C.O.——以及已经发行的比特币和以太币——兴趣的激增,可能最引人注目的就是有多少金融投机活动已经被吸引到了那些实际上没有被普通消费者采用的平台中去。

至少在上世纪 90 年代末的互联网泡沫时期,普通人的确在亚马逊上买书,或者在网上阅读报纸;那时有明确的证据表明,网络将会成为主流平台。

而如今,炒作周期已经被加速到,数十亿美元正在追逐一项几乎除了密码学专家以外无人能理解的技术,更不用说只有多少人真的在使用了。

为了讨论清楚,让我们假设炒作是必要的,而且像以太坊这样的区块链平台成为了我们数字基础架构的基础部分。那么一个分布式的分类账和象征性的经济将如何挑战一个科技巨头呢?

Fred Wilson 在联合广场风险投资公司(Union Square Ventures)的合伙人 Brad Burnham 提出了一个围绕另一家科技巨头的设想。去年,这家公司与监管机构和公众舆论发生了冲突——优步(Uber)。

「优步基本上只是司机和乘客之间的协调平台,」Burnham 说,「是的,它确实很有创意,一开始就有很多功能来减少司机是否会来的焦虑,还有地图,以及很多值得夸赞的东西。」

但当优步等新服务迅猛发展时,市场就有了巩固一个领导者的强大动力。事实上,越来越多的乘客开始使用优步 app 吸引了更多的司机,而这反过来又吸引了更多的乘客。人们在优步上绑定了信用卡;他们已经安装了应用程序;在路上也有更多的优步司机。因此,尝试其他竞争对手服务的转换成本最终会变得令人望而却步,即使首席执行官似乎是一个混蛋,或者理论上来说消费者应该更喜欢一个有十来个优步的竞争市场。

Burnham 说:「在某个时候,围绕协调的创新变得越来越没创意。」

区块链世界提出了不同的建议。想象一下,一些像协议实验室这样的团体决定在堆栈中添加另一个「基本层」。

正如 GPS 给我们提供了一个发现和分享我们位置的方法一样,这个新协议将定义一个简单的请求:我在这里,想去那里。分布式账簿可能会记录所有用户过去的旅行、信用卡、最喜欢的地点——所有优步或亚马逊这样的服务商用来锁定客户的元数据。为了方便论证,把它叫做「交通(transit)」协议。

将「交通」请求发送到互联网的标准将完全开放;任何想要构建应用程序来响应该请求的人都可以免费使用。城市可以建立「交通」应用程序,允许出租车司机提出请求。而自行车共享组织,或者人力车夫也可以这样做。

开发人员可以创建共享的市场应用程序,在这些应用程序中,所有的潜在车辆都可以通过「交通」来争夺您的业务。

当你走在人行道上,想要搭车时,你不需要在招呼之前就忠心于一个供应商。你会简单地宣布你站在麦迪逊广场 67 号,需要去联合广场。然后你会得到一连串的竞争性报价。你甚至可以在理论上得到大都会运输署(M.T.A)的报价。它可以建立一个服务来提醒「交通」的用户,直接乘坐轨道交通 6 号线可能会更便宜,也更快捷。

当优步和 Lyft 已经在拼车市场占据主导地位时,「交通」将如何达到临界规模?这就是代币发挥作用的地方。

早期用户将获得过「交通」代币,这些代币可以用来购买「交通」服务或兑换传统货币。就像在比特币模式中一样,随着交通工具的普及,代币分发会变得越来越吝啬。

在早期,一名用「交通」开发了 iPhone 应用程序的开发人员可能会得到一大笔代币;开始使用「交通」作为寻找乘客的第二种选择的优步司机可以收集到代币作为拥抱新系统的奖励;有冒险精神的消费者将会因为在早期开始使用「交通」而得到代币奖励,因为与现有的专有网络(如优步或 Lyft)相比,可用的司机要少得多。

当「交通」业务猛增时,它将吸引投机者,他们会将代币的标上货币价格,并通过膨胀其价值来驱动更多人对协议的兴趣,而这反过来又会吸引更多的开发商、司机和客户。如果整个系统最终像它的倡导者所认为的那样运作,那么结果就是一个更加竞争性,同时更公平的市场。

所有的经济价值而不是被一个或两个主导市场的大公司的股东获取,而是在一个更广泛的群体间分配:早期的「交通」开发人员、那些使得协议的使用更加用户友好的 app 开发者们、早期的司机和乘客用户,以及第一波投机者。

代币经济体引进一套不符合传统模型的新奇元素:不像在股东权益模型中那样拥有资本来创造价值拥,人们通过改善底层协议、帮助记账(就像比特币挖矿)、在上面编写应用程序,或者只是使用服务来创造价值。创始人、投资者和客户之间的界线比传统的公司模式要模糊得多;所有的激励都是明确设计来避免赢家通吃的结果。然而,与此同时,整个系统依赖于一个最初的投机阶段——外部人士押注于代币升值。

「你想想 90 年代的互联网泡沫,以及我们从中得到的所有伟大的基础设施,」Dixon 说,「你基本上是接受了这些成果,并将其缩小到应用程序的大小。」

即使是分散化的加密动作也有其关键节点。

在以太坊中,其中一个节点是总部位于布鲁克林的一个叫 Consensys 的组织,由一位以太坊的早期先驱 Joseph Lubin 创立。十一月,ConsenSys 的首席营销官,26 岁的 Amanda Gutterman,带我参观了该组织总部。在我们在一起的最初几分钟里,她坚持要给我泡一杯咖啡,却发现厨房里的滴漏式咖啡机已经干透了。

「如果我们连咖啡都不能煮,还怎么去修理互联网?」她笑着说。

Consensys 的总部位于工业城市布什威克,毗邻比萨爱好者的朝圣地 Roberta’s,这与「总部」的形象格格不入。门前满是涂鸦和贴纸;门内的楼梯井还维持在库利奇政府时期的风格。

仅仅三年时间,Consensys 网络现在已拥有超过 550 名雇员,分布在 28 个国家,且从来没有接受过任何风险投资。作为一个组织,ConsenSys 并不太适合被归为任何常见的类别:从技术上讲,它是一个公司,但它也有类似于非营利组织和工人团体的成分。

Consensys 成员的共同目标是加强和扩大以太坊区块链的影响力与规模。他们支持开发者为以太坊平台创建新的 app 和开发工具,其中就有 MetaMask 软件,用于生成我的以太坊地址。但他们也为企业、非营利组织或政府提供咨询式的服务,帮助这些机构将以太坊的智能合同纳入到他们自己的系统中。

区块链所面临的真正考验将围绕身份问题循环出现,就像过去几年反复出现的那些线上危机一样。

今天,你的数字身份会分散在几十个甚至数百个不同站点上:亚马逊有你的信用卡信息和你的购买历史记录;Facebook 知道有关你的朋友和家人的信息;Equifax 保存了你的信用记录历史。当你使用这些服务时,你实际上是在请求出借一些关于你自己的信息,从而执行某项任务:为你的叔叔订购圣诞礼物,或是打开 Instagram 查看昨晚的办公室聚会图片。

但你的所有这些不同身份片段都不属于你;它们属于 Facebook、亚马逊和谷歌,这些公司可以自由地向广告商推销有关你的信息,却不必通知你本人。

当然,你可以选择删除这些账户,如果你停止使用 Facebook,扎克伯格和 Facebook 的股东就不能再把你的注意力租给他们真正的客户,也就不能从你身上赚钱了。但是,你却带不走在你在 Facebook 或谷歌的身份。如果你想加入另一个富有吸引力的社交网络,它受到俄罗斯机器人(Russian bots 的感染程度可能比较小,但是你不能从 Twitter 中提取出你的社交网络并把它存入新的服务中。你必须从头开始构建网络(并说服你的所有朋友都这样做)。

区块链传道者认为,这套方法已经落伍了。

你应该拥有你自己的数字身份,它包括你的出生日期、朋友网络、购买历史等,你应该能够自由调用这些身份片段,将它借给你认为合适的服务。

由于你的身份并没有被纳入最初的互联网协议,且在比特币出现之前,分布式数据库的管理困难重重,因此这种形式的「自主权」身份——正如这句话所说的那样——在过去实际上是不可能的。

现在,这个目标可以实现了。

一些基于区块链的服务正试图解决这个问题,包括一种新的身份系统 Uport,是从 ConsenSys 独立出来的,以及目前基于比特币平台的 Blockstack。(Tim Berners Lee 正在领导一个类似系统的开发工作,称作 Solid,它也将允许用户拥有对个人数据的控制权。)这些竞争对手的框架都略有不同,但他们都立足于解决同一个问题,即身份应该如何存在于一个真正的去中心化的互联网中。

什么能够让一个基于区块链的新身份标准脱离 Tim Wu 的管辖?后者一手促成了 Facebook 的这种主导地位。也许没有什么能够阻挡这一趋势。但是想象一下,这个序列在实践中会发挥怎样的作用?

有人通过以太坊创建了一个新协议来定义你的社交网络。它可能同其它一系列的以太坊地址一样简单;换句话说就是,这是那些我喜欢并信任的人的公共地址。

这种定义社会网络的方式或许能赢得大众的欢迎,并最终取代 Facebook 那种自行定义用户网络的封闭式系统。也许有一天,地球上的每个人都可以用这个标准来描绘他们的社会关系,就像互联网上的每个人都使用 TCP/IP 来共享数据一样。

即使这种新的身份形式无处不在,它也不会给滥用和操纵行为创造机会,而这在封闭系统中实际上已经成为了事实标准。

Facebook 式的服务可以基于我的好友动态来使用我的社交地图,从而为我过滤新闻、八卦或音乐,但如果这项服务惹恼了我,我就可以自由地选择其它选择而无需转换成本。一个开放的身份标准将能够给普通人创造一个机会,让他们把注意力集中到出价最高的广告主身上,或是选择将他们完全屏蔽。

Gutterman 认为,该类系统可以被应用于更加重要的身份形式,比如医疗数据。你的基因组数据将不属于私营机构,他们无权将其存储在自己的服务器上,你的信息将被存储在个人的数据档案中。

「可能我不想让很多实体企业看到这些数据,但也许我愿意把它们捐给医学研究项目。」她说,「我可以把我的基于区块链的自主权账户发给一个研究小组,(允许)他们而非其他人来使用我的数据。我可以把它们卖了,或者把它们捐了。」

由于 Facebook 等封闭标准采用 token 架构,这给了基于区块链的身份标准一个优势。

许多评论家观察到,在从内容生产到广告销售这一整条产业链中,普通用户在社交媒体平台上创建内容,却几乎没有得到任何补偿,而该媒体平台却可以捕获其中的所有经济价值。

一个基于 token 的社交网络至少会给早期用户一点补偿,奖励他们为新平台凝聚到的吸引力。

「如果有人真的能创造出一种社交网络平台,让用户拥有网络的一部分并获得相应的报酬,」Dixon 说,「那将相当有说服力。」

相较于谷歌或 Facebook 等科技巨头所精心构建的防火墙,信息在一个分布式区块链中会更加安全吗?

在这方面,比特币的故事实际上很有启发性:作为一种货币,它可能永远都不够稳定,但它确实提供了一个令人信服的证据,即分布式分类账户有很高的安全性。

「看看比特币或以太坊的市值:800 亿美元,250 亿美元,具体的我忘了,」Dixon 说。

「这意味着,如果你攻破了这个系统,你就可以卷走至少十亿美金。你听说过「bug 悬赏(bug bounty)」吗?有人称,『如果你破解了我的系统,我就给你一百万美元』,所以现在,比特币在过去的 9 年时间里已经积累了数十亿美元的 bug 赏金,但没有人曾越过它的防线。这似乎是一个很好的证明。」

基于区块链的身份协议具有分散性,这同样也增加了信息的安全性。

在 Blockstack 提出的身份系统中,有关你的身份的实际信息,比如你的社会关系、购买历史等,将被存储在线上空间的任何地方。区块链使用加密的安全密钥来解锁信息,并将其共享给其他值得信赖的供应商。一个拥有数亿用户数据的中央存储系统——安全专家称之为「蜜罐(honey pots)」——对黑客来说更具吸引力。

你会偏向于哪种做法:入侵一亿台独立的个人电脑,在每一台大脑上逐条筛选数据,然后窃取一亿条信用记录;或者入侵一个一个 Equifax 的中央存储系统,然后在几小时之内卷走这一亿条数据。

正如 Gutterman 所说,「这是抢劫一栋房子和抢劫整个村庄之间的差异。」

太多的区块链架构受制于这样一堆预测,即一旦该架构发现了一个更广泛的观众群体,那么它可能会如何被滥用。

这是其自身魅力和力量的一部分。区块链疏导了投机泡沫的能量,因为它允许平台上的广大真实支持者去共享 Token。它会阻碍任何个人或小团体获得对整个数据库的控制权。它的加密机制是为了防止监视状态或阻挡身份窃贼。在这方面,区块链显示出一种政治宪法般的家族相似性:其规则设计着眼于该规则被利用的潜在方式。

在比特币和其它无证货币社区中,涌现出众多无政府自由主义倾向;这个社区充斥着一些词语和短语(比如「自主权」),听起来像是蒙大纳州一些民兵组织的口号。

然而对于想要更公平地分配财富、打破数字时代的卡特尔的人,区块链思想提供了一个诱人的可能性,该社区或可瓦解高度的权利集中,探索出较为民主的所有权模型。

在这个意义上,区块链理念还可以为自由主义者发声,它为资本无度行为(比如信息垄断)提供了非官方的解决方案。

然而,对区块链的信任并不意味着必须反对监管,如果该监管制度的设计目标与之互补的话。

例如,Brad Burnham 建议监管机构,应该坚决支持每个公民对「私人数据商店的掌控权」,其中包括公民在线身份的各个方面。

但是政府不会被要求设计那些身份协议。它们将会在区块链中被开发出来,并开放源码给大众。

从意识形态上讲,私人数据的存储任务将需要社会各方的协助:作为一种公共知识财产而被创建,受到 Token 投机者的资助,并在监管机构的支持下维持运营。

与互联网刚出现时一样,区块链思想对于大众来说有些激进,甚至带有社群主义,同时又吸引到了一些最为轻率资本欲望的回潮。

我们在线上世界的第一个二阶段是由开放协议和知识共享所定义的;我们的第二个阶段渐渐受到封闭式架构和专有数据库的主导。我们从这段历史中学到,开放优于封闭,至少在基础问题上是如此。但我们很难找出一条回到开放协议时代的路。在国防部科研领域之外,不太可能出现一些救世主般的下一代互联网协议,第一代互联网早在 50 年前就这么做了。

在现在看来,区块链似乎是最糟糕的投机资本主义,而且它还让人难以理解。但是,开放协议的美妙之处就在于,那些在早期发现并拥护它们的人,能够以令人震撼的新方式来驾驭它们。

就是现在,区块链是复兴开放协议精神的唯一希望。最终,它能否兑现其追求平等的承诺,将在很大程度上取决于这些平台上的拥护者。

用 Juan Benet 的话来说,他们从这些早期的网络先驱那里接过了接力棒。

如果你认为,在现有的互联网架构下,你无法独自通过思考和 F.C.C 法规来改变这个系统,那么你需要新的代码。

本文链接: https://netlover.cn/2018/08/17/qukuailian-weilai.html

ExceptionLess本地部署

ExceptionLess是一套免费开源分布式系统日志收集框架

参考资料

官方wiki文档 https://github.com/exceptionless/Exceptionless/wiki/Self-Hosting

搭建步骤:

  1. .NET 4.6.1。如果已安装过VS请忽略。
  2. 安装JDK配置环境变量
  3. 下载 Elasticsearch
  4. 下载 ExceptionLess

第一步,安装JDK并配置环境变量。

第二步,解压Elasticsearch,进入bin目录,运行elasticsearch.bat。

第三步,解压 Exceptionless,运行Start.bat。

在执行Start.bat的时候,如果出现以下错误,请参考PowerShell设置

powershell Set-ExecutionPolicy Unrestricted

如果没有报错,会出现”正在请求写入流“。

等待安装完成,会自动打开http://localhost:50000/这个页面。
在低版本的安装过程中,需要修改各种配置文件,在最新版本已经不需要手动去修改了,完全是傻瓜式安装。
到此为止,安装流程已经全部完成了。

本文链接: https://netlover.cn/2018/08/16/ExceptionLess-local.html

如何成为一个合格的架构师?

在互联网圈,架构师这个名号的火热程度堪比产品经理,它在产品经理没火之前就已经风生水起。

仅以本文向带给我许多欢乐和感悟的周星驰致敬。

架构师的定义

乔布斯是苹果的产品架构师,比尔盖茨是微软的首席架构师,马化腾也号称腾讯的首席架构师。

有些人会觉得架构师很神秘,不知道整天脑袋里在想什么。那么架构师到底是什么样的人?

聚焦到 IT 技术领域,基本可以还原,架构师的本质就是更高级更资深的程序员,架构师的能力要求在程序员或者说工程师之上,是一脉相承,有延续性的。

有些大厂因为层级较多(当然也是有更顶尖的人才),高级工程师跳到小厂做个架构师游刃有余。

所以我们并不纠结于工程师进阶架构师的边界到底在哪里,实际上有的公司架构师是正式职位,有的只是项目的临时职务。

架构师是足够复杂、规模较大的系统才需要的角色,当系统架构不那么一目了然,才需要有人在更高的视角上去关注整体性的东西。

架构师是高阶职位,难以通过培训批量生产,严重依赖于个人的工作经验和成长,而且各方面都要求更高。

架构师的经验体现在什么地方呢?举一个例子:

比如一个复杂的分布式系统,时时刻刻处理业务请求,要设计一套机制,保证所有的业务都能处理完成,无论成功失败。

简单的开发思维会考虑,尽可能的捕获异常,给每一种错误类型编号,中途失败的流程要进行回退,相信设计能否覆盖所有情况。

有经验的架构师则会清醒的认识到,这样的系统随着不断升级和持续运行,一定会出现各种各样的问题,不出问题是不可能的。

应用的潜在 Bug、业务逻辑漏洞、数据异常、网络抖动、硬件故障、人工误操作,甚至还有莫名其妙未能找到原因只能归结为灵异事件的问题,会层出不穷,等你解决。

我们需要做的是尽可能监控、捕获到异常情况,通过技术手段修复多数的问题,少数不常见的或者难以自动解决的问题最终还是要考虑通过人工方式处理。

我们的目标是解决问题,通过分析,调整架构,优化逻辑,旧的问题解决后,还会有新的问题。
只要系统运行,就需要维护,软件工程理论中系统上线后期维护都是一个重要的阶段,此时系统是动态的,业务是连续的。

用近几年很多人用过的比喻,开着飞机修飞机,开着火车修火车,在原有的系统上做修改,并不比从头做一个系统轻松。

就像是 CAP 理论下,多数的选择是最终一致性,即通过努力,无限趋近于问题最小化,时刻准备着迎接新问题,动态平衡才是系统运行的常态。

用七句话总结我对架构师的定义:

  • 以工程思维全面理解业务需求
  • 基于模型和基础模式抽象简化
  • 提出恰当可行的整体解决方案
  • 在限定资源范围完成明确目标
  • 满足业务需求且保证系统质量
  • 在可预见的周期内具备扩展性
  • 并在系统生命周期内持续演进

以上只是描述了架构师本身,实际工作中还有许多干系人,包括了项目经理、业务需求提出方、产品经理、研发工程师、测试工程师、运维工程师、DBA 及各部门各层级的管理者,在一些外部合作的项目中还包括其他公司的各类人员。

项目由相关干系人组成的团队完成,架构师必须与其中各类角色协作,以达成项目目标。

因此要有很好的综合素养,对于相关干系人的职责必须有深入理解,熟悉项目操作流程,能够与各方做好沟通。

比如现在都推行敏捷开发,快速迭代,一般的需求,小的敏捷团队就可以实现,架构师可能不会参与,怎样保证设计开发的质量?

更远一点,怎么保证在诸多小团队各行其是的情况下,整体架构的合理性、先进性,甚至推进架构演化?

这其中会有很多流程外的沟通交流,架构,不是编码规范、设计原则、技术框架,更多的时候是通过各种沟通,尤其是非正式沟通,所达成的共识。

这个共识越清晰,沟通成本就越低,工作就越高效,产品质量就越有保证。

架构师的核心价值

系统架构有哪些特征?对架构师有怎样的要求呢?总结如下五点:

技术开源化

开源已经成为互联网技术的主流,多数公司使用开源技术,自行选型维护,出了问题自己解决,而且技术更新很快,需要能够高效学习快速上手。

开源的技术流,与大众创业、万众创新一样,充分发挥创造力,各种风险和坑也都由使用者来买单。

产品敏捷化

业务调整快,小步快跑,快速试错,必然弱化长期规划,创业公司可以先上 MVP,已经上规模的公司怎么保持活力?

可以将新的业务做成独立的模块,解耦,降低依赖,更重要的是时刻关注架构的灵活性,有备无患。

服务全网化

面向全网用户,随时提供服务,系统规模大,停止服务就会损失收入,要求尽可能无缝升级。

业务不可控性较大,业务量可能波动很大,一旦业务爆发,要有快速的弹性部署方案。

系统复杂化

难免有很多的临时方案,以及有用没用的功能堆积,会使系统的可维护性,架构合理性越来越差。

系统的交互越来越多,关联性强,需要工具结合系统机制进行管理,否则就会失控。

人力高效化

根据摩尔定律,基础设施成本日趋廉价,而人工成本则持续走高,这是两个必然方向。

那么就需要提供更好的技术平台,好钢用在刀刃上,技术人员的能力要求越来越高,高效做有意义的事,简单重复的东西让机器去做。

架构师的核心价值是什么?借用李智慧老师《大型网站技术架构核心原理与案例分析》中的说法:

软件架构师的最大价值不在于掌握多少先进的技术,而在于具有将一个大系统切分成 N 个低耦合的子模块的能力,这些子模块包含横向的业务模块,也包含纵向的基础技术模块。

这种能力一部分源自专业的技术和经验,还有一部分源自于架构师对业务场景的理解、对人性的把握、甚至对世界的认知。

在技术团队中,架构师是技术的领导者,没有人辅导,手把手教更是不可能,必须对最终设计和实现负责。

多数情况下,架构是一种妥协,一种平衡的产物,掌握这个平衡度的,就是架构师。

我们都知道,理想的架构是什么样的,但又必须抱残守缺,面对现实,提出可行方案。

因此,架构师是胸怀理想的现实主义者,高度在理想,落地在现实,绝对是有挑战,有难度。

架构师的核心能力

对于架构师的核心能力定义,《软件架构师的 12 项修炼》中有一张图,可作参考。

周爱民老师也曾经在《程序员》上发表过《做人、做事,做架构师——架构师能力模型解析》。

就我的个人总结,架构师的核心能力包括六个方面:

做一个合格的架构师,需要各方面能力都比较强,不能有明显的短板。

其中技术能力和业务能力属于硬指标,可以通过学习和工作,跨过行业门槛获得。

这里主要分析下后四种,可称为通用技能,对于团队协作的技术职位都是需要的。

前三种自我驱动、高效学习、良好心态是内功,用汽车比喻的话,自我驱动能力相当于发动机,高效学习能力则是方向盘和变速箱,良好心态就是悬挂和制动系统。

沟通协作则是外功,最终的外在体现,内功与外功两者之间就如同内因和外因,起决定作用的是内部因素。

自我驱动能力

这是一种特质,简单说就是有上进心,不甘于混日子,闲不住,爱钻研,始终有目标性的追求,有很强的自控力。

这种动力来自于兴趣,比如对技术的热爱,就是喜欢。

每个人都有自己的兴趣点,可能不是 IT 技术,找对自己的方向很重要。

而且喜欢不一定就能做好,有时候努力够了,成就要看天分,发现对自己不合适,干活没劲头,不如及早调整。

具备这样能力的人一般都很明显,做事努力,用心,进步很快,相信大家在工作和学习过程中都遇到过。

举一个加班的例子吧,搞 IT 的加班很常见,甚至可能许多人并不是真心愿意加班,但一定有很多人有这样的经历。

就是碰到一个技术问题,哪怕工期上没有那么紧迫,也要盯着它,甚至不吃饭,不喝水,绞尽脑汁要整明白,死磕到底,搞定为止。

自我驱动力表现在了这种高度专注的精神,遇到问题斗志昂扬的冲劲,解决问题的成就感之上。

高效学习能力

IT 技术需要不断学习,持续更新,真正的学习,是要靠自己的,要把学习养成习惯。

架构师很多时候要快速切入一个不熟悉的领域,必须要有高效的学习能力。

有些人会抓住一切机会学习,比如我的某位同事,等待面试的时候还拿着一本技术的书在看。

在同等的时间里,怎样能有最高效的吞吐量,获得更多的有价值的信息量,并沉淀为自己的能力,就需要正确的方法。

每个人都有自己的特点,需要找到适合自己的学习方法,方法得当,事半功倍。

那么学习的过程,也是一个不断发现自我,形成模式,目标导向,反复强化,不断调整的过程。

比如曾经有位同学,每天下班回家,还要看英文原版的书,在家钻研技术到后半夜,形成了习惯,成效自然显著,后来去了百度。《从学渣到学霸-我的 100 天阅读简史》,可作为学习的借鉴。

保持良好心态

N 年前,曾经流行一句话,心态决定一切。TVB 有句经典台词说得好,做人呢,最重要的就是开心。

积极正面的阳光心态,是把事情做好的基础,因为工作中难免有意外和波折,不会一帆风顺,好心态能够为你保驾护航。

好心态一般什么样呢?谦虚平和、宽容、有韧性,活在当下,内心强大。不是说你是架构师就高人一等,要凭实力说话。

这其中还包括责任心,决定了心态的方向。比如我就认为,敬业是职业化的体现,那么无论是否处在已经即将离职的状态,都应该做好自己的职责,做一天和尚撞一天钟。

善于沟通协作

架构师处在团队中,且属于技术核心角色,必须做许多沟通配合的工作,而且要做好,做到位。

这其中有几方面需要强调,首先是团队精神,架构师不能个人英雄主义,团队的存在就是因为能做到比个人更好,团队的成功才是最终的目标。

团队成员各有千秋,合作愉快的基础是理解万岁,消除沟通障碍,架构师在这方面有更大的责任和义务。

技术人员相对简单直接,也容易认可技术上的原则,以诚相待能够最大程度上降低沟通的成本,事情说清楚就好。

而成就他人是一个技术领导者必备的素质,相信互惠互利,我为人人,人人为我,甚至要把更多的机会给别人,吃独食的人难以服众。

架构师的四门功课

架构设计是一门艺术,架构师作为架构设计的实践者,要掌握四门功课,不是说学逗唱,而是:多打酱油,能和稀泥,肯背黑锅,敢拉仇恨。

多打酱油

互联网公司普遍存在人员流动性强,缺乏文档的情况,而架构设计偏偏需要全方位考虑问题。

我就曾经遇到过这样的事情,一大帮人开了两小时的会,终于讨论出一个都能够接受的可行方案,结果第二天有个没能参会的人回了个邮件,说他们有问题趟不过去,原来的方案得推翻重来。

技术最重要的一点就是复用,不重复造轮子,如果有的功能或者组件别人做过,拿过来用是最方便的。

所以架构师必须消息灵通,覆盖全面,知己知彼,收集问题,尽可能了解全局。

多打酱油什么意思,无论是否由你主导,主要的项目都要保持关注,多参与,多积累才有发言权。

这个过程中要不装不拿,不懂多问,谁也不是全才,不必急于表达自己和做出判断,谋定后动。

打酱油不仅获取信息,还要输出信息,哪怕事不关己,可以建议,但不能指手画脚,获取沟通的最大收益,形成技术部门共识。

一般来说,男同学都是单线程思维模式,要达到最好的效果,打酱油的时候也要专注精神不分二心。

当然也有奇人能够做到并发处理,比如我的前同事老王,时间分片高频切换事务处理输入输出,堪称一台人形电脑。

当当技术部原来有一个开会的潜规则就很好,除了产品经理和项目经理,其他人开会都不带电脑,只拿笔记本。

能和稀泥

架构的核心在于平衡,实用导向,最终要提出解决方案。

那么就需要在这个过程中综合考量,化解争论,对事不对人,规避面子问题,努力充分沟通,达成共识。

充分了解各方意见,设身处地理解本质问题,提出多种方案,客观的列出优缺点,以供决策。

但有时也有化解不了的矛盾,无论是基于技术理念、设计思路、自身定位还是意气之争,有时搁置也是一种可选项,比如邓小平对钓鱼岛、台湾问题的处理方式。

之前有一个项目,我们提出的方案某个系统开发负责人不认可,期望用另一种实现方式。

那我们就把两种方案都拉出来对比,每个系统的改动难度、问题都说清楚,最终对方还是接受了原来的方案。因为综合考虑,这才是最优解。

肯背黑锅

能力越大,责任越大,想做事就要有勇气担责任,抗风险,逃避责任是难有成就的。

举个例子,曾经有一个紧急的需求,交给了一个同事,快上线的时候撂挑子说干不完,领导找到我,问能不能干。

这种情况,时间紧任务重,要是接了没干出来,黑锅就落在自己身上,但需求总要有人做,领导的信任更不能辜负,任务接下来干好了,后面就不必说了。

架构师作为主导,要清醒的意识到,需求和状况总是变化的,总有考虑不周的,总有难办的有挑战的,总有不确定的各种风险,需要坚持推进达成目标。

如果推进不成或者发现之前的判断甚至决策失误,适时调整,不必钻牛角尖,也要坦然承担失败的责任,这也是一种宝贵的经验。

作为一个技术团队,可能出现问题并非直接责任人是架构师,不必非要划清界限,团队的失败,也是每个人的失败。

最后要清楚,谋事在人,成事在天,事在人为,但要的确可为,明知不可为而为之,不是明智之举。

敢拉仇恨

架构师要面对很多挑战,技术人员都很有想法,都认为自己伟大光荣正确,不会因为你是架构师就乖乖地听话,要以理服人。

一个设计方案的出炉,可能需要像诸葛亮一般舌战群儒,说服很多人。

我遇到过这种情况,明明是好事儿,做起来也不难,就是有人不接受,不愿意做。

那就需要坚持主张,胸怀坦荡,没有私心,正直诚实,打开天窗说亮话。

即便大家很熟,也不能抹不开面子,不讲原则。

要注意一点,虽然真理经常是掌握在少数人手里,但要让多数人接受,不能被接受的真理也是没有价值的,可能就不是真理。

所以架构师可以力排众议,但不能成为千夫所指。

比如我们经常遇到时间紧迫要做临时方案,不考虑扩展性,如果同类的业务模式重复出现,再做临时方案虽然大家都轻车熟路,却不是一个好的选择。

因为有再一再二,就会有再三再四,只要把握住这一点,尽早进行架构改造,实现后就能快速响应后续的同类需求,这也体现了架构师的价值。

当你做的正确的事情多了,才会与团队磨合,获得大家的信任,而不是怨念,逐步树立自己的权威,从此可以跟小伙伴们一起愉快地玩耍了。

本文链接: https://netlover.cn/2018/08/16/do-jiagoushi.html

基于vue生态的UI框架推荐

1.elementUI

由饿了么前端开源的UI框架,一经面世,就收获大量程序员的芳心。在github 上更是高达29.8k的star早已说明一切。用于开发PC端的页面还是绰绰有余的。如果说你是用vue开发者,却没用过element UI,那你肯定不是合格的vue开发者。

官方:http://element.eleme.io

Github:https://github.com/ElemeFE/element

2.iview

这个UI框架是对标elementUI而生的,最大优点是官方有桌面版配置工具,只需使用鼠标就可以构建一个基于iview+vue的应用,免去手巧命令的烦恼。最新的版本为3.x。建议对elementUI框架审美疲劳的同学可以尝试这个呦。官方网站的文档和例子基本上你是小白也能学明白。

官方:https://www.iviewui.com/

Github:https://github.com/iview/iview

3.zanUI

由有赞团队开源的移动端UI框架,对于移动电商应用的开发来说,有很多写好的页面组件,可以直接拿来使用。当然zanUI的样式也是很好看的。当然也有PC端组件,和小程序端。zanUI一共分三个版本,针对移动端的为vantUI,PC端为zentUI,小程序端为Vant Weapp。

官方:https://youzan.github.io/vant-weapp

Github:https://github.com/youzan/vant-weapp

4.onsenUI

这个UI框架是国外开发,所以UI设计,很多都是迎合国外用户,对于国内用户,可能不是很好看,但是做为主打海外市场的应用,这个UI框架还是值得去使用的。

官方:https://onsen.io/

Github:https://github.com/OnsenUI/OnsenUI

5.mintUI

这个是一个中规中矩的移动端UI框架,适合移动端的绝大部分场景。

官方:http://mint-ui.github.io

Github:https://github.com/ElemeFE/mint-ui/

6.museUI

这个框架还是比较有特色的,不管怎么说,这类不随波逐流的UI框架已经很少见了,但是还是建议使用在主打海外市场的应用上。

官方:https://muse-ui.org/

Github:https://github.com/museui/muse-ui

本文链接: https://netlover.cn/2018/08/16/vue-ui-recommend.html

常用meta标签的作用以及全面整理

1、定义

标签提供关于 HTML 文档的元数据。它不会显示在页面上,但是对于机器是可读的。可用于浏览器(如何显示内容或重新加载页面),搜索引擎(关键词),或其他 web 服务。

2、作用

meta里的数据是供机器解读的,告诉机器该如何解析这个页面,还有一个用途是可以添加服务器发送到浏览器的http头部内容,例如我们为页面中添加如下meta标签:

1
2
<meta http-equiv="charset" content="iso-8859-1">
<meta http-equiv="expires" content="31 Dec 2008">

浏览器的头部就会包括这些:

1
2
charset:iso-8859-1
expires:31 Dec 2008

只有浏览器可以接受这些附加的头部字段,并能以适当的方式使用它们时,这些字段才有意义。

3、meta的必需属性和可选属性

meta的必需属性是content,当然并不是说meta标签里一定要有content,而是当有http-equiv或name属性的时候,一定要有content属性对其进行说明。例如:

必需属性

1
<meta name="keywords" content="HTML,ASP,PHP,SQL">

这里面content里的属性就是对keywords进行的说明,所以呢也可以理解成一个键值对吧,就是{keywords:”HTML,ASP,PHP,SQL”}。

可选属性

在W3school中,对于meta的可选属性说到了三个,分别是http-equiv、name和scheme。考虑到scheme不是很常用,所以就只说下前两个属性吧。

http-equiv

http-equiv属性是添加http头部内容,对一些自定义的,或者需要额外添加的http头部内容,需要发送到浏览器中,我们就可以是使用这个属性。在上面的meta作用中也有简单的说明,那么现在再举个例子。例如我们不想使用js来重定向,用http头部内容控制,那么就可以这样控制:

1
<meta http-equiv="Refresh" content="5;url=https://netlover.cn" />

在页面中加入这个后,5秒钟后就会跳转到指定页面啦,效果可看W3school的例子

name

第二个可选属性是name,这个属性是供浏览器进行解析,对于一些浏览器兼容性问题,name属性是最常用的,当然有个前提就是浏览器能够解析你写进去的name属性才可以,不然就是没有意义的。还是举个例子吧:

1
<meta name="renderer" content="webkit">

这个meta标签的意思就是告诉浏览器,用webkit内核进行解析,当然前提是浏览器有webkit内核才可以,不然就是没有意义的啦。当然看到这个你可能会有疑问,这个renderer是从哪里冒出来的,我要怎么知道呢?这个就是在对应的浏览器的开发文档里就会有表明的,例如这个renderer是在360浏览器里说明的。360浏览器内核控制Meta标签说明文档

常用meta标签大总结

接下来就是常用的meta标签大总结啦,我会尽可能的做到全

charset

charset是声明文档使用的字符编码,解决乱码问题主要用的就是它,值得一提的是,这个charset一定要写第一行,不然就可能会产生乱码了。

charset有两种写法

1
2
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

两个都是等效的。

百度禁止转码

百度会自动对网页进行转码,这个标签是禁止百度的自动转码

1
<meta http-equiv="Cache-Control" content="no-siteapp" />

SEO 优化部分

1
2
3
4
5
6
7
8
9
10
<!-- 页面标题<title>标签(head 头部必须) -->
<title>your title</title>
<!-- 页面关键词 keywords -->
<meta name="keywords" content="your keywords">
<!-- 页面描述内容 description -->
<meta name="description" content="your description">
<!-- 定义网页作者 author -->
<meta name="author" content="author,email address">
<!-- 定义网页搜索引擎索引方式,robotterms 是一组使用英文逗号「,」分割的值,通常有如下几种取值:none,noindex,nofollow,all,index和follow。 -->
<meta name="robots" content="index,follow">

viewport

viewport主要是影响移动端页面布局的,例如:

1
<meta name="viewport" content="width=device-width, initial-scale=1.0">

content 参数:

  • width viewport 宽度(数值/device-width)
  • height viewport 高度(数值/device-height)
  • initial-scale 初始缩放比例
  • maximum-scale 最大缩放比例
  • minimum-scale 最小缩放比例
  • user-scalable 是否允许用户缩放(yes/no)

各浏览器平台

Microsoft Internet Explorer

1
2
3
4
5
6
7
8
9
10
11
<!-- 优先使用最新的ie版本 -->
<meta http-equiv="x-ua-compatible" content="ie=edge">
<!-- 是否开启cleartype显示效果 -->
<meta http-equiv="cleartype" content="on">
<meta name="skype_toolbar" content="skype_toolbar_parser_compatible">
<!-- Pinned Site -->
<!-- IE 10 / Windows 8 -->
<meta name="msapplication-TileImage" content="pinned-tile-144.png">
<meta name="msapplication-TileColor" content="#009900">
<!-- IE 11 / Windows 9.1 -->
<meta name="msapplication-config" content="ieconfig.xml">

Google Chrome

1
2
3
4
<!-- 优先使用最新的chrome版本 -->
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
<!-- 禁止自动翻译 -->
<meta name="google" value="notranslate">

360浏览器

1
2
<!-- 选择使用的浏览器解析内核 -->
<meta name="renderer" content="webkit|ie-comp|ie-stand">

QQ手机浏览器

1
2
3
4
5
6
<!-- 锁定屏幕在特定方向 -->
<meta name="x5-orientation" content="landscape/portrait">
<!-- 全屏显示 -->
<meta name="x5-fullscreen" content="true">
<!-- 页面将以应用模式显示 -->
<meta name="x5-page-mode" content="app">

Apple iOS

1
2
3
4
5
6
7
8
9
10
11
<!-- Smart App Banner -->
<meta name="apple-itunes-app" content="app-id=APP_ID,affiliate-data=AFFILIATE_ID,app-argument=SOME_TEXT">
<!-- 禁止自动探测并格式化手机号码 -->
<meta name="format-detection" content="telephone=no">
<!-- Add to Home Screen添加到主屏 -->
<!-- 是否启用 WebApp 全屏模式 -->
<meta name="apple-mobile-web-app-capable" content="yes">
<!-- 设置状态栏的背景颜色,只有在 “apple-mobile-web-app-capable” content=”yes” 时生效 -->
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<!-- 添加到主屏后的标题 -->
<meta name="apple-mobile-web-app-title" content="App Title">

Google Android

1
2
3
4
<meta name="theme-color" content="#E64545">
<!-- 添加到主屏 -->
<meta name="mobile-web-app-capable" content="yes">
<!-- More info: https://developer.chrome.com/multidevice/android/installtohomescreen -->

App Links

1
2
3
4
5
6
7
8
9
10
11
<!-- iOS -->
<meta property="al:ios:url" content="applinks://docs">
<meta property="al:ios:app_store_id" content="12345">
<meta property="al:ios:app_name" content="App Links">
<!-- Android -->
<meta property="al:android:url" content="applinks://docs">
<meta property="al:android:app_name" content="App Links">
<meta property="al:android:package" content="org.applinks">
<!-- Web Fallback -->
<meta property="al:web:url" content="http://applinks.org/documentation">
<!-- More info: http://applinks.org/documentation/ -->

最后——移动端常用的meta

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
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="format-detection"content="telephone=no, email=no" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" /><!-- 删除苹果默认的工具栏和菜单栏 -->
<meta name="apple-mobile-web-app-status-bar-style" content="black" /><!-- 设置苹果工具栏颜色 -->
<meta name="format-detection" content="telphone=no, email=no" /><!-- 忽略页面中的数字识别为电话,忽略email识别 -->
<!-- 启用360浏览器的极速模式(webkit) -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- 针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓 -->
<meta name="HandheldFriendly" content="true">
<!-- 微软的老式浏览器 -->
<meta name="MobileOptimized" content="320">
<!-- uc强制竖屏 -->
<meta name="screen-orientation" content="portrait">
<!-- QQ强制竖屏 -->
<meta name="x5-orientation" content="portrait">
<!-- UC强制全屏 -->
<meta name="full-screen" content="yes">
<!-- QQ强制全屏 -->
<meta name="x5-fullscreen" content="true">
<!-- UC应用模式 -->
<meta name="browsermode" content="application">
<!-- QQ应用模式 -->
<meta name="x5-page-mode" content="app">
<!-- windows phone 点击无高光 -->
<meta name="msapplication-tap-highlight" content="no">
<!-- 适应移动端end -->

本文链接: https://netlover.cn/2018/08/15/meta-all.html

初步接触hexo

官方文档

https://hexo.io/zh-cn/docs/

init

1
$ hexo init [folder]

新建一个网站。如果没有设置 folder ,Hexo 默认在目前的文件夹建立网站。

new

1
$ hexo new [layout] <title>

新建一篇文章。如果没有设置 layout 的话,默认使用 _config.yml 中的 default_layout 参数代替。如果标题包含空格的话,请使用引号括起来。

generate

1
$ hexo generate

生成静态文件。

选项 描述
-d, --deploy 文件生成后立即部署网站
-w, --watch 监视文件变动

该命令可以简写为

1
$ hexo g

publish

1
$ hexo publish [layout] <filename>

发表草稿。

server

1
$ hexo server

启动服务器。默认情况下,访问网址为: http://localhost:4000/

选项 描述
-p, --port 重设端口
-s, --static 只使用静态文件
-l, --log 启动日记记录,使用覆盖记录格式

deploy

1
$ hexo deploy

部署网站。

参数 描述
-g, --generate 部署之前预先生成静态文件

该命令可以简写为:

1
$ hexo d

render

1
$ hexo render <file1> [file2] ...

渲染文件。

参数 描述
-o, --output 设置输出路径

migrate

1
$ hexo migrate <type>

从其他博客系统 迁移内容

clean

1
$ hexo clean

清除缓存文件 (db.json) 和已生成的静态文件 (public)。

在某些情况(尤其是更换主题后),如果发现您对站点的更改无论如何也不生效,您可能需要运行该命令。

list

1
$ hexo list <type>

列出网站资料。

version

1
$ hexo version

显示 Hexo 版本。

选项

安全模式

1
$ hexo --safe

在安全模式下,不会载入插件和脚本。当您在安装新插件遭遇问题时,可以尝试以安全模式重新执行。

调试模式

1
$ hexo --debug

在终端中显示调试信息并记录到 debug.log。当您碰到问题时,可以尝试用调试模式重新执行一次,并 提交调试信息到 GitHub

简洁模式

1
$ hexo --silent

隐藏终端信息。

自定义配置文件的路径

1
$ hexo --config custom.yml

自定义配置文件的路径,执行后将不再使用 _config.yml

显示草稿

1
$ hexo --draft

显示 source/_drafts 文件夹中的草稿文章。

自定义 CWD

1
$ hexo --cwd /path/to/cwd

自定义当前工作目录(Current working directory)的路径。

建站

安装 Hexo 完成后,请执行下列命令,Hexo 将会在指定文件夹中新建所需要的文件。

1
2
3
$ hexo init <folder>
$ cd <folder>
$ npm install

新建完成后,指定文件夹的目录如下:

1
2
3
4
5
6
7
8
.
├── _config.yml
├── package.json
├── scaffolds
├── source
| ├── _drafts
| └── _posts
└── themes

_config.yml

网站的 配置 信息,您可以在此配置大部分的参数。

package.json

应用程序的信息。EJS, StylusMarkdown renderer 已默认安装,您可以自由移除。

package.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"name": "hexo-site",
"version": "0.0.0",
"private": true,
"hexo": {
"version": ""
},
"dependencies": {
"hexo": "^3.0.0",
"hexo-generator-archive": "^0.1.0",
"hexo-generator-category": "^0.1.0",
"hexo-generator-index": "^0.1.0",
"hexo-generator-tag": "^0.1.0",
"hexo-renderer-ejs": "^0.1.0",
"hexo-renderer-stylus": "^0.2.0",
"hexo-renderer-marked": "^0.2.4",
"hexo-server": "^0.1.2"
}
}

scaffolds

模版 文件夹。当您新建文章时,Hexo 会根据 scaffold 来建立文件。

Hexo的模板是指在新建的markdown文件中默认填充的内容。例如,如果您修改scaffold/post.md中的Front-matter内容,那么每次新建一篇文章时都会包含这个修改。

source

资源文件夹是存放用户资源的地方。除 _posts 文件夹之外,开头命名为 _ (下划线)的文件 / 文件夹和隐藏的文件将会被忽略。Markdown 和 HTML 文件会被解析并放到 public 文件夹,而其他文件会被拷贝过去。

themes

主题 文件夹。Hexo 会根据主题来生成静态页面。

配置

您可以在 _config.yml 中修改大部份的配置。

网站

参数 描述
title 网站标题
subtitle 网站副标题
description 网站描述
author 您的名字
language 网站使用的语言
timezone 网站时区。Hexo 默认使用您电脑的时区。时区列表。比如说:America/New_York, Japan, 和 UTC

其中,description主要用于SEO,告诉搜索引擎一个关于您站点的简单描述,通常建议在其中包含您网站的关键词。author参数用于主题显示文章的作者。

网址

参数 描述 默认值
url 网址
root 网站根目录
permalink 文章的 永久链接 格式 :year/:month/:day/:title/
permalink_defaults 永久链接中各部分的默认值
网站存放在子目录

如果您的网站存放在子目录中,例如 http://yoursite.com/blog,则请将您的 url 设为 http://yoursite.com/blog 并把 root 设为 /blog/

目录

参数 描述 默认值
source_dir 资源文件夹,这个文件夹用来存放内容。 source
public_dir 公共文件夹,这个文件夹用于存放生成的站点文件。 public
tag_dir 标签文件夹 tags
archive_dir 归档文件夹 archives
category_dir 分类文件夹 categories
code_dir Include code 文件夹 downloads/code
i18n_dir 国际化(i18n)文件夹 :lang
skip_render 跳过指定文件的渲染,您可使用 glob 表达式来匹配路径。
提示

如果您刚刚开始接触Hexo,通常没有必要修改这一部分的值。

文章

参数 描述 默认值
new_post_name 新文章的文件名称 :title.md
default_layout 预设布局 post
auto_spacing 在中文和英文之间加入空格 false
titlecase 把标题转换为 title case false
external_link 在新标签中打开链接 true
filename_case 把文件名称转换为 (1) 小写或 (2) 大写 0
render_drafts 显示草稿 false
post_asset_folder 启动 Asset 文件夹 false
relative_link 把链接改为与根目录的相对位址 false
future 显示未来的文章 true
highlight 代码块的设置
相对地址

默认情况下,Hexo生成的超链接都是绝对地址。例如,如果您的网站域名为example.com,您有一篇文章名为hello,那么绝对链接可能像这样:http://example.com/hello.html,它是绝对于域名的。相对链接像这样:/hello.html,也就是说,无论用什么域名访问该站点,都没有关系,这在进行反向代理时可能用到。通常情况下,建议使用绝对地址。

分类 & 标签

参数 描述 默认值
default_category 默认分类 uncategorized
category_map 分类别名
tag_map 标签别名

日期 / 时间格式

Hexo 使用 Moment.js 来解析和显示时间。

参数 描述 默认值
date_format 日期格式 YYYY-MM-DD
time_format 时间格式 H:mm:ss

分页

参数 描述 默认值
per_page 每页显示的文章量 (0 = 关闭分页功能) 10
pagination_dir 分页目录 page

扩展

参数 描述
theme 当前主题名称。值为false时禁用主题
deploy 部署部分的设置

部署

Hexo 提供了快速方便的一键部署功能,让您只需一条命令就能将网站部署到服务器上。

1
$ hexo deploy

在开始之前,您必须先在 _config.yml 中修改参数,一个正确的部署配置中至少要有 type 参数,例如:

1
2
deploy:
type: git

您可同时使用多个 deployer,Hexo 会依照顺序执行每个 deployer。

1
2
3
4
5
deploy:
- type: git
repo:
- type: heroku
repo:
缩进

YAML依靠缩进来确定元素间的从属关系。因此,请确保每个deployer的缩进长度相同,并且使用空格缩进。

Git

安装 hexo-deployer-git

1
$ npm install hexo-deployer-git --save

修改配置。

1
2
3
4
5
deploy:
type: git
repo: <repository url>
branch: [branch]
message: [message]
参数 描述
repo 库(Repository)地址
branch 分支名称。如果您使用的是 GitHub 或 GitCafe 的话,程序会尝试自动检测。
message 自定义提交信息 (默认为 Site updated: {{ now('YYYY-MM-DD HH:mm:ss') }})

Heroku

安装 hexo-deployer-heroku

1
$ npm install hexo-deployer-heroku --save

修改配置。

1
2
3
4
deploy:
type: heroku
repo: <repository url>
message: [message]
参数 描述
repo Heroku 库(Repository)地址
message 自定提交信息 (默认为 Site updated: {{ now('YYYY-MM-DD HH:mm:ss') }})

Rsync

安装 hexo-deployer-rsync

1
$ npm install hexo-deployer-rsync --save

修改配置。

1
2
3
4
5
6
7
8
9
deploy:
type: rsync
host: <host>
user: <user>
root: <root>
port: [port]
delete: [true|false]
verbose: [true|false]
ignore_errors: [true|false]
参数 描述 默认值
host 远程主机的地址
user 使用者名称
root 远程主机的根目录
port 端口 22
delete 删除远程主机上的旧文件 true
verbose 显示调试信息 true
ignore_errors 忽略错误 false
rsync部署模块的工作方式

需要注意的是,要求您提供的实际上是一个能通过SSH登陆远程主机的Linux用户。Hexo会自动处理关于rsync使用的一切操作。因此,您需要在远程主机上为您的Hexo站点建立一个用户,并允许其通过SSH登陆。不过,这里的port,的确是指rsync监听的端口,请确保防火墙打开了该端口。

OpenShift

安装 hexo-deployer-openshift

1
$ npm install hexo-deployer-openshift --save

修改配置。

1
2
3
4
deploy:
type: openshift
repo: <repository url>
message: [message]
参数 描述
repo OpenShift 库(Repository)地址
message 自定提交信息 (默认为 Site updated: {{ now('YYYY-MM-DD HH:mm:ss') }})

FTPSync

安装 hexo-deployer-ftpsync

1
$ npm install hexo-deployer-ftpsync --save

修改配置。

1
2
3
4
5
6
7
8
9
10
deploy:
type: ftpsync
host: <host>
user: <user>
pass: <password>
remote: [remote]
port: [port]
ignore: [ignore]
connections: [connections]
verbose: [true|false]
参数 描述 默认值
host 远程主机的地址
user 使用者名称
pass 密码
remote 远程主机的根目录 /
port 端口 21
ignore 忽略的文件或目录
connections 使用的连接数 1
verbose 显示调试信息 false
FTP部署可能出现的问题

您可能需要预先通过其他方式将所有文件上传到远程主机中。否则初次使用ftpsync插件就可能出现报错。另外,由于FTP协议的特征,它每传送一个文件就需要一次握手,相对速度较慢。

其他方法

Hexo 生成的所有文件都放在 public 文件夹中,您可以将它们复制到您喜欢的地方。

变量

全局变量

变量 描述
site 网站变量
page 针对该页面的内容以及 front-matter 所设定的变量。
config 网站配置
theme 主题配置。继承自网站配置。
_ (单下划线) Lodash 函数库
path 当前页面的路径(不含根路径)
url 当前页面的完整网址
env 环境变量

网站变量

变量 描述
site.posts 所有文章
site.pages 所有分页
site.categories 所有分类
site.tags 所有标签

页面变量

页面(page)

变量 描述
page.title 页面标题
page.date 页面建立日期(Moment.js 对象)
page.updated 页面更新日期(Moment.js 对象)
page.comments 留言是否开启
page.layout 布局名称
page.content 页面的完整内容
page.excerpt 页面摘要
page.more 除了页面摘要的其余内容
page.source 页面原始路径
page.full_source 页面的完整原始路径
page.path 页面网址(不含根路径)。我们通常在主题中使用 url_for(page.path)
page.permalink 页面的完整网址
page.prev 上一个页面。如果此为第一个页面则为 null
page.next 下一个页面。如果此为最后一个页面则为 null
page.raw 文章的原始内容
page.photos 文章的照片(用于相簿)
page.link 文章的外部链接(用于链接文章)

文章 (post):page 布局类似,但是添加了下列变量。

Variable Description
page.published 如果该文章已发布则为True
page.categories 该文章的所有分类
page.tags 该文章的所有标签

首页(index)

变量 描述
page.per_page 每页显示的文章数量
page.total 总文章数
page.current 目前页数
page.current_url 目前分页的网址
page.posts 本页文章
page.prev 上一页的页数。如果此页是第一页的话则为 0
page.prev_link 上一页的网址。如果此页是第一页的话则为 ''
page.next 下一页的页数。如果此页是最后一页的话则为 0
page.next_link 下一页的网址。如果此页是最后一页的话则为 ''
page.path 当前页面的路径(不含根目录)。我们通常在主题中使用 url_for(page.path)

归档 (archive):与 index 布局相同,但新增以下变量。

变量 描述
page.archive 等于 true
page.year 年份归档 (4位)
page.month 月份归档 (没有前导零的2位数)

分类 (category):与 index 布局相同,但新增以下变量。

变量 描述
page.category 分类名称

标签 (tag):与 index 布局相同,但新增以下变量。

变量 描述
page.tag 标签名称

辅助函数(Helpers)

辅助函数帮助您在模版中快速插入内容。辅助函数不能在源文件中使用。

网址

url_for

在路径前加上根路径,从 Hexo 2.7 开始您应该使用此函数而不是 config.root + path

1
<%- url_for(path) %>

relative_url

取得与 from 相对的 to 路径。

1
<%- relative_url(from, to) %>

gravatar

插入 Gravatar 图片。
如果你不指定 options 参数,将会应用默认参数。否则,你可以将其设置为一个数字,这个数字将会作为 Gravatar 的大小参数。最后,如果你设置它一个对象,它将会被转换为 Gravatar 的一个查询字符串参数。

1
<%- gravatar(email, [options]);

示例:

1
2
3
4
5
6
7
8
<%- gravatar('a@abc.com') %>
// http://www.gravatar.com/avatar/b9b00e66c6b8a70f88c73cb6bdb06787

<%- gravatar('a@abc.com', 40) %>
// http://www.gravatar.com/avatar/b9b00e66c6b8a70f88c73cb6bdb06787?s=40

<%- gravatar('a@abc.com' {s: 40, d: 'http://example.com/image.png'}) %>
// http://www.gravatar.com/avatar/b9b00e66c6b8a70f88c73cb6bdb06787?s=40&d=http%3A%2F%2Fexample.com%2Fimage.png

HTML 标签

css

载入 CSS 文件。path 可以是数组或字符串,如果 path 开头不是 / 或任何协议,则会自动加上根路径;如果后面没有加上 .css 扩展名的话,也会自动加上。

1
<%- css(path, ...) %>

示例:

1
2
3
4
5
6
<%- css('style.css') %>
// <link rel="stylesheet" href="/style.css" type="text/css">

<%- css(['style.css', 'screen.css']) %>
// <link rel="stylesheet" href="/style.css" type="text/css">
// <link rel="stylesheet" href="/screen.css" type="text/css">

js

载入 JavaScript 文件。path 可以是数组或字符串,如果 path 开头不是 / 或任何协议,则会自动加上根路径;如果后面没有加上 .js 扩展名的话,也会自动加上。

1
<%- js(path, ...) %>

示例:

1
2
3
4
5
6
<%- js('script.js') %>
// <script type="text/javascript" src="/script.js"></script>

<%- js(['script.js', 'gallery.js']) %>
// <script type="text/javascript" src="/script.js"></script>
// <script type="text/javascript" src="/gallery.js"></script>

插入链接。

1
<%- link_to(path, [text], [options]) %>
参数 描述 默认值
external 在新视窗打开链接 false
class Class 名称
id ID

示例:

1
2
3
4
5
6
7
8
<%- link_to('http://www.google.com') %>
// <a href="http://www.google.com" title="http://www.google.com">http://www.google.com</a>

<%- link_to('http://www.google.com', 'Google') %>
// <a href="http://www.google.com" title="Google">Google</a>

<%- link_to('http://www.google.com', 'Google', {external: true}) %>
// <a href="http://www.google.com" title="Google" target="_blank" rel="external">Google</a>

mail_to

插入电子邮箱链接。

1
<%- mail_to(path, [text], [options]) %>
参数 描述
class Class 名称
id ID
subject 邮件主题
cc 抄送(CC)
bcc 密送(BCC)
body 邮件内容

示例:

1
2
3
4
5
<%- mail_to('a@abc.com') %>
// <a href="mailto:a@abc.com" title="a@abc.com">a@abc.com</a>

<%- mail_to('a@abc.com', 'Email') %>
// <a href="mailto:a@abc.com" title="Email">Email</a>

image_tag

插入图片。

1
<%- image_tag(path, [options]) %>
参数 描述
alt 图片的替代文字
class Class 名称
id ID
width 图片宽度
height 图片高度

favicon_tag

插入 favicon。

1
<%- favicon_tag(path) %>

feed_tag

插入 feed 链接。

1
<%- feed_tag(path, [options]) %>
参数 描述 默认值
title Feed 标题
type Feed 类型 atom

条件函数

is_current

检查 path 是否符合目前页面的网址。开启 strict 选项启用严格比对。

1
<%- is_current(path, [strict]) %>

is_home

检查目前是否为首页。

1
<%- is_home() %>

is_post

检查目前是否为文章。

1
<%- is_post() %>

is_archive

检查目前是否为存档页面。

1
<%- is_archive() %>

is_year

检查目前是否为年度归档页面。

1
<%- is_year() %>

is_month

检查目前是否为月度归档页面。

1
<%- is_month() %>

is_category

检查目前是否为分类归档页面。
如果给定一个字符串作为参数,将会检查目前是否为指定分类。

1
2
<%- is_category() %>
<%- is_category('hobby') %>

is_tag

检查目前是否为标签归档页面。
如果给定一个字符串作为参数,将会检查目前是否为指定标签。

1
2
<%- is_tag() %>
<%- is_tag('hobby') %>

字符串处理

trim

清除字符串开头和结尾的空格。

1
<%- trim(string) %>

strip_html

清除字符串中的 HTML 标签。

1
<%- strip_html(string) %>

示例:

1
2
<%- strip_html('It's not <b>important</b> anymore!') %>
// It's not important anymore!

titlecase

把字符串转换为正确的 Title case。

1
<%- titlecase(string) %>

示例:

1
2
<%- titlecase('this is an apple') %>
# This is an Apple

markdown

使用 Markdown 解析字符串。

1
<%- markdown(str) %>

示例:

1
2
<%- markdown('make me **strong**') %>
// make me <strong>strong</strong>

render

解析字符串。

1
<%- render(str, engine, [options]) %>

word_wrap

使每行的字符串长度不超过 lengthlength 预设为 80。

1
<%- word_wrap(str, [length]) %>

示例:

1
2
<%- word_wrap('Once upon a time', 8) %>
// Once upon\n a time

truncate

移除超过 length 长度的字符串。

1
<%- truncate(text, length) %>

示例:

1
2
3
4
5
6
7
8
<%- truncate('Once upon a time in a world far far away', {length: 17}) %>
// Once upon a ti...

<%- truncate('Once upon a time in a world far far away', {length: 17, separator: ' '}) %>
// Once upon a...

<%- truncate('And they found that many people were sleeping better.', {length: 25, omission: '... (continued)'}) %>
// And they f... (continued)

模板

partial

载入其他模板文件,您可在 locals 设定区域变量。

1
<%- partial(layout, [locals], [options]) %>
参数 描述 默认值
cache 缓存(使用 Fragment cache) false
only 限制局部变量。在模板中只能使用 locals 中设定的变量。 false

fragment_cache

局部缓存。它储存局部内容,下次使用时就能直接使用缓存。

1
<%- fragment_cache(id, fn);

示例:

1
2
3
<%- fragment_cache('header', function(){
return '<header></header>';
}) %>

日期与时间

date

插入格式化的日期。date 可以是 UNIX 时间、ISO 字符串、Date 对象或 Moment.js 对象。format 默认为 date_format 配置信息。

1
<%- date(date, [format]) %>

示例:

1
2
3
4
5
<%- date(Date.now()) %>
// 2013-01-01

<%- date(Date.now(), 'YYYY/M/D') %>
// Jan 1 2013

date_xml

插入 XML 格式的日期。date 可以是 UNIX 时间、ISO 字符串、Date 对象或 Moment.js 对象。

1
<%- date_xml(date) %>

示例:

1
2
<%- date_xml(Date.now()) %>
// 2013-01-01T00:00:00.000Z

time

插入格式化的时间。date 可以是 UNIX 时间、ISO 字符串、Date 对象或 Moment.js 对象。format 默认为 time_format 配置信息。

1
<%- time(date, [format]) %>

示例:

1
2
3
4
5
<%- time(Date.now()) %>
// 13:05:12

<%- time(Date.now(), 'h:mm:ss a') %>
// 1:05:12 pm

full_date

插入格式化的日期和时间。date 可以是 UNIX 时间、ISO 字符串、Date 对象或 Moment.js 对象。format 默认为 date_format + time_format

1
<%- full_date(date, [format]) %>

示例:

1
2
3
4
5
<%- full_date(new Date()) %>
// Jan 1, 2013 0:00:00

<%- full_date(new Date(), 'dddd, MMMM Do YYYY, h:mm:ss a') %>
// Tuesday, January 1st 2013, 12:00:00 am

moment

Moment.js 函数库。

列表

list_categories

插入分类列表。

1
<%- list_categories([options]) %>
参数 描述 默认值
orderby 分类排列方式 name
order 分类排列顺序。1, asc 升序;-1, desc 降序。 1
show_count 显示每个分类的文章总数 true
style 分类列表的显示方式。使用 list 以无序列表(unordered list)方式显示。 list
separator 分类间的分隔符号。只有在 style 不是 list 时有用。 ,
depth 要显示的分类层级。0 显示所有层级的分类;-10 很类似,但是显示不分层级;1 只显示第一层的分类。 0
class 分类列表的 class 名称。 category
transform 改变分类名称显示方法的函数

list_tags

插入标签列表。

1
<%- list_tags([options]) %>
选项 描述 预设值
orderby 标签排列方式 name
order 标签排列顺序。1, asc 升序;-1, desc 降序。 1
show_count 显示每个标签的文章总数 true
style 标签列表的显示方式。使用 list 以无序列表(unordered list)方式显示。 list
separator 标签间的分隔符号。只有在 style 不是 list 时有用。 ,
class 标签列表的 class 名称。 tag
transform 改变标签名称显示方法的函数
amount 要显示的标签数量(0 = 无限制) 0

list_archives

插入归档列表。

1
<%- list_archives([options]) %>
参数 描述 默认值
type 类型。此设定可为 yearlymonthly monthly
order 排列顺序。1, asc 升序;-1, desc 降序。 1
show_count 显示每个归档的文章总数 true
format 日期格式 MMMM YYYY
style 归档列表的显示方式。使用 list 以无序列表(unordered list)方式显示。 list
separator 归档间的分隔符号。只有在 style 不是 list 时有用。 ,
class 归档列表的 class 名称。 archive
transform 改变归档名称显示方法的函数

list_posts

插入文章列表。

1
<%- list_posts([options]) %>
参数 描述 默认值
orderby 文章排列方式 date
order 文章排列顺序。1, asc 升序;-1, desc 降序。 -1
style 文章列表的显示方式。使用 list 以无序列表(unordered list)方式显示。 list
separator 文章间的分隔符号。只有在 style 不是 list 时有用。 ,
class 文章列表的 class 名称。 post
amount 要显示的文章数量(0 = 无限制) 6
transform 改变文章名称显示方法的函数

tagcloud

插入标签云。

1
<%- tagcloud([tags], [options]) %>
参数 描述 默认值
min_font 最小字体尺寸 10
max_font 最大字体尺寸 20
unit 字体尺寸的单位 px
amount 标签总量 40
orderby 标签排列方式 name
order 标签排列顺序。1, sac 升序;-1, desc 降序 1
color 使用颜色 false
start_color 开始的颜色。您可使用十六进位值(#b700ff),rgba(rgba(183, 0, 255, 1)),hsla(hsla(283, 100%, 50%, 1))或 颜色关键字。此变量仅在 color 参数开启时才有用。
end_color 结束的颜色。您可使用十六进位值(#b700ff),rgba(rgba(183, 0, 255, 1)),hsla(hsla(283, 100%, 50%, 1))或 颜色关键字。此变量仅在 color 参数开启时才有用。

其他

paginator

插入分页链接。

1
<%- paginator(options) %>
参数 描述 默认值
base 基础网址 /
format 网址格式 page/%d/
total 分页总数 1
current 目前页数 0
prev_text 上一页链接的文字。仅在 prev_next 设定开启时才有用。 Prev
next_text 下一页链接的文字。仅在 prev_next 设定开启时才有用。 Next
space 空白文字
prev_next 显示上一页和下一页的链接 true
end_size 显示于两侧的页数 1
mid_size 显示于中间的页数 2
show_all 显示所有页数。如果开启此参数的话,end_sizemid_size 就没用了。 false

search_form

插入 Google 搜索框。

1
<%- search_form(options) %>
参数 描述 默认值
class 表单的 class name search-form
text 搜索提示文字 Search
button 显示搜索按钮。此参数可为布尔值(boolean)或字符串,当设定是字符串的时候,即为搜索按钮的文字。 false

number_format

格式化数字。

1
<%- number_format(number, [options]) %>
参数 描述 默认值
precision 数字精度。此选项可为 false 或非负整数。 false
delimiter 千位数分隔符号 ,
separator 整数和小数之间的分隔符号 .

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<%- number_format(12345.67, {precision: 1}) %>
// 12,345.68

<%- number_format(12345.67, {precision: 4}) %>
// 12,345.6700

<%- number_format(12345.67, {precision: 0}) %>
// 12,345

<%- number_format(12345.67, {delimiter: ''}) %>
// 12345.67

<%- number_format(12345.67, {separator: '/'}) %>
// 12,345/67

open_graph

插入 open graph 资源。

1
<%- open_graph([options]) %>
参数 描述 默认值
title 页面标题 (og:title) page.title
type 页面类型 (og:type) blog
url 页面网址 (og:url) url
image 页面图片 (og:image) 内容中的图片
site_name 网站名称 (og:site_name) config.title
description 页面描述 (og:desription) 内容摘要或前 200 字
twitter_card Twitter 卡片类型 (twitter:card) summary
twitter_id Twitter ID (twitter:creator)
twitter_site Twitter 网站 (twitter:site)
google_plus Google+ 个人资料链接
fb_admins Facebook 管理者 ID
fb_app_id Facebook 应用程序 ID

toc

解析内容中的标题标签 (h1~h6) 并插入目录。

1
<%- toc(str, [options]) %>
参数 描述 默认值
class Class 名称 toc
list_number 显示编号 true

示例:

1
<%- toc(page.content) %>

本文链接: https://netlover.cn/2018/08/01/hexo-begin.html