You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cypress编译含pdfjs-dist的Webpack项目报错但开发环境正常

问题描述

我在Webpack ES6环境中使用npm安装的pdfjs-dist已有数周,项目使用Cypress做E2E测试,昨日Cypress突然无法正常工作。

Cypress抛出的错误信息如下:

Error: Webpack Compilation Error
./node_modules/pdfjs-dist/build/pdf.worker.js (./node_modules/worker-loader/dist/cjs.js?esModule=false&filename=[name].js!./node_modules/pdfjs-dist/build/pdf.worker.js)
Module build failed (from ./node_modules/worker-loader/dist/cjs.js):
TypeError: Cannot read property 'tap' of undefined
 @ ./node_modules/pdfjs-dist/webpack.js 19:20-100
 @ ./src/js/select/views/pdfViews.js
 @ ./src/js/select/views/navbarViews.js
 @ ./src/js/select/utils/DOMutils.js
 @ ./src/js/common/texts/navbars/selectTxt.js
 @ ./cypress/support/KJIcommands/skipRep.js
 @ ./cypress/integration/step1/301-show--lists.spec.js
    at Watching.handle [as handler] (/home/giampaolo/.cache/Cypress/8.2.0/Cypress/resources/app/packages/server/node_modules/@cypress/webpack-preprocessor/dist/index.js:176:23)
    at /home/giampaolo/.cache/Cypress/8.2.0/Cypress/resources/app/packages/server/node_modules/webpack/lib/Watching.js:99:9
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/home/giampaolo/.cache/Cypress/8.2.0/Cypress/resources/app/packages/server/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook (/home/giampaolo/.cache/Cypress/8.2.0/Cypress/resources/app/packages/server/node_modules/tapable/lib/Hook.js:154:20)
    at Watching._done (/home/giampaolo/.cache/Cypress/8.2.0/Cypress/resources/app/packages/server/node_modules/webpack/lib/Watching.js:98:28)
    at /home/giampaolo/.cache/Cypress/8.2.0/Cypress/resources/app/packages/server/node_modules/webpack/lib/Watching.js:73:19
    at Compiler.emitRecords (/home/giampaolo/.cache/Cypress/8.2.0/Cypress/resources/app/packages/server/node_modules/webpack/lib/Compiler.js:499:39)
    at /home/giampaolo/.cache/Cypress/8.2.0/Cypress/resources/app/packages/server/node_modules/webpack/lib/Watching.js:54:20
    at /home/giampaolo/.cache/Cypress/8.2.0/Cypress/resources/app/packages/server/node_modules/webpack/lib/Compiler.js:485:14
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/home/giampaolo/.cache/Cypress/8.2.0/Cypress/resources/app/packages/server/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook (/home/giampaolo/.cache/Cypress/8.2.0/Cypress/resources/app/packages/server/node_modules/tapable/lib/Hook.js:154:20)
    at /home/giampaolo/.cache/Cypress/8.2.0/Cypress/resources/app/packages/server/node_modules/webpack/lib/Compiler.js:482:27
    at /home/giampaolo/.cache/Cypress/8.2.0/Cypress/resources/app/packages/server/node_modules/neo-async/async.js:2818:7
    at done (/home/giampaolo/.cache/Cypress/8.2.0/Cypress/resources/app/packages/server/node_modules/neo-async/async.js:3522:9)
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/home/giampaolo/.cache/Cypress/8.2.0/Cypress/resources/app/packages/server/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook (/home/giampaolo/.cache/Cypress/8.2.0/Cypress/resources/app/packages/server/node_modules/tapable/lib/Hook.js:154:20)

Cypress提示Webpack编译错误,但实际应用运行完全正常,开发环境的编译报告如下:

> webpack-dev-server --mode development

ℹ 「wds」: Project is running at http://localhost:8080/
ℹ 「wds」: webpack output is served from /
ℹ 「wds」: Content not from webpack is served from ./dist
(node:55249) [DEP_WEBPACK_COMPILATION_ASSETS] DeprecationWarning: Compilation.assets will be frozen in future, all modifications are deprecated.
BREAKING CHANGE: No more changes should happen to Compilation.assets after sealing the Compilation.
        Do changes to assets earlier, e. g. in Compilation.hooks.processAssets.
        Make sure to select an appropriate stage from Compilation.PROCESS_ASSETS_STAGE_*.
ℹ 「wdm」: assets by path *.js 4.07 MiB
  asset pdf.worker.js 1.7 MiB [emitted]
  asset select.js 1.19 MiB [emitted] (name: select)
  asset show.js 1.18 MiB [emitted] (name: show)
