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

Playwright组件测试中Next.js项目MyComponent.tsx无法访问process.env

在Next.js Playwright组件测试中让组件访问环境变量

我在Next.js项目中用Playwright做组件测试,目录结构如下:

./playwright
 - component
     ./MyComponent.spec.tsx
     ./MyComponent.tsx
     ./index.html
 - fixtures
 - index.ts

目前在playwright-ct-config.ts里用dotenv加载了./env/.env.test的环境变量,测试文件MyComponent.spec.tsx能正常访问process.env,但组件MyComponent.tsx里访问不到。需要让组件也能拿到这些环境变量。


核心原因

测试文件运行在Node.js环境,能直接读取process.env;但组件是在浏览器环境渲染的,Node的process.env不会自动同步到浏览器上下文,得手动注入。


方案1:通过Playwright配置注入浏览器环境变量

在playwright-ct-config.ts里,把dotenv加载的变量配置到environmentVariables中,Playwright会自动把这些变量注入到浏览器的process.env模拟对象里:

import { defineConfig } from '@playwright/experimental-ct-react';
import dotenv from 'dotenv';

// 加载测试环境变量
const envConfig = dotenv.config({ path: './env/.env.test', override: true });
const env = envConfig.parsed || {};

export default defineConfig({
  testDir: './playwright/component',
  environment: 'next', // 指定Next.js环境
  // 注入环境变量到浏览器上下文
  environmentVariables: {
    // 可以全部注入,或者只挑需要的(推荐只传NEXT_PUBLIC_开头的,符合Next.js规则)
    ...env,
    // 示例:只传递公共变量
    NEXT_PUBLIC_API_BASE_URL: env.NEXT_PUBLIC_API_BASE_URL,
  },
});

注意:Next.js中只有NEXT_PUBLIC_前缀的环境变量会被暴露到浏览器环境,所以组件里只能访问带这个前缀的变量,私有变量不要直接注入到浏览器。


方案2:通过Fixture传递私有变量(适合敏感数据)

如果是不需要暴露给浏览器的私有变量(比如API密钥),别直接注入到浏览器,而是通过Playwright Fixture把变量作为props传给组件:

  1. 在playwright/fixtures/env.ts里定义环境变量fixture:
import { test as base } from '@playwright/experimental-ct-react';
import dotenv from 'dotenv';

const env = dotenv.config({ path: './env/.env.test', override: true }).parsed || {};

// 扩展基础测试,添加环境变量fixture
export const test = base.extend({
  componentEnv: async ({}, use) => {
    await use({
      privateApiKey: env.PRIVATE_API_KEY,
    });
  },
});

export { expect } from '@playwright/experimental-ct-react';
  1. 在测试文件中使用fixture传递变量给组件:
import { test, expect } from '../fixtures/env';
import MyComponent from './MyComponent';

test('组件能拿到私有变量', async ({ mount, componentEnv }) => {
  // 把变量作为props传给组件
  await mount(<MyComponent apiKey={componentEnv.privateApiKey} />);
  
  // 验证组件行为
  await expect(page.getByText('API密钥已加载')).toBeVisible();
});
  1. 组件通过props接收变量:
// MyComponent.tsx
interface Props {
  apiKey: string;
}

export default function MyComponent({ apiKey }: Props) {
  return <div>API密钥已加载:{apiKey}</div>;
}

方案3:通过Vite配置注入(自定义浏览器环境变量)

如果需要更灵活的注入方式,可以通过Playwright的ctViteConfig配置,用Vite的define选项把变量替换到组件代码中:

import { defineConfig } from '@playwright/experimental-ct-react';
import dotenv from 'dotenv';

const envConfig = dotenv.config({ path: './env/.env.test', override: true });
const env = envConfig.parsed || {};

export default defineConfig({
  testDir: './playwright/component',
  environment: 'next',
  use: {
    ctIndexHtml: './playwright/component/index.html',
    // 配置Vite替换规则
    ctViteConfig: {
      define: {
        // 把process.env变量替换成实际值
        'process.env.NEXT_PUBLIC_API_URL': JSON.stringify(env.NEXT_PUBLIC_API_URL),
        // 也可以注入到window对象
        'window.appEnv.API_URL': JSON.stringify(env.NEXT_PUBLIC_API_URL),
      },
    },
  },
});

之后组件里就能直接用process.env.NEXT_PUBLIC_API_URL或者window.appEnv.API_URL访问变量。


关键提醒

  • 永远不要把敏感的私有变量(比如数据库密码、私钥)暴露到浏览器环境,这类变量只能通过方案2的props传递,或者在测试中模拟接口返回。
  • Next.js的NEXT_PUBLIC_前缀是浏览器环境访问变量的标准方式,尽量遵循这个规则,避免自定义注入带来的混乱。

内容的提问来源于stack exchange,提问作者Divyanshu Rawat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 00:57:29