Skip to main content
Version: 22.9.0

贡献

¥Contributing

首先感谢你对 Puppeteer 的关注!我们很乐意接受你的补丁和贡献!

¥First of all, thank you for your interest in Puppeteer! We'd love to accept your patches and contributions!

贡献者许可协议

¥Contributor License Agreement

对此项目的贡献必须附有贡献者许可协议。你(或你的雇主)保留你贡献的版权,这只是允许我们使用和重新分发你的贡献作为项目的一部分。前往 <https://cla.developers.google.com/> 查看你当前存档的协议或签署新协议。

¥Contributions to this project must be accompanied by a Contributor License Agreement. You (or your employer) retain the copyright to your contribution, this simply gives us permission to use and redistribute your contributions as part of the project. Head over to <https://cla.developers.google.com/> to see your current agreements on file or to sign a new one.

你通常只需要提交一次 CLA,因此如果你已经提交了一份 CLA(即使是针对不同的项目),你可能不需要再次提交。

¥You generally only need to submit a CLA once, so if you've already submitted one (even if it was for a different project), you probably don't need to do it again.

新手入门

¥Getting started

  1. 克隆这个存储库

    ¥Clone this repository

    git clone https://github.com/puppeteer/puppeteer
    cd puppeteer

    或者

    ¥or

    Open in GitHub Codespaces

  2. 安装依赖

    ¥Install the dependencies

    npm install
    # Or to download Firefox by default
    PUPPETEER_PRODUCT=firefox npm install
  3. 构建所有包

    ¥Build all packages

    npm run build
  4. 运行所有测试

    ¥Run all tests

    npm test

构建单个包

¥Building a single package

要构建单个包,你可以运行:

¥To build a single package, you can run:

npm run build --workspace <package> # e.g. puppeteer

这将自动构建所有依赖包,因此指定单个包就足够了。这一切都是可能的,因为 wireit 的行为与 GNU 使 类似。

¥This will build all dependent packages automatically, so specifying a single package is sufficient. This is all possible due to wireit which behaves similar to GNU Make.

监视模式

¥Watch mode

要持续构建包,你可以运行:

¥To continuously build a package, you can run:

npm run build --watch --workspace <package> # e.g. puppeteer

你必须只指定一个包来观察,否则事情将无法按预期工作如上所述,因为 wireit,当发生更改时,所有依赖都将被构建或重建(如果需要)。

¥You have to only specify a single package to watch else things will not work as expected As stated above because of wireit when a change happens all dependencies will be build or rebuild (if needed).

删除旧的工件

¥Removing stale artifacts

某些生成的工件(例如 packages/puppeteer-core/src/types.ts)可能会变得过时,因为这些工件依赖于构建系统无法捕获的复杂条件(例如不同文件的名称)。要清理工件,你可以运行

¥It's possible some generated artifacts (such as packages/puppeteer-core/src/types.ts) can become stale since these artifacts rely on complex conditions (such as names of distinct files) that cannot be captured by the build system. To clean artifacts, you can run

npm run clean
# or specify the package
npm run clean --workspace <package>

综合测试

¥Comprehensive testing

除了 npm test 之外,还有其他几个通常通过 CI 检查的 npm 脚本

¥Outside of npm test, there are several other npm scripts that are usually check through CI:

  • test-install - 测试 puppeteerpuppeteer-core 是否安装正确且功能正常。

    ¥test-install - Tests whether puppeteer and puppeteer-core install properly and are functional.

  • test-types - 使用 tsd 测试 puppeteer 中的 TypeScript 类型。

    ¥test-types - Tests the TypeScript types in puppeteer using tsd.

  • test:chrome:** - 在 Chromium 上测试 puppeteer

    ¥test:chrome:** - Tests puppeteer on Chromium.

  • test:firefox:** - 在 Firefox 上测试 puppeteer

    ¥test:firefox:** - Tests puppeteer on Firefox.

  • unit - 运行单元测试。

    ¥unit - Runs unit tests.