assets by path ../../../templates/docs/*.html 29.4 KiB
  asset ../../../templates/docs/dist-select.html 16.8 KiB [emitted]
  asset ../../../templates/docs/dist-show.html 12.6 KiB [emitted]
runtime modules 4.2 KiB 14 modules
modules by path ./src/js/ 286 KiB
  modules by path ./src/js/show/ 79.3 KiB 41 modules
  modules by path ./src/js/select/ 194 KiB 31 modules
  modules by path ./src/js/common/ 12.2 KiB 4 modules
modules by path ./node_modules/ 713 KiB
  cacheable modules 713 KiB 30 modules
  ./node_modules/webpack/hot/ sync nonrecursive ^\.\/log$ 170 bytes [built] [code generated]
  ./node_modules/worker-loader/dist/cjs.js?esModule=false&filename=[name].js!./node_modules/pdfjs-dist/build/pdf.worker.js 106 bytes [not cacheable] [built] [code generated]
canvas (ignored) 15 bytes [built] [code generated]
fs (ignored) 15 bytes [built] [code generated]
zlib (ignored) 15 bytes [optional] [built] [code generated]
http (ignored) 15 bytes [built] [code generated]
https (ignored) 15 bytes [built] [code generated]
url (ignored) 15 bytes [built] [code generated]
webpack 5.49.0 compiled successfully in 3598 ms
ℹ 「wdm」: Compiled successfully.

目前查到的常见解决方案是回退到旧版pdfjs,但项目此前运行一直无问题,且更像是Cypress本身的问题而非Webpack或pdfjs的问题,应用代码运行完全正常,但也需要保证测试可用。

补充信息

回退了几个测试正常的提交,第一个出现错误的提交报的是另一个错误:

An uncaught error was detected outside of a testfailed
No commands were issued in this test.
TypeError
The following error originated from your test code, not from Cypress.

  > Cannot read property 'dataset' of null

When Cypress detects uncaught errors originating from your test code it will automatically fail the current test.

Cypress could not associate this error to any specific test.

We dynamically generated a new test to display this failure.
src/js/show/utils/base-show.js:31:49
  29 | export const showElements = {
  30 | 
> 31 |   myPdfDoc: document.querySelector('#script-1').dataset.mypdfdoc,
     |                                                 ^
  32 | 
  33 | }
  34 |  
View stack trace
 Print to console
    at Object../src/js/show/utils/base-show.js (webpack:///./src/js/show/utils/base-show.js:31:49)
    at __webpack_require__ (webpack:///webpack/bootstrap:19:1)
    at Object../src/js/show/UI/selections.js (webpack:///./src/js/show/UI/selections.js:1:1)
    at __webpack_require__ (webpack:///webpack/bootstrap:19:1)
    at Object../src/js/common/texts/navbars/selectTxt.js (webpack:///./src/js/common/texts/navbars/selectTxt.js:3:1)
    at __webpack_require__ (webpack:///webpack/bootstrap:19:1)
    at Object../cypress/support/KJIcommands/skip.js (webpack:///./cypress/support/KJIcommands/skip.js:1:1)
    at __webpack_require__ (webpack:///webpack/bootstrap:19:1)
    at Object../cypress/support/commands.js (webpack:///./cypress/support/commands.js:32:1)
    at __webpack_require__ (webpack:///webpack/bootstrap:19:1)
From previous event:
    at runScriptsFromUrls (http://localhost:34631/__cypress/runner/cypress_runner.js:164932:98)
    at Object.runScripts (http://localhost:34631/__cypress/runner/cypress_runner.js:164946:11)
    at $Cypress.onSpecWindow (http://localhost:34631/__cypress/runner/cypress_runner.js:153894:19)

这两类错误的共同点是测试代码完全没有执行,错误在测试启动前就已经触发。Cypress提示“动态生成了测试来展示错误”,但此时还没有访问应用页面,找不到DOM元素是很正常的。

控制台还出现了以下报错,可能和问题无关,应该是Firefox加载source map的错误,开发过程中经常遇到:

DevTools failed to load source map: Could not load content for http://localhost:34631/__cypress/runner/popper.js.map: HTTP error: status code 404, net::ERR_HTTP_RESPONSE_CODE_FAILURE

解决方案

错误根源

  1. Webpack编译报错是版本不兼容导致:本地开发使用Webpack5,而Cypress 8.2.0内置的webpack预处理器默认依赖Webpack4,高版本worker-loader仅支持Webpack5,因此在Cypress的编译流程中会抛出属性不存在的错误,和本地开发环境的Webpack版本无关。
  2. DOM查询报错是代码执行时机问题:DOM查询逻辑写在了模块顶层导出位置,只要模块被导入就会立即执行这段代码。Cypress加载support目录下的文件是在测试启动前、还未访问应用页面的阶段,此时页面为Cypress的空白上下文,自然无法找到对应DOM元素。

具体解决方法

  • 处理worker-loader兼容问题:
    • 方案1:升级@cypress/webpack-preprocessor到支持Webpack5的版本,同时配置Cypress使用项目本地的Webpack5实例进行编译。
    • 方案2:在Cypress的webpack配置中新增mock规则,直接替换pdfjs-dist/webpack.js为模拟模块,绕开worker加载逻辑,无需修改业务代码。
    • 方案3:开发依赖中额外安装兼容Webpack4的worker-loader@3.x版本,指定Cypress编译时使用该版本loader处理pdf worker文件。
  • 处理顶层DOM查询问题:
    调整代码写法,将顶层DOM查询改为导出函数调用时执行:
    // 调整前
    export const showElements = {
      myPdfDoc: document.querySelector('#script-1').dataset.mypdfdoc,
    }
    
    // 调整后
    export const getShowElements = () => ({
      myPdfDoc: document.querySelector('#script-1')?.dataset.mypdfdoc
    })
    
    业务代码中使用到showElements的地方改为调用getShowElements()即可,仅在业务逻辑实际执行时才会触发DOM查询,不会在模块导入阶段提前执行。
    若不想修改业务代码,也可以在Cypress的support入口文件最前端新增模拟DOM的代码,提前创建对应ID的元素并填充属性,避免查询为空。

内容的提问来源于stack exchange,提问作者Giampaolo Ferradini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 04:15:01