-
Notifications
You must be signed in to change notification settings - Fork 255
Fix AppInsights breaking Angular SSR in Cloudflare Worker #2548
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 6 commits
c852316
0066b07
b26b249
db27b5e
b8570a5
cd9a6d9
33ad868
372ce46
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| # Note on Cloudflare Worker Compatibility with ApplicationInsights SDK | ||
|
|
||
| When using the ApplicationInsights SDK in a Cloudflare Worker environment, particularly with Angular SSR, users may encounter errors related to property redefinition: | ||
|
|
||
| ``` | ||
| Cannot redefine property: name | ||
| at defineProperty (<anonymous>) | ||
| at __name (server.js:7:33) | ||
| ``` | ||
|
|
||
| ## Root Cause | ||
|
|
||
| The issue appears to be related to how esbuild processes the code when bundling for Cloudflare Workers. The error occurs because esbuild adds code that attempts to redefine the "name" property, which is prohibited in Cloudflare Workers' restrictive JavaScript environment. | ||
|
|
||
| ## Workaround | ||
|
|
||
| As noted in [issue #2523](https://github.com/microsoft/ApplicationInsights-JS/issues/2523), you can work around this by: | ||
|
|
||
| 1. Manually invoking esbuild with `preserveNames=false` parameter | ||
| 2. Instructing wrangler to skip bundling | ||
|
|
||
| You may also consider dynamically importing and initializing the SDK only in client-side rendering contexts: | ||
|
|
||
| ```typescript | ||
| private async lazyLoadAppInsights(connectionString: string) { | ||
| try { | ||
| // Check if we're in a browser environment (not SSR) | ||
| if (typeof window !== 'undefined' && typeof document !== 'undefined') { | ||
| // Dynamically import the module only at runtime in browser | ||
| const appInsights = await import('@microsoft/applicationinsights-web'); | ||
| const ApplicationInsights = appInsights.ApplicationInsights; | ||
|
|
||
| this._appInsights = new ApplicationInsights({ | ||
| config: { | ||
| connectionString: connectionString, | ||
| // your other config options... | ||
| } | ||
| }); | ||
|
|
||
| this._appInsights.loadAppInsights(); | ||
| } | ||
| } catch (error) { | ||
| console.error('Failed to initialize ApplicationInsights:', error); | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| This conditional initialization approach prevents the SDK from being instantiated during server-side rendering, avoiding the property redefinition issues. | ||
|
|
||
| ## Reproducing the Issue | ||
|
|
||
| To better understand and diagnose this issue, we've created reproduction scripts in the `/docs/reproduction/` directory. These scripts provide: | ||
|
|
||
| 1. An automated setup for an Angular + Cloudflare Worker environment | ||
| 2. Analysis tools to inspect how esbuild processes the code | ||
| 3. Implementation of various workarounds to test their effectiveness | ||
|
|
||
| You can use these scripts to reproduce the issue and test different solutions in your environment. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,178 @@ | ||
| # Reproducing ApplicationInsights Issues with Angular SSR in Cloudflare Workers | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Move all of the reproduction code to AISKU/Tests/CloudFlareWorkerRepro and update the docs
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moved all reproduction code to AISKU/Tests/CloudFlareWorkerRepro/ and updated the documentation references in commit 33ad868. |
||
|
|
||
| This document outlines steps to reproduce the issues reported in [issue #2523](https://github.com/microsoft/ApplicationInsights-JS/issues/2523), where the ApplicationInsights SDK breaks Angular Server-Side Rendering in Cloudflare Workers environments. | ||
|
|
||
| > **Note:** We've created automated reproduction scripts in the `/docs/reproduction/` directory. These scripts set up a test environment and provide tools to analyze the issue in depth. | ||
|
|
||
| ## Issues Reported | ||
|
|
||
| 1. Property redefinition error for 'name' property: | ||
| ``` | ||
| Cannot redefine property: name | ||
| at defineProperty (<anonymous>) | ||
| at __name (server.js:7:33) | ||
| ``` | ||
|
|
||
| 2. Rendering hanging or being extremely slow without error messages | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - Node.js v16+ and npm/pnpm | ||
| - Cloudflare account (for deployment testing) | ||
| - Wrangler CLI tool (`npm i -g wrangler`) | ||
|
|
||
| ## Reproduction Steps | ||
|
|
||
| ### 1. Create Basic Angular + Cloudflare Project | ||
|
|
||
| ```bash | ||
| # Using the Cloudflare template for Angular | ||
| pnpm create cloudflare@latest my-angular-app --framework=angular | ||
|
|
||
| # Navigate to the created project | ||
| cd my-angular-app | ||
| ``` | ||
|
|
||
| ### 2. Add ApplicationInsights SDK | ||
|
|
||
| ```bash | ||
| # Install ApplicationInsights | ||
| npm install @microsoft/applicationinsights-web | ||
| ``` | ||
|
|
||
| ### 3. Configure ApplicationInsights in Angular | ||
|
|
||
| Update `app.component.ts` to initialize ApplicationInsights: | ||
|
|
||
| ```typescript | ||
| import { Component, OnInit } from '@angular/core'; | ||
| import { ApplicationInsights } from '@microsoft/applicationinsights-web'; | ||
|
|
||
| @Component({ | ||
| selector: 'app-root', | ||
| templateUrl: './app.component.html', | ||
| styleUrls: ['./app.component.css'] | ||
| }) | ||
| export class AppComponent implements OnInit { | ||
| private _appInsights: ApplicationInsights; | ||
|
|
||
| constructor() { | ||
| // This initialization alone will cause the issues | ||
| this._appInsights = new ApplicationInsights({ | ||
| config: { | ||
| connectionString: 'PLACEHOLDER_CONNECTION_STRING', | ||
| enableAutoRouteTracking: true, | ||
| enableCorsCorrelation: false, | ||
| enableRequestHeaderTracking: true, | ||
| enableResponseHeaderTracking: true, | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| ngOnInit() { | ||
| // Even without calling loadAppInsights(), the issue occurs | ||
| // this._appInsights.loadAppInsights(); | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ### 4. Configure Server-Side Rendering | ||
|
|
||
| Ensure the application is configured for server-side rendering in `app.route.server.ts`: | ||
|
|
||
| ```typescript | ||
| import { RenderMode, ServerRoute } from '@angular/ssr'; | ||
|
|
||
| export const serverRoutes: ServerRoute[] = [ | ||
| { | ||
| path: '**', | ||
| renderMode: RenderMode.Server | ||
| } | ||
| ]; | ||
| ``` | ||
|
|
||
| ### 5. Build and Test | ||
|
|
||
| ```bash | ||
| # Build the Angular application | ||
| npm run build | ||
|
|
||
| # Run the application locally using Wrangler | ||
| npx wrangler dev | ||
| ``` | ||
|
|
||
| ## Observed Errors | ||
|
|
||
| When running the application, we observe: | ||
|
|
||
| 1. Error in the Cloudflare Worker logs: | ||
| ``` | ||
| Cannot redefine property: name | ||
| at defineProperty (<anonymous>) | ||
| at __name (server.js:7:33) | ||
| ``` | ||
|
|
||
| 2. The page load hangs indefinitely or is extremely slow. | ||
|
|
||
| ## Testing Workarounds | ||
|
|
||
| ### 1. Using esbuild with preserveNames=false | ||
|
|
||
| To test the workaround mentioned in the issue, we can modify the esbuild configuration: | ||
|
|
||
| ```bash | ||
| # Create a custom esbuild config | ||
| npx esbuild server.js --bundle --outfile=server.custom.js --platform=neutral --target=es2020 --preserve-names=false | ||
| ``` | ||
|
|
||
| ### 2. Dynamically Importing ApplicationInsights in Client-Side Only | ||
|
|
||
| Modify `app.component.ts` to conditionally import and initialize ApplicationInsights: | ||
|
|
||
| ```typescript | ||
| export class AppComponent implements OnInit { | ||
| private _appInsights: any; | ||
|
|
||
| constructor() { | ||
| this.lazyLoadAppInsights('PLACEHOLDER_CONNECTION_STRING'); | ||
| } | ||
|
|
||
| private async lazyLoadAppInsights(connectionString: string) { | ||
| try { | ||
| // Check if we're in a browser environment (not SSR) | ||
| if (typeof window !== 'undefined' && typeof document !== 'undefined') { | ||
| const appInsights = await import('@microsoft/applicationinsights-web'); | ||
| const ApplicationInsights = appInsights.ApplicationInsights; | ||
|
|
||
| this._appInsights = new ApplicationInsights({ | ||
| config: { | ||
| connectionString: connectionString, | ||
| enableAutoRouteTracking: true, | ||
| enableCorsCorrelation: false, | ||
| enableRequestHeaderTracking: true, | ||
| enableResponseHeaderTracking: true, | ||
| } | ||
| }); | ||
|
|
||
| this._appInsights.loadAppInsights(); | ||
| } | ||
| } catch (error) { | ||
| console.error('Failed to initialize ApplicationInsights:', error); | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## Analyzing the Built Bundle | ||
|
|
||
| To understand what causes the property redefinition error, we can examine the built bundle: | ||
|
|
||
| ```bash | ||
| # Find occurrences of property name definition in the bundle | ||
| grep -n "defineProperty" server.js | ||
| grep -n "__name" server.js | ||
| ``` | ||
|
|
||
| ## Findings and Conclusions | ||
|
|
||
| (This section will be updated after successfully reproducing and analyzing the issue) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| # ApplicationInsights with Angular SSR in Cloudflare Workers - Issue Reproduction | ||
|
|
||
| This repository contains scripts and tools to reproduce and analyze the issue reported in [ApplicationInsights-JS issue #2523](https://github.com/microsoft/ApplicationInsights-JS/issues/2523), where the ApplicationInsights SDK breaks Angular Server-Side Rendering in Cloudflare Workers. | ||
|
|
||
| ## Setup and Reproduction | ||
|
|
||
| This reproducer includes several scripts to help diagnose the issue: | ||
|
|
||
| ### 1. Basic Setup (`setup.sh`) | ||
|
|
||
| This script creates a simple Angular application with Cloudflare Worker integration and ApplicationInsights. It: | ||
|
|
||
| - Creates a new Angular project | ||
| - Adds Angular Universal for SSR | ||
| - Installs ApplicationInsights SDK | ||
| - Configures server routes for SSR | ||
| - Sets up AppComponent with ApplicationInsights initialization | ||
| - Creates a Wrangler configuration for Cloudflare Workers | ||
| - Adds a bundle analysis script | ||
|
|
||
| Usage: | ||
| ```bash | ||
| chmod +x setup.sh | ||
| ./setup.sh | ||
| ``` | ||
|
|
||
| ### 2. Testing Workarounds (`test-workarounds.sh`) | ||
|
|
||
| This script implements and tests the workarounds mentioned in the issue: | ||
|
|
||
| - Using esbuild with `preserveNames=false` | ||
| - Using dynamic imports to load ApplicationInsights only in client-side context | ||
|
|
||
| Usage: | ||
| ```bash | ||
| chmod +x test-workarounds.sh | ||
| ./test-workarounds.sh | ||
| ``` | ||
|
|
||
| ### 3. Analyzing the ApplicationInsights SDK (`analyze-appinsights.js`) | ||
|
|
||
| This script scans the ApplicationInsights SDK code to identify patterns that might cause issues with esbuild in Cloudflare Workers: | ||
|
|
||
| - Looks for `Object.defineProperty` calls | ||
| - Checks for `.name` property access or assignment | ||
| - Identifies use of `__name` metadata | ||
| - Scans for dynamic function creation and property redefinition | ||
|
|
||
| Usage: | ||
| ```bash | ||
| node analyze-appinsights.js | ||
| ``` | ||
|
|
||
| ### 4. Testing esbuild Configurations (`test-esbuild.js`) | ||
|
|
||
| This script tests different esbuild configurations to understand how they process function names and properties: | ||
|
|
||
| - Creates test code with various function types | ||
| - Builds with different esbuild configurations | ||
| - Analyzes the output for `__name` helper functions and property definitions | ||
|
|
||
| Usage: | ||
| ```bash | ||
| node test-esbuild.js | ||
| ``` | ||
|
|
||
| ## Expected Results | ||
|
|
||
| After running these scripts, you should be able to: | ||
|
|
||
| 1. Reproduce the "Cannot redefine property: name" error in Cloudflare Workers | ||
| 2. Understand how esbuild processes function names and properties | ||
| 3. Identify patterns in the ApplicationInsights SDK that trigger esbuild to add property redefinition code | ||
| 4. Test workarounds to see if they resolve the issue | ||
|
|
||
| ## Key Findings | ||
|
|
||
| (This section will be updated after running the reproduction scripts and analyzing the results) | ||
|
|
||
| ## Recommendations | ||
|
|
||
| Based on the reproduction and analysis, potential solutions might include: | ||
|
|
||
| 1. Modifying the esbuild configuration when bundling for Cloudflare Workers | ||
| 2. Adding specific detection for Cloudflare Workers environments in the SDK | ||
| 3. Providing guidance to users on how to properly initialize the SDK in SSR contexts | ||
| 4. Restructuring specific parts of the SDK to avoid triggering esbuild's property redefinition | ||
|
|
||
| ## References | ||
|
|
||
| - [ApplicationInsights-JS Issue #2523](https://github.com/microsoft/ApplicationInsights-JS/issues/2523) | ||
| - [Cloudflare Worker documentation](https://developers.cloudflare.com/workers/) | ||
| - [Angular SSR with Cloudflare](https://developers.cloudflare.com/workers/frameworks/framework-guides/angular/) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove isServerSideRenderEnvironment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed isServerSideRenderEnvironment function from the export in applicationinsights-web.ts in commit 33ad868.