pnpm 问题记录

2021-12-19 23:46:38 +08:00
 kaiduo

hi, all ~ 分享一个批量项目迁移到 pnpm 过程中遇到的问题与解决办法,希望对大家有所帮助 ~

原文链接: https://github.com/xiaoxiaojx/blog/issues/23

背景

2022 前端技术领域会有哪些新的变化? 话题中我曾回答到,越来越多的项目会开始使用 pnpm 。

这是我正在推动的一件事,使用 pnpm 替换现在的 yarn 。无论是 csr 、ssr 、monorepos 等类型项目都正在进行中,有近 10 个项目已经迁移完成。 当时 yarn 的 pnp 特性出来的时候,观望过一阵子,没有大面积火起来,遂放弃 ... 现在是注意到 vite 、modernjs 等使用了 pnpm ,其设计理念与 node_modules 的目录结构也能让业务更加快速安全,所以决定开始全面使用 pnpm 。

下面记录与分享一下最近使用 pnpm 遇到的问题与解决的过程~

✅ 已解决的问题

jest 单测运行失败

// Copyright 2004-present Facebook. All Rights Reserved.

'use strict';

jest.useFakeTimers();

describe('timerGame', () => {
  beforeEach(() => {
    jest.spyOn(global, 'setTimeout');
  });
  it('waits 1 second before ending the game', () => {
    const timerGame = require('../timerGame');
    timerGame();

    expect(setTimeout).toBeCalledTimes(1);
    expect(setTimeout).toBeCalledWith(expect.any(Function), 1000);
  });

  it('calls the callback after 1 second via runAllTimers', () => {
    const timerGame = require('../timerGame');
    const callback = jest.fn();

    timerGame(callback);

    // At this point in time, the callback should not have been called yet
    expect(callback).not.toBeCalled();

    // Fast-forward until all timers have been executed
    jest.runAllTimers();

    // Now our callback should have been called!
    expect(callback).toBeCalled();
    expect(callback).toBeCalledTimes(1);
  });
});

node-gyp rebuild failures