默认的 npm test 运行 test:{chrome,firefox}:headless,这通常就足够了。

¥The default npm test runs test:{chrome,firefox}:headless which is generally sufficient.

Puppeteer 在 Mocha 之上使用自定义测试运行器,该测试运行器咨询 TestExpectations.json 以查看给定的测试结果是否符合预期。请参阅 tools/mocha-runner 中有关测试运行程序的更多信息。

¥Puppeteer uses a custom test runner on top of Mocha that consults the TestExpectations.json to see if a given test result is expected or not. See more info about the test runner in tools/mocha-runner.

单元测试

¥Unit tests

仅将测试代码(没有正在运行的浏览器)放置在它们使用 Node 测试运行程序(需要 Node 20+)测试和运行的类旁边的测试:

¥Tests that only test code (without the running browser) are put next to the classes they test and run using the Node test runner (requires Node 20+):

npm run unit

代码审查

¥Code reviews

所有提交的内容,包括项目成员提交的内容,都需要审核。为此,我们使用 GitHub 拉取请求。有关使用拉取请求的更多信息,请参阅 GitHub 帮助

¥All submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. Consult GitHub Help for more information on using pull requests.

代码风格

¥Code Style

我们的编码风格在 .eslintrcESLint)和 .prettierrc.cjsPrettier)中得到了完整的定义。

¥Our coding style is fully defined in .eslintrc (ESLint) and .prettierrc.cjs (Prettier).

代码会自动检查 PR,你可以通过运行以下命令手动检查代码:

¥Code is checked for PRs automatically and you can check your code manually by running:

npm run lint

如果返回一些错误,你可以尝试使用以下方法修复它们:

¥If some errors are returned, you can attempt to fix them using:

npm run format

项目结构

¥Project structure

以下是 Puppeteer 中主要文件夹的说明:

¥The following is a description of the primary folders in Puppeteer:

  • packages 包含所有公共源代码。

    ¥packages contains all public source code.

  • test 包含所有测试源代码。

    ¥test contains all test source code.

  • test-d 包含使用 tsd 的型式测试。

    ¥test-d contains type tests using tsd.

  • tools 包含用于构建等的各种脚本。

    ¥tools contains miscellaneous scripts that are used in building and etc.

  • tools/mocha-runner - 包含我们的测试运行程序的源代码。

    ¥tools/mocha-runner - contains the source code for our test runner.

API 指南

¥API guidelines

编写新的 API 方法时,请考虑以下事项:

¥When authoring new API methods, consider the following:

  • 根据需要公开尽可能少的信息。如有疑问,请勿透露新信息。

    ¥Expose as little information as needed. When in doubt, don’t expose new information.

  • 方法的使用有利于 getter/setter。

    ¥Methods are used in favor of getters/setters.

    • 唯一的例外是命名空间,例如 page.keyboardpage.coverage

      ¥The only exception is namespaces, e.g. page.keyboard and page.coverage

  • 所有字符串字面量都必须是小写字母。这包括事件名称和选项值。

    ¥All string literals must be small case. This includes event names and option values.

  • 避免添加 "sugar" API(可以在用户空间中轻松实现的 API),除非非常需要。

    ¥Avoid adding "sugar" API (API that is trivially implementable in user-space) unless they're extremely demanded.

提交消息

¥Commit messages

提交消息应遵循 常规提交格式

¥Commit messages should follow the Conventional Commits format.

特别是,重大变更应在提交消息页脚中清楚地注明为“重大变更:”。示例:

¥In particular, breaking changes should clearly be noted as “BREAKING CHANGE:” in the commit message footer. Example:

fix(page): fix page.pizza method

This patch fixes page.pizza so that it works with iframes.

Issues: #123, #234

BREAKING CHANGE: page.pizza now delivers pizza at home by default.
To deliver to a different location, use the "deliver" option:
`page.pizza({deliver: 'work'})`.

编写文档

