如何在Playwright浏览器上下文中导入本地模块?
解决Playwright page.evaluate中导入本地TypeScript模块的问题
这个场景我太熟悉了——在page.evaluate里直接导入本地TS文件肯定会报错,毕竟浏览器上下文和你的Node.js开发环境完全是两个独立的运行环境,浏览器根本不知道../src/Foo/Bar这个本地路径指向哪里。下面给你几个靠谱的解决办法:
方法一:把模块打包成浏览器可运行的脚本(最推荐)
这是最规范的做法,用前端打包工具(比如Vite、Webpack、esbuild)把../src/Foo/Bar.ts打包成一个IIFE或UMD格式的脚本。打包后的文件会把导出的内容挂载到window对象上,这样就能在浏览器上下文里直接访问了。
步骤大概是这样:
- 配置打包工具,把
Bar.ts作为入口,输出一个浏览器友好的脚本(比如dist/bar.bundle.js) - 在Playwright代码里先注入这个打包后的脚本:
await page.addScriptTag({ path: './dist/bar.bundle.js' });
- 然后在
page.evaluate里直接使用导出的内容:
await page.evaluate(async () => { // 假设打包后namedExportExample挂载到了window上 const result = window.namedExportExample.connectWebSocket(); // 后续逻辑... });
方法二:内联模块代码到evaluate上下文
如果你的模块代码量不大,不想额外配置打包工具,可以把模块代码直接读取并注入到浏览器里:
- 先在Node端读取
Bar.ts的内容(记得先把TS转成JS,比如用tsc预编译,或者用esbuild实时转译) - 把代码作为参数传给
page.evaluate,然后用data:URL的方式导入:
const fs = require('fs'); const esbuild = require('esbuild'); // 读取并转译TS为JS const barTsCode = fs.readFileSync('../src/Foo/Bar.ts', 'utf8'); const { code: barJsCode } = await esbuild.transform(barTsCode, { loader: 'ts', target: 'es2020' }); await page.evaluate(async (jsCode) => { // 用data URL导入模块 const { namedExportExample } = await import(`data:text/javascript,${encodeURIComponent(jsCode)}`); // 执行你的逻辑... }, barJsCode);
这种方法适合快速测试,但代码量多的话会显得杂乱,不适合生产环境。
方法三:传递序列化后的函数(局限性大)
如果你的模块导出的函数不依赖浏览器API,可以在Node端先导入模块,再把函数序列化后传给page.evaluate。但注意:如果函数里用到了WebSocket这类浏览器专属API,Node端导入时会直接报错,所以这个方法只适用于纯逻辑函数。
// 先转译TS为JS,再导入 const { namedExportExample } = require('../src/Foo/Bar.js'); await page.evaluate(async (func) => { func(); }, namedExportExample);
总结一下,方法一是最稳定、可维护的方案,符合前端工程化的思路;方法二适合快速验证;方法三只能用于特殊场景。
内容的提问来源于stack exchange,提问作者Dois
相关产品推荐
相关产品推荐

