|
| 1 | +# Client-Side JavaScript Error Reporting for Laravel |
| 2 | + |
| 3 | +This package provides a robust, zero-dependency solution for capturing client-side JavaScript errors and unhandled promise rejections, and logging them to Google Cloud Error Reporting. |
| 4 | + |
| 5 | +It automatically captures and transforms stack traces into a V8-compatible format, ensuring errors are grouped correctly within the Google Cloud console. |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | +## Features |
| 10 | + |
| 11 | +* **Seamless Integration with Google Cloud**: Client-side errors are reported directly to Google Cloud Error Reporting, appearing alongside your server-side exceptions. |
| 12 | +* **Correlated Logging**: Errors are logged against the `traceId` of the initial page load request. This allows you to easily find all client-side errors generated from a specific server request in the Log Viewer. |
| 13 | +* **User Tracking**: When configured, a user identifier is sent with each error report, allowing you to see how many users are affected by a specific issue directly within the Error Reporting UI. |
| 14 | + |
| 15 | +## Installation & Setup |
| 16 | + |
| 17 | +1. **Enable the Service Provider** |
| 18 | + |
| 19 | +In your `bootstrap/app.php` file, add the service provider to the `withProviders` array: |
| 20 | + |
| 21 | +```php |
| 22 | +->withProviders([ |
| 23 | + // ... other providers |
| 24 | + \AffordableMobiles\GServerlessSupportLaravel\Integration\ErrorReporting\ClientSideJavaScript\ClientSideJavaScriptErrorReportingServiceProvider::class, |
| 25 | +]) |
| 26 | +``` |
| 27 | + |
| 28 | +2. **Publish and Configure** |
| 29 | + |
| 30 | +First, publish the package's dedicated configuration file: |
| 31 | + |
| 32 | +```sh |
| 33 | +php artisan vendor:publish --tag="js-error-reporter-config" |
| 34 | +``` |
| 35 | + |
| 36 | +This will create a new configuration file at `config/js-error-reporter.php`. |
| 37 | + |
| 38 | +Open this file to configure the reporter. |
| 39 | + |
| 40 | +At a minimum, you must enable it: |
| 41 | + |
| 42 | +```php |
| 43 | +// config/js-error-reporter.php |
| 44 | + |
| 45 | +return [ |
| 46 | + // Enable or disable the entire feature. |
| 47 | + 'enabled' => true, |
| 48 | + |
| 49 | + // ... other options |
| 50 | +]; |
| 51 | +``` |
| 52 | + |
| 53 | +3. **Important: Cookie Encryption** |
| 54 | + |
| 55 | +If you are using a `'cookie'` source for the `user_identifier` and that cookie is **not** set by Laravel (e.g., it's a platform-level or legacy cookie), you **must** prevent Laravel from trying to encrypt it. |
| 56 | + |
| 57 | +In `bootstrap/app.php`, add the cookie name to the exceptions list for the `EncryptCookies` middleware: |
| 58 | + |
| 59 | +```php |
| 60 | +->withMiddleware(function (Middleware $middleware) { |
| 61 | + $middleware->encryptCookies(except: [ |
| 62 | + '__global_session_id', // <-- Add your cookie name here |
| 63 | + ]); |
| 64 | +}) |
| 65 | +``` |
| 66 | + |
| 67 | +4. **Include the Blade Partial** |
| 68 | + |
| 69 | +Finally, include the provided Blade partial in your main application layout, inside the `<head>` tag. |
| 70 | + |
| 71 | +This ensures the error handlers are registered as early as possible. |
| 72 | + |
| 73 | +```php |
| 74 | +{{-- resources/views/layouts/app.blade.php --}} |
| 75 | +<head> |
| 76 | + ... |
| 77 | + {{-- Include the Client-Side Error Reporter --}} |
| 78 | + @include('gss-js-error-reporting::partials.error-reporter-init') |
| 79 | + ... |
| 80 | +</head> |
| 81 | +``` |
| 82 | + |
| 83 | +5. **Configure Authentication (Optional)** |
| 84 | + |
| 85 | +By default, the package protects the reporting endpoint from cross-domain requests by ensuring the Host and Referer headers match. |
| 86 | + |
| 87 | +You can customize this behavior by providing a custom authentication closure in the `config/js-error-reporter.php` file. |
| 88 | + |
| 89 | +Setting the value to null will disable authentication. |
| 90 | + |
| 91 | +```php |
| 92 | +// config/js-error-reporter.php |
| 93 | + |
| 94 | +'authentication' => function (\Illuminate\Http\Request $request) { |
| 95 | + // Example: Allow requests only from specific subdomains |
| 96 | + $refererHost = parse_url($request->header('referer'), PHP_URL_HOST); |
| 97 | + return str_ends_with($refererHost, '.yourdomain.com'); |
| 98 | +}, |
| 99 | +``` |
| 100 | + |
| 101 | +## Improving Stack Trace Accuracy (Optional) |
| 102 | + |
| 103 | +For the most accurate and readable stack traces in Google Cloud Error Reporting, it is highly recommended to generate JavaScript source maps (`.js.map` files) during your asset build process. The error reporting library will automatically use these maps to translate minified production code back into its original, readable source. |
| 104 | + |
| 105 | +**Important Note:** Enabling source maps for production builds will make your original, un-minified JavaScript code (including comments) visible to anyone who uses the browser's developer tools. For most applications, the benefit to debugging outweighs this consideration. |
| 106 | + |
| 107 | +**Enabling Source Maps in Vite** |
| 108 | + |
| 109 | +In your project's `vite.config.js` file, set the `build.sourcemap` option to `true`: |
| 110 | + |
| 111 | +```js |
| 112 | +// vite.config.js |
| 113 | +import { defineConfig } from 'vite'; |
| 114 | + |
| 115 | +export default defineConfig({ |
| 116 | + // ... |
| 117 | + build: { |
| 118 | + sourcemap: true, |
| 119 | + }, |
| 120 | +}); |
| 121 | +``` |
| 122 | + |
| 123 | +**Enabling Source Maps in Laravel Mix** |
| 124 | + |
| 125 | +In your project's `webpack.mix.js` file, chain the `.sourceMaps()` method in your production environment block: |
| 126 | + |
| 127 | +```js |
| 128 | +// webpack.mix.js |
| 129 | +const mix = require('laravel-mix'); |
| 130 | + |
| 131 | +mix.js('resources/js/app.js', 'public/js'); |
| 132 | + |
| 133 | +if (mix.inProduction()) { |
| 134 | + mix.version().sourceMaps(); |
| 135 | +} |
| 136 | +``` |
| 137 | + |
| 138 | +## Deployment |
| 139 | + |
| 140 | +The package includes versioned JavaScript assets. To ensure the correct assets are always published during your deployment pipeline, make sure the `g-serverless:publish-assets` command is called. |
| 141 | + |
| 142 | +**If you are using the `g-serverless:prepare` command, this is handled for you automatically.** |
0 commit comments