¥Writing documentation

文档是通过 npm run docs 从 TSDoc 注释生成的。它会在合并时自动发布到我们的文档站点,并在发布时进行版本控制。

¥Documentation is generated from TSDoc comments via npm run docs. It is automatically published to our documentation site on merge and gets versioned on release.

这意味着你不应手动更改文件 docs/api 中的 Markdown。

¥This means that you should not change the markdown in files docs/api manually.

编写 TSDoc 注释

¥Writing TSDoc comments

对 Puppeteer 的每次更改都应使用 TSDoc 注释进行完整记录。有关确切语法的信息,请参阅 API 提取器文档

¥Each change to Puppeteer should be thoroughly documented using TSDoc comments. Refer to the API Extractor documentation for information on the exact syntax.

  • 每个新方法都需要添加 @public@internal 作为标记,具体取决于它是否是公共 API 的一部分。

    ¥Every new method needs to have either @public or @internal added as a tag depending on if it is part of the public API.

  • 注释中的每一行不得超过 90 个字符(如果超过此范围,ESLint 会警告你)。如果你是 VSCode 用户,强烈推荐 重新封装插件

    ¥Keep each line in a comment to no more than 90 characters (ESLint will warn you if you go over this). If you're a VSCode user the Rewrap plugin is highly recommended!

在本地运行文档站点

¥Running the documentation site locally

  1. 在 root 下,使用 npm i --ignore-scripts 安装所有依赖。

    ¥At root, install all dependencies with npm i --ignore-scripts.

  2. 运行 npm run docs 将在 puppeteer/docs/api 上生成所有 .md 文件。

    ¥run npm run docs which will generate all the .md files on puppeteer/docs/api.

  3. puppeteer/website 中运行 npm i

    ¥run npm i in puppeteer/website.

  4. puppeteer/website 中运行 npm start

    ¥run npm start in puppeteer/website.

添加新的依赖

¥Adding new dependencies

对于所有依赖(安装和开发):

¥For all dependencies (both installation and development):

  • 如果所需的功能很容易实现,则不要添加依赖。

    ¥Do not add a dependency if the desired functionality is easily implementable.

  • 如果添加依赖,它应该维护良好且值得信赖。

    ¥If adding a dependency, it should be well-maintained and trustworthy.

引入新的安装依赖的障碍特别高:

¥A barrier for introducing new installation dependencies is especially high:

  • 不要添加安装依赖,除非它对项目成功至关重要。

    ¥Do not add installation dependency unless it's critical to project success.

对于与环境竞争的依赖,还有其他注意事项。详细信息请参见 third_party/README.md

¥There are additional considerations for dependencies that are environment agonistic. See the third_party/README.md for details.

测试技巧

¥Testing tips

  • 每个功能都应该附有测试。

    ¥Every feature should be accompanied by a test.

  • 每个公共 api 事件/方法都应该伴随一个测试。

    ¥Every public api event/method should be accompanied by a test.

  • 测试不应依赖于外部服务。

    ¥Tests should not depend on external services.

  • 测试应该在所有三个平台上运行:Mac、Linux 和 Win。这对于屏幕截图测试尤其重要。

    ¥Tests should work on all three platforms: Mac, Linux and Win. This is especially important for screenshot tests.

如果测试预计在某些配置上失败或变得不稳定,请更新 TestExpectations.json 以反映这一点。请参阅 tools/mocha-runner 中有关 TestExpectations.json 的更多信息。

¥If a test is expected to fail on certain configurations or became flaky, update TestExpectations.json to reflect that. See more info about TestExpectations.json in tools/mocha-runner.

API 覆盖范围

¥API Coverage

每个公共 API 方法或事件都应在测试中至少调用一次。为了确保这一点,主要的 test 命令在测试期间运行覆盖。

¥Every public API method or event should be called at least once in tests. To ensure this, the main test command runs coverage during testing.

调试 Puppeteer

¥Debugging Puppeteer

