TypeScript项目用powerbi-client-react报错:ReferenceError: self is not defined
解决powerbi-client-react在TypeScript项目中出现的ReferenceError: self is not defined错误
问题场景
在TypeScript项目中使用powerbi-client-react库嵌入PowerBI报表时,运行抛出ReferenceError: self is not defined错误,相同逻辑的代码在JavaScript项目中可正常运行。
组件代码
import { PowerBIEmbed } from 'powerbi-client-react'; import { models } from 'powerbi-client'; // aditional declarete from use "window" in my getEmbeddedComponent declare global { interface Window { report: any; } } export default function PbiEmbeddedDashboard() { return ( <div className="App"> <PowerBIEmbed embedConfig={{ type: 'report', // Supported types: report, dashboard, tile, visual and qna id: '<Report Id>', // the information has been filled in correctly in the project embedUrl: '<Embed Url>', // the information has been filled in correctly in the project accessToken: '<Access Token>', // the information has been filled in correctly in the project tokenType: models.TokenType.Embed, // i also tried to use the models.TokenType.Aad but the error was the same settings: { panes: { filters: { expanded: false, visible: false } }, background: models.BackgroundType.Transparent, } }} eventHandlers={ new Map([ ['loaded', function () { console.log('Report loaded'); }], ['rendered', function () { console.log('Report rendered'); }], ['error', function (event) { console.log(event.detail); }] ]) } cssClassName={"report-style-class"} getEmbeddedComponent={(embeddedReport) => { window.report = embeddedReport; }} /> </div> ) };
报错详情
Server Error ReferenceError: self is not defined This error happened while generating the page. Any console logs will be displayed in the terminal window. Call Stack Object.<anonymous> file:///home/myProject/sistema-web-myProject/be-front/node_modules/powerbi-client-react/dist/powerbi-client-react.js (1:452) Module._compile internal/modules/cjs/loader.js (1085:14) Object.Module._extensions..js internal/modules/cjs/loader.js (1114:10) module.load internal/modules/cjs/loader.js (950:32) Function.Module._load internal/modules/cjs/loader.js (790:12) module.require internal/modules/cjs/loader.js (974:19) require internal/modules/cjs/helpers.js (101:18) Object.powerbi-client-react file:///home/myProject/sistema-web-myProject/be-front/.next/server/pages/dashboards/pbi.js (52:18) __webpack_require__ file:///home/myProject/sistema-web-myProject/be-front/.next/server/webpack-runtime.js (33:42) eval webpack-internal:///./src/util/pbiEmbedded/pbi_getAccessToken.tsx (9:78)
错误原因
powerbi-client-react依赖的powerbi-client库是为浏览器环境开发的,代码中直接访问了浏览器全局对象self。而你的项目(从报错路径可判断是Next.js)默认会在**服务端渲染(SSR)**阶段加载该组件,服务端Node.js环境中不存在self对象,因此触发报错。JavaScript项目可能未启用SSR,或组件加载逻辑仅在客户端执行,所以没有这个问题。
解决方案
1. 动态导入组件并禁用SSR(Next.js首选方案)
使用Next.js的dynamic导入方法,指定ssr: false,让组件仅在客户端环境加载:
import dynamic from 'next/dynamic'; import { models } from 'powerbi-client'; // 动态导入PowerBIEmbed,禁用服务端渲染 const PowerBIEmbed = dynamic(() => import('powerbi-client-react').then(mod => mod.PowerBIEmbed), { ssr: false, loading: () => <div>加载报表中...</div> // 可选的加载占位符 } ); declare global { interface Window { report: any; } } export default function PbiEmbeddedDashboard() { return ( <div className="App"> <PowerBIEmbed embedConfig={{ type: 'report', id: '<Report Id>', embedUrl: '<Embed Url>', accessToken: '<Access Token>', tokenType: models.TokenType.Embed, settings: { panes: { filters: { expanded: false, visible: false } }, background: models.BackgroundType.Transparent, } }} eventHandlers={ new Map([ ['loaded', () => console.log('Report loaded')], ['rendered', () => console.log('Report rendered')], ['error', (event) => console.log(event.detail)] ]) } cssClassName={"report-style-class"} getEmbeddedComponent={(embeddedReport) => { window.report = embeddedReport; }} /> </div> ) };
2. 条件渲染,仅在浏览器环境加载组件
如果是非Next.js项目,可通过判断window对象是否存在,确保组件仅在客户端渲染:
import { models } from 'powerbi-client'; declare global { interface Window { report: any; } } export default function PbiEmbeddedDashboard() { // 服务端环境返回加载占位符 if (typeof window === 'undefined') { return <div>加载中...</div>; } // 客户端环境动态导入组件 const { PowerBIEmbed } = require('powerbi-client-react'); return ( <div className="App"> <PowerBIEmbed embedConfig={{/* 保持原配置 */}} eventHandlers={/* 保持原配置 */} cssClassName={"report-style-class"} getEmbeddedComponent={(embeddedReport) => { window.report = embeddedReport; }} /> </div> ) };
3. Webpack配置模拟浏览器全局对象(不推荐)
通过Webpack插件在构建时模拟self对象指向window,但这种方式可能引发其他兼容性问题,仅作为备选:
// webpack.config.js const webpack = require('webpack'); module.exports = { // 其他配置项 plugins: [ new webpack.DefinePlugin({ 'self': 'window' }) ] };
内容的提问来源于stack exchange,提问作者Rafael Vinicius
相关产品推荐
相关产品推荐

