kramsuiluj's avatar

Uncaught ReferenceError: Echo is not defined

I'm trying to learn laravel broadcasting and laravel echo. I'm completely new in this subject. So, I've been following some tutorials and documentations to hopefully learn this concept. But, I've been struggling for hours now and I guess its time to ask for some help. I'm currently pairing laravel echo with laravel websockets.

What I wanted to do was output a simple console.log() by listening to an event using laravel echo. I've been following the guide from the official laravel websockets documentation.

  1. Install laravel websockets via composer.
  2. Publish config and migration files.
  3. migrate the database.
  4. Install pusher via composer.
  5. Configure the .env of my project.
  6. Configure the config/broadcasting.php
  7. Configure the config/websockets.php
  8. Configure the js/bootstrap.js (there was already code for laravel echo so I just uncommented it.)
  9. I created an event named OrderPlaced just to test the code. Then configured it
  10. I uncommented the BroadcastServiceProvider on config/app.php
  11. I ran php artisan serve, npm run dev, php artisan websockets:serve

.env file

BROADCAST_DRIVER=pusher
PUSHER_APP_ID=broadcasting
PUSHER_APP_KEY=broadcasting
PUSHER_APP_SECRET=broadcasting
PUSHER_HOST=127.0.0.1
PUSHER_PORT=6001
PUSHER_SCHEME=http
PUSHER_APP_CLUSTER=mt1

VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}"
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

config/broadcasting.php (I just copied the code from laravel-websockets documentation)

'pusher' => [
            'driver' => 'pusher',
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            'app_id' => env('PUSHER_APP_ID'),
            'options' => [
                'cluster' => env('PUSHER_APP_CLUSTER'),
                'encrypted' => true,
                'host' => '127.0.0.1',
                'port' => 6001,
                'scheme' => 'http'
            ],
        ],

config/websockets.php

'apps' => [
        [
            'id' => env('PUSHER_APP_ID'),
            'name' => env('APP_NAME'),
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            'enable_client_messages' => false,
            'enable_statistics' => true,
        ],
    ],

resources/js/bootstrap.js

import Echo from 'laravel-echo';

import Pusher from 'pusher-js';
window.Pusher = Pusher;

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: import.meta.env.VITE_PUSHER_APP_KEY,
    wsHost: import.meta.env.VITE_PUSHER_HOST ?? `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`,
    wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80,
    wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443,
    forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
    enabledTransports: ['ws', 'wss'],
});

resources/js/app.js

import './bootstrap';

welcome.blade.php

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    @vite('resources/js/app.js')
    <title>Document</title>
</head>
<body>

<script>
    Echo.private(`orders.${orderId}`)
        .listen('OrderPlaced', (e) => {
            console.log(e.order);
        });
</script>
</body>
</html>

routes/web.php

Route::get('/', function () {
    return view('welcome');
});

Route::get('event', function () {
    $order = \App\Models\Order::create();

    \App\Events\OrderPlaced::dispatch($order);
});

After setting it all up, when I go to my welcome page and check the console its giving me an "Uncaught ReferenceError: Echo is not defined" error.

0 likes
18 replies
OussamaMater's avatar

Well you already did great, you just need to pull the Laravel Echo, you have perfectly setup the backend, and almost prepared the frontend by uncommenting the Echo snippet, but have you installed it?

npm install --save-dev laravel-echo pusher-js

and then recompile your assets

npm run dev

And this should do the trick.

Refer to the docs

1 like
OussamaMater's avatar

@kramsuiluj have you recompiled the assets? if so maybe clear all the cache and retry

php artisan optimize:clear

this will clear all cache, or to test it launch a private tab in your browser, it won't have anything cached, and hopefully this solves it for you.

OussamaMater's avatar

@kramsuiluj I think I understand why, try adding the type module, so your code should be like this

<script type="module"> // the change is here
    Echo.private(`orders.${orderId}`)
        .listen('OrderPlaced', (e) => {
            console.log(e.order);
        });
</script>

This will solve it (fingers crossed).

11 likes
kramsuiluj's avatar

@OussamaMater It still didn't work for me. I'll try to reset first cuz I'm tired debugging this error and maybe try to find a tutorial later to setup laravel websocket and echo. I reall appreciate your effort trying to help, thanks!

OussamaMater's avatar

@kramsuiluj Happy to help, just keep in mind to pull the Echo library and use the newer syntax <script type="module"> I remember facing the exact issue when I switched from webpack to vite to use Laravel 9.

Other than that I don't really see what can cause the problem, check your network tab to see if js is pulled or not, and good luck with the issue!

6 likes
Sylla's avatar

@OussamaMater <script type="module"> works but in my side, I'm getting another post broacasting/auth forbiden error 403

kramsuiluj's avatar

I finally managed to solve this problem, I'll just post the solution here just in case someone ran into the same problem.

The problem is in my welcome.blade.php file, what's happening is the script on the head tag @vite() is not yet ready when the script tag on my body was executed. Basically the script on the body was executed first before I hook up the app.js file, therefore when the script on the body tag ran, the Echo has not been initialized yet resulting to undefined error.

The solution is to wrap the code inside the script tag of the body in a window.onload what this does is it makes sure all the script file has been completely loaded before running the code inside the window.onload.

<script>
	window.onload=function(){
		Echo.private(`orders.${orderId}`)
        .listen('OrderPlaced', (e) => {
            console.log(e.order);
        });
	}
</script>
4 likes
G-ManiX's avatar

@kramsuiluj please would you kindly share how did you import the Laravel-Echo. I have followed the documentation but I'm facing this error "Module parse failed: 'import' and 'export' may appear only with 'sourceType: module".

asif193873's avatar

that will occur while key and cluster are missing from the object, use it...

	window.Echo = new Echo({
    broadcaster: 'pusher',
    key: process.env.MIX_PUSHER_APP_KEY,
    cluster: process.env.MIX_PUSHER_APP_CLUSTER,
    wsHost: window.location.hostname,
    wsPort: 6001,
    forceTLS: false,
    disableStats: true,
});
Disciple's avatar

Set in your bootstrap.js window.Echo = new Echo({ // ... cluster:import.meta.env.VITE_PUSHER_APP_CLUSTER, }); For me it worked.

Please or to participate in this conversation.