参见 调试技巧

¥See Debugging Tips.

通过 VSCode 调试 Puppeteer 测试

¥Debugging Puppeteer tests via VSCode

将提供的默认 .vscode/launch.template.json 复制到 .vscode/launch.json,然后使用集成的 VSCode 调试器进行调试测试。

¥Copy the provided default .vscode/launch.template.json to .vscode/launch.json and then use the integrated VSCode debugger to debug test.

请记住在启动之前通过以下方式构建测试:

¥Remember to build test before launching via:

npm run build --workspace @puppeteer-test/test

对于项目维护人员

¥For Project Maintainers

推出新的 Chrome 版本

¥Rolling new Chrome version

有一个 GitHub 行动 每天运行一次。该动作有一个手动触发器,可以在 操作选项卡 上找到。

¥There is a GitHub action that runs once per day. The action has a manual trigger that can be found on the Actions Tab.

手册说明

¥Manual instructions

你可以在本地运行 tools/update_chrome_revision.mjs 并尝试查看是否需要提交任何更改。

¥You can run the tools/update_chrome_revision.mjs locally and try see if any changes need to be committed.

注意:你可能需要运行 node --experimental-fetch tools/update_chrome_revision.mjs,因为该脚本依赖于 fetch

¥Note: You may need to run node --experimental-fetch tools/update_chrome_revision.mjs as the script relies on fetch

以下步骤是上述脚本的手动版本。

¥The following steps are manual version of the script above.

  1. 通过 https://googlechromelabs.github.io/chrome-for-testing/https://chromiumdash.appspot.com/ 找到合适的 Chrome revisionversion

    ¥Find a suitable Chrome revision and version via https://googlechromelabs.github.io/chrome-for-testing/ or https://chromiumdash.appspot.com/.

  2. 使用找到的 version 编号更新 packages/puppeteer-core/src/revisions.ts

    ¥Update packages/puppeteer-core/src/revisions.ts with the found version number.

  3. 使用新的 Chrome 到 Puppeteer version 映射更新 versions.js,并使用列表中的下一个映射更新 lastMaintainedChromeVersion

    ¥Update versions.js with the new Chrome-to-Puppeteer version mapping and update lastMaintainedChromeVersion with the next one in from the list.

  4. 运行 npm run check。如果失败,请使用预期的 devtools-protocol 版本更新 packages/puppeteer-core/package.json,并运行 npm install 以生成更新的 package-lock.json

    ¥Run npm run check. If it fails, update packages/puppeteer-core/package.json with the expected devtools-protocol version and run npm install to generate an updated package-lock.json.

  5. 运行 npm run cleannpm installnpm run build

    ¥Run npm run clean, npm install and npm run build.

  6. 运行 npm test 并确保所有测试都通过。如果测试失败,则 bisect 失败的上游原因,并相应地更新测试期望(如果这是有意的更改)或解决 Puppeteer 中的更改(如果不希望更改 Puppeteer 的可观察行为)。

    ¥Run npm test and ensure that all tests pass. If a test fails, bisect the upstream cause of the failure, and either update the test expectations accordingly (if it was an intended change) or work around the changes in Puppeteer (if it’s not desirable to change Puppeteer’s observable behavior).

  7. 提交并推送你的更改并打开拉取请求。提交消息必须包含 Chrome <version> (r<revision>) 格式的版本,以确保 pptr.dev 可以正确解析它,例如 feat(chrome): roll to Chrome 90.0.4427.0 (r856583)

    ¥Commit and push your changes and open a pull request. The commit message must contain the version in Chrome <version> (r<revision>) format to ensure that pptr.dev can parse it correctly, e.g. feat(chrome): roll to Chrome 90.0.4427.0 (r856583).

注意:你可以通过在 Find Releases 中搜索 r<revision> 来找到版本对应版本的另一个地方是 omahaproxy.appspot.com

¥NOTE: Another place you can find version corresponding version is omahaproxy.appspot.com by searching in Find Releases for r<revision>.

