1.babel的编译流程
1.词法分析
将源代码拆分成Token
例如源代码为 let x = 5 + 3;
Token(type="keyword", value="let")
Token(type="identifier", value="x")
Token(type="operator", value="=")
Token(type="number", value="5")
Token(type="operator", value="+")
Token(type="number", value="3")
Token(type="semicolon", value=";")
2.语法分析
将Token组合成抽象语法树
let ast = {
type: "VariableDeclaration",
declarations: [{
type: "VariableDeclarator",
id: {
type: "Identifier",
name: "x"
},
init: {
type: "BinaryExpression",
operator: "+",
left: {
type: "Literal",
value: 5
},
right: {
type: "Literal",
value: 3
}
}
}],
kind: "let"
};
2.pnpm的优势
参考资料:blog.csdn.net/weixin_4244…
npm和pnpm对比
假设我们的项目A依赖于两个库:library1和library2。它们都依赖于一个名为common-library的包,版本为1.0.0。
使用npm的话,目录结构如下:
project-a/
│
├── node_modules/
│ ├── common-library/
│ │ └── ... (common-library 的内容)
│ │
│ ├── library1/
│ │ └── ... (library1 的内容)
│ │
│ └── library2/
│ └── ... (library2 的内容)
│
└── ... (项目A的其他文件和文件夹)
使用pnpm的话目录结构如下:
project-a/
│
├── node_modules/
│ ├── .pnpm/
│ │ └── common-library@1.0.0/
│ │ └── ... (common-library 的内容)
│ │
│ ├── library1/
│ │ ├── node_modules/
│ │ │ └── common-library -> ../../../.pnpm/common-library@1.0.0 (硬链接)
│ │ └── ... (library1 的内容)
│ │
│ └── library2/
│ ├── node_modules/
│ │ └── common-library -> ../../../.pnpm/common-library@1.0.0 (硬链接)
│ └── ... (library2 的内容)
│
└── ... (项目A的其他文件和文件夹)
在此例中,都没有重复安装common-library,两种方式都很优秀。但npm3在其他情况下会有问题:
1.幽灵依赖
假设还有一个library3文件,在它的package.json中没有注册common-library,它的代码中使用import common-library也不会报错。为什么?因为common-library已经被打平到node_modules中了。但是如果使用pnpm就不存在幽灵依赖,library3直接报错。
project-a/
│
├── node_modules/
│ ├── .pnpm/
│ │ └── common-library@1.0.0/
│ │ └── ... (common-library 的内容)
│ │
│ ├── library1/
│ │ ├── node_modules/
│ │ │ └── common-library -> ../../../.pnpm/common-library@1.0.0 (硬链接)
│ │ └── ... (library1 的内容)
│ │
│ ├── library2/
│ │ ├── node_modules/
│ │ │ └── common-library -> ../../../.pnpm/common-library@1.0.0 (硬链接)
│ │ └── ... (library2 的内容)
│ │
│ └── library3/
│ └── ... (library3 的内容)
│
└── ... (项目A的其他文件和文件夹)
2.文件结构的不确定性
其他条件如上不变,假设library 1 和 library 2依赖的common-library版本不同,会发生什么?最终node_modules的结构可能会出现以下2种
project-a/
│
├── node_modules/
│ ├── common-library@1.1.0/
│ │ └── ... (common-library 1.1.0 的内容)
│ │
│ ├── library1/
│ │ └── ... (library1 的内容)
│ │
│ └── library2/
│ ├── node_modules/
│ │ └── common-library@1.0.0/
│ │ └── ... (common-library 1.0.0 的内容)
│ └── ... (library2 的内容)
│
└── ... (项目A的其他文件和文件夹)
project-a/
│
├── node_modules/
│ ├── common-library@1.0.0/
│ │ └── ... (common-library 1.0.0 的内容)
│ │
│ ├── library1/
│ │ ├── node_modules/
│ │ │ └── common-library@1.1.0/
│ │ │ └── ... (common-library 1.1.0 的内容)
│ │ └── ... (library1 的内容)
│ │
│ └── library2/
│ └── ... (library2 的内容)
│
└── ... (项目A的其他文件和文件夹)
如果使用pnpm就不会出现这种情况,只会出现以下一种结构:
project-a/
│
├── node_modules/
│ ├── .pnpm/
│ │ ├── common-library@1.1.0/
│ │ │ └── ... (common-library 1.1.0 的内容)
│ │ │
│ │ └── common-library@1.0.0/
│ │ └── ... (common-library 1.0.0 的内容)
│ │
│ ├── library1/
│ │ ├── node_modules/
│ │ │ └── common-library -> ../../../.pnpm/common-library@1.1.0 (硬链接)
│ │ └── ... (library1 的内容)
│ │
│ └── library2/
│ ├── node_modules/
│ │ └── common-library -> ../../../.pnpm/common-library@1.0.0 (硬链接)
│ └── ... (library2 的内容)
│
└── ... (项目A的其他文件和文件夹)
3.硬连接与软连接
硬链接
每一个硬链接是一个指针,不管产生多少个硬链接,他们指向的都是磁盘内同一份文件数据。当我们删除文件的时候,删除的其实是指针。如果没有指针指向该文件数据,它今后可能会被其他文件覆盖。
软连接
它类似于快捷方式,是指向指针的指针。如果我删除快捷方式,对源文件没有任何影响。