21 个不稳定版本 (8 个破坏性更新)
0.9.0 | 2024年7月11日 |
---|---|
0.7.2 | 2024年7月9日 |
0.6.0 | 2023年4月1日 |
0.5.4 | 2023年3月25日 |
69 在 压缩
1,365 每月下载量
用于 rspack_resolver
1MB
19K SLoC
pnp-rs
该软件包实现了 Yarn Plug'n'Play 的 解析算法,以便在基于 Rust 的工具中轻松重用。它还包括允许透明地从 zip 存档中读取文件的实用工具。
安装
cargo add pnp
解析
fn example() {
let manifest
= load_pnp_manifest(".pnp.cjs").unwrap();
let host = ResolutionHost {
find_pnp_manifest: Box::new(move |_| Ok(Some(manifest.clone()))),
..Default::default()
};
let config = ResolutionConfig {
host,
..Default::default()
};
let resolution = resolve_to_unqualified(
"lodash/cloneDeep",
std::path::PathBuf::from("/path/to/index.js"),
&config,
);
match resolution {
Ok(Resolution::Resolved(path, subpath)) => {
// path = "/path/to/lodash.zip"
// subpath = "cloneDeep"
},
Ok(Resolution::Skipped) => {
// This is returned when the PnP resolver decides that it shouldn't
// handle the resolution for this particular specifier. In that case,
// the specifier should be forwarded to the default resolver.
},
Err(err) => {
// An error happened during the resolution. Falling back to the default
// resolver isn't recommended.
},
};
}
文件系统工具
虽然 PnP 仅处理解析,而不是文件系统,但 Yarn 生成的文件映射依赖于虚拟文件系统层,原因如下:
-
虚拟包,需要具有不同路径的同包来考虑不同的依赖集(这仅发生在列出依赖项的包中)
-
Zip 存储空间,Yarn 使用它,因此安装的文件无需从存档中解包,从而实现更快的安装和更少的缓存损坏风险。
为了更容易地处理这些虚拟文件系统,pnp
软件包还包括一个名为 VPath
的枚举,允许您解析虚拟路径,以及一组 zip 操作实用工具(默认为 open_zip_via_read
,如果启用了 mmap
功能,则为 open_zip_via_mmap
)。
use pnp::fs::{VPath, open_zip_via_read};
fn read_file(p: PathBuf) -> std::io::Result<String> {
match VPath::from(&p).unwrap() {
// The path was virtual and stored within a zip file; we need to read from the zip file
// Note that this opens the zip file every time, which is expensive; we'll see how to optimize that
VPath::Zip(info) => {
open_zip_via_read(info.physical_base_path()).unwrap().read_to_string(&zip_path)
},
// The path was virtual but not a zip file; we just need to read from the provided location
VPath::Virtual(info) => {
std::fs::read_to_string(info.physical_base_path())
},
// Nothing special to do, it's a regular path
VPath::Native(p) => {
std::fs::read_to_string(&p)
},
}
}
缓存重用
为每次单个文件访问打开和丢弃 zip 存档将会非常昂贵。为了避免这种情况,pnp-rs
提供了一个名为 LruZipCache
的辅助类,允许您抽象化 zip 的打开和关闭,并且只保留最近使用的存档打开。
use pnp::fs::{VPath, LruZipCache, open_zip_via_read};
const ZIP_CACHE: Lazy<LruZipCache<Vec<u8>>> = Lazy::new(|| {
// It'll keep the last 50 zip archives open
LruZipCache::new(50, open_zip_via_read_p)
});
fn read_file(p: PathBuf) -> std::io::Result<String> {
match VPath::from(&p).unwrap() {
// The path was virtual and stored within a zip file; we need to read from the zip file
VPath::Zip(info) => {
ZIP_CACHE.read_to_string(info.physical_base_path(), &zip_path)
},
// The path was virtual but not a zip file; we just need to read from the provided location
VPath::Virtual(info) => {
std::fs::read_to_string(info.physical_base_path())
},
// Nothing special to do, it's a regular path
VPath::Native(p) => {
std::fs::read_to_string(&p)
},
}
}
依赖项
~4–35MB
~476K SLoC