平分上游变化

¥Bisecting upstream changes

对于平分 Chrome/Chromium 更改,请使用 https://www.chromium.org/developers/bisect-builds-py/

¥For bisecting Chrome/Chromium changes use https://www.chromium.org/developers/bisect-builds-py/.

发布到 npm

¥Releasing to npm

我们使用 release-please 来自动化发布。当发布应该完成时,检查我们的 拉取请求 中的发布 PR 并合并它。

¥We use release-please to automate releases. When a release should be done, check for the release PR in our pull requests and merge it.

如果 Release Please 失败

¥In case Release Please fails

如果 release-please 失败,需要执行以下操作:

¥In the event release-please fails, the following needs to be done:

  1. 更新应该发布的每个包的变更日志中缺少的任何内容。例如,如果标头丢失,你可能需要添加

    ¥Update anything missing in the CHANGELOG of every package that was supposed to be published. For example, if the header is missing, you may need to add

    • 对于木偶师来说:

      ¥For puppeteer:

      ## [{NEW_VERSION}](https://github.com/puppeteer/puppeteer/compare/v{PREVIOUS_VERSION}...v{NEW_VERSION}) ({CURRENT_DATE})`
    • 对于其他包:

      ¥For other packages:

      ## [{NEW_VERSION}](https://github.com/puppeteer/puppeteer/compare/{PACKAGE_FOLDER_NAME}-v{PREVIOUS_VERSION}...{PACKAGE_FOLDER_NAME}-v{NEW_VERSION}) ({CURRENT_DATE})
  2. 遵循以前版本的做法,为每个包创建一个 GitHub 版本。

    ¥Create a GitHub release for each package, following the practice of previous releases.

错误分类指南

¥Bug triage guidelines

没有 confirmedneeds-feedback 标签的 检查传入的错误报告

¥Check incoming bug reports that do not have a confirmed or needs-feedback label:

  1. 确保问题标记为 bugfeature

    ¥Make sure the issue is labeled as either bug or feature.

  2. 如果问题没有明确的重现或你无法重现,请索要重现并设置 needs-feedback 标签。

    ¥If the issue does not have a clear repro or you cannot repro, ask for the repro and set the needs-feedback label.

  3. 跟进你之前要求反馈的问题(当用户响应时,你应该在 GitHub 上收到通知)。

    ¥Follow-up on the issues you previously asked for a feedback on (you should get a notification on GitHub when the user responds).

  4. 如果用户不提供反馈,问题最终将被过时的机器人关闭。

    ¥If the user does not provide feedback, the issue will be closed by the stale bot eventually.

  5. 如果你能够重现该问题,请添加标签 confirmed

    ¥If you are able to reproduce the issue, add the label confirmed.

  6. 如果 bug 在 Chromium 端,请创建相应的 crbug.com 问题,并使用 upstream 标签标记 GitHub 问题,并在评论中发布 crbug.com 的链接。

    ¥If the bug is on the Chromium side, create a corresponding crbug.com issue, label the GitHub issue with the upstream label, and post a link to crbug.com in the comments.

  7. 如果问题与 Puppeteer 或 Chromium 无关,请关闭该问题。

    ¥If the issue is not related to either Puppeteer or Chromium, close the issue.

  8. 如果问题与文档缺失/不正确有关,请将其标记为 documentation

    ¥If the issue is about missing/incorrect documentation, label it as documentation.

PDF 的问题:

¥Issues with PDFs:

  1. 如果使用常规打印对话框和/或 headful 重现问题,针对 Blink>Layout 组件提交 crbug.com

    ¥If the issue reproduces using the regular print dialog and/or headful, file a crbug.com against the Blink>Layout component.

  2. 如果问题特定于无头模式,则 在 crbug.com 上针对 Internals>Headless 组件提出问题

    ¥If the issue is specific to Headless mode, file an issue on crbug.com against the Internals>Headless component.