# pnpm i better-sqlite3
Packages: +11
+++++++++++
Resolving: total 11, reused 11, downloaded 0, done
node_modules/.pnpm/registry.npmjs.org/integer/2.1.0/node_modules/integer: Running install script, done in 2s
node_modules/.pnpm/registry.npmjs.org/better-sqlite3/5.4.3/node_modules/better-sqlite3: Running install script, failed in 393ms
.../5.4.3/node_modules/better-sqlite3 install$ node-gyp rebuild
│ gyp info it worked if it ends with ok
│ gyp info using node-gyp@6.0.0
│ gyp info using node@12.13.0 | linux | x64
│ gyp info find Python using Python version 3.6.8 found at "/usr/bin/python3"
│ gyp info spawn /usr/bin/python3
│ gyp info spawn args [
│ gyp info spawn args   '/usr/lib/node_modules/pnpm/lib/node_modules/node-gyp/gyp/gyp_main.py',
│ gyp info spawn args   'binding.gyp',
│ gyp info spawn args   '-f',
│ gyp info spawn args   'make',
│ gyp info spawn args   '-I',
│ gyp info spawn args   '/root/2/node_modules/.pnpm/registry.npmjs.org/better-sqlite3/5.4.3/node_modules/better-sqlite3/build/config.gypi',
│ gyp info spawn args   '-I',
│ gyp info spawn args   '/usr/lib/node_modules/pnpm/lib/node_modules/node-gyp/addon.gypi',
│ gyp info spawn args   '-I',
│ gyp info spawn args   '/root/.cache/node-gyp/12.13.0/include/node/common.gypi',
│ gyp info spawn args   '-Dlibrary=shared_library',
│ gyp info spawn args   '-Dvisibility=default',
│ gyp info spawn args   '-Dnode_root_dir=/root/.cache/node-gyp/12.13.0',
│ gyp info spawn args   '-Dnode_gyp_dir=/usr/lib/node_modules/pnpm/lib/node_modules/node-gyp',
│ gyp info spawn args   '-Dnode_lib_file=/root/.cache/node-gyp/12.13.0/<(target_arch)/node.lib',
│ gyp info spawn args   '-Dmodule_root_dir=/root/2/node_modules/.pnpm/registry.npmjs.org/better-sqlite3/5.4.3/node_modules/better-sqlite3',
│ gyp info spawn args   '-Dnode_engine=v8',
│ gyp info spawn args   '--depth=.',
│ gyp info spawn args   '--no-parallel',
│ gyp info spawn args   '--generator-output',
│ gyp info spawn args   'build',
│ gyp info spawn args   '-Goutput_dir=.'
│ gyp info spawn args ]
│ Traceback (most recent call last):
│   File "/usr/lib/node_modules/pnpm/lib/node_modules/node-gyp/gyp/gyp_main.py", line 50, in <module>
│     sys.exit(gyp.script_main())
│   File "/usr/lib/node_modules/pnpm/lib/node_modules/node-gyp/gyp/pylib/gyp/__init__.py", line 554, in script_main
│     return main(sys.argv[1:])
│   File "/usr/lib/node_modules/pnpm/lib/node_modules/node-gyp/gyp/pylib/gyp/__init__.py", line 547, in main
│     return gyp_main(args)
│   File "/usr/lib/node_modules/pnpm/lib/node_modules/node-gyp/gyp/pylib/gyp/__init__.py", line 532, in gyp_main
│     generator.GenerateOutput(flat_list, targets, data, params)
│   File "/usr/lib/node_modules/pnpm/lib/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py", line 2215, in GenerateOutput
│     part_of_all=qualified_target in needed_targets)
│   File "/usr/lib/node_modules/pnpm/lib/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py", line 794, in Write
│     extra_mac_bundle_resources, part_of_all)
│   File "/usr/lib/node_modules/pnpm/lib/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py", line 978, in WriteActions
│     part_of_all=part_of_all, command=name)
│   File "/usr/lib/node_modules/pnpm/lib/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py", line 1724, in WriteDoCmd
│     force = True)
│   File "/usr/lib/node_modules/pnpm/lib/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py", line 1779, in WriteMakeRule
│     cmddigest = hashlib.sha1(command if command else self.target).hexdigest()
│ TypeError: Unicode-objects must be encoded before hashing
│ gyp ERR! configure error
│ gyp ERR! stack Error: `gyp` failed with exit code: 1
│ gyp ERR! stack     at ChildProcess.onCpExit (/usr/lib/node_modules/pnpm/lib/node_modules/node-gyp/lib/configure.js:351:16)
│ gyp ERR! stack     at ChildProcess.emit (events.js:210:5)
│ gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:272:12)
│ gyp ERR! System Linux 4.15.0-33-generic
│ gyp ERR! command "/usr/bin/node" "/usr/lib/node_modules/pnpm/lib/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
│ gyp ERR! cwd /root/2/node_modules/.pnpm/registry.npmjs.org/better-sqlite3/5.4.3/node_modules/better-sqlite3
│ gyp ERR! node -v v12.13.0
│ gyp ERR! node-gyp -v v6.0.0
│ gyp ERR! not ok
└─ Failed in 393ms
 ERROR  Command failed with exit code 1.

同一个版本的包有两份副本

// .pnpmfile.cjs

function readPackage(pkg, context) {
  if (pkg.name && pkg.peerDependencies) {
    // https://pnpm.io/zh/how-peers-are-resolved
    pkg.peerDependencies = {}
  }

  return pkg
}

module.exports = {
  hooks: {
    readPackage,
  },
}

only-allow 命令影响到了业务项目

{
    "scripts": {
        "preinstall": "npx only-allow pnpm"
    }
}

❌ 未解决的问题

pnpm add 与 pnpm i 命令不会去重

cypress e2e 测试运行失败

1809 次点击
所在节点    Node.js
4 条回复
Terry05
2021-12-20 12:53:01 +08:00
也正在逐步使用 pnpm 中
shunia
2021-12-20 14:53:41 +08:00
强👍
除了测试的问题其他问题我基本都有遇到,多版本和去重的问题因为项目小没有实质影响无视了,其他的 google 一下也解决掉了。
只能说 pnpm 带来的好处确实很明显,降低心智负担,提升效率。但是当前确实也有不少 bug ,所幸他们的迭代速度也非常快,基本没几天就在命令行里提示新版本了。
kaiduo
2021-12-21 00:03:58 +08:00
@Terry05 快速且安全 ~
kaiduo
2021-12-21 00:04:18 +08:00
@shunia 是的,看来都是感同身受 ~

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/823196

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX