杂项(pnpm,babel)

67 阅读3分钟

1.babel的编译流程

image.png

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依赖于两个库:library1library2。它们都依赖于一个名为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 1library 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.硬连接与软连接

硬链接

每一个硬链接是一个指针,不管产生多少个硬链接,他们指向的都是磁盘内同一份文件数据。当我们删除文件的时候,删除的其实是指针。如果没有指针指向该文件数据,它今后可能会被其他文件覆盖。

image.png

软连接

它类似于快捷方式,是指向指针的指针。如果我删除快捷方式,对源文件没有任何影响。

image.png