Skip to content

[BUG] H5 build fails with ReferenceError: window is not defined when app.config.ts imports @tarojs/taro #19031

@jiezhiyong

Description

@jiezhiyong

环境 / Environment

Taro version 4.1.11
Node.js version v24.14.0
OS macOS 12.7.6 (x64)
Framework React
Compiler webpack5
Package manager pnpm

问题描述 / Bug Description

执行 pnpm build:h5 时,构建在约 250ms 内失败,报错:

ReferenceError: window is not defined
    at node_modules/.pnpm/@tarojs+runtime@4.1.11/node_modules/@tarojs/runtime/dist/env.js

根本原因 / Root Cause

@tarojs/runtime/dist/env.js 第4行:

const env = {
    window: process.env.TARO_PLATFORM === 'web' ? window : EMPTY_OBJ,
    document: process.env.TARO_PLATFORM === 'web' ? document : EMPTY_OBJ
};

JavaScript 三元表达式的两端都会被求值,即使条件为 false,window 仍然被访问。

Taro 使用 esbuild 将 app.config.ts bundle 后在 Node.js 环境中执行(通过 requireWithEsbuild),此时若 app.config.ts import 了 @tarojs/taro,就会触发 @tarojs/runtime 的加载和初始化,导致在 Node.js 环境中裸访问 window

调用链:

app.config.ts
  → import @tarojs/taro
  → @tarojs/taro/index.js
  → @tarojs/runtime/dist/index.js
  → @tarojs/runtime/dist/env.js  ← ReferenceError: window is not defined

复现步骤 / Steps to Reproduce

  1. 初始化 Taro 4.1.11 H5 项目(taro init
  2. 确保 app.config.ts 包含 import { defineAppConfig } from '@tarojs/taro'(默认模板即如此)
  3. 执行 pnpm build:h5

修复方案 / Fix

方案一(用户侧 workaround):

移除 app.config.ts 和页面 *.config.ts 中对 @tarojs/taro 的 import,直接 export 原始对象:

// 修复前
import { defineAppConfig } from '@tarojs/taro'
export default defineAppConfig({ ... })

// 修复后
export default { ... }

方案二(框架侧根本修复):

@tarojs/runtime/dist/env.js 添加 typeof 安全检查:

const env = {
    window: process.env.TARO_PLATFORM === 'web'
        ? (typeof window !== 'undefined' ? window : EMPTY_OBJ)
        : EMPTY_OBJ,
    document: process.env.TARO_PLATFORM === 'web'
        ? (typeof document !== 'undefined' ? document : EMPTY_OBJ)
        : EMPTY_OBJ
};

备注 / Notes

此问题在 Node.js 18/20 LTS 上也可能存在,但因模块加载顺序差异可能不触发。Node.js 24 对模块初始化更严格,更容易暴露此问题。

官方模板(taro init 生成的默认 app.config.ts)即包含触发此 bug 的 import,建议官方模板也同步修复。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions