Drab webpack problem - Uncaught ReferenceError: require is not defined

I am trying to use drab with webpack but i get error in drap.js

Uncaught ReferenceError: require is not defined
this.Socket = require("phoenix").Socket;

I tried to add that to in app.js
window.socket = require("phoenix").Socket
and i changed
this.Socket = window.socket

But get new errorthis.Socket is not a constructor. How can i use drab with webpack ?

Hi @dokuzbir,
yes, Drab does it:

window.Drab = {
  create: function (drab_return_token, drab_session_token, broadcast_topic) {
    this.Socket = require("phoenix").Socket;

And webpack does not provide global require. We had some discussions about it in github before, but I still can’t find the more universal way to initialize Socket.

1 Like

This is a good point to ask the community, how to improve this?

Now Drab injects its javascript directly into the page. This is why:

  1. Drab’s JS are dynamic (EEx), they depends on the configuration: for example they injects only the parts of used Drab Modules, so if you don’t want to use Drab.Live, it does not inject that part of javascript. Also, there are configuration options which changes the generation of the JS part.
  2. The JS generation function (Drab.Client.run/2) passes some information from conn to the client, for example - the controller name, in the token, which is checked on each execution of the event handler.
  3. Personally, I find npm and friends a nightmare.

I could extract all Drab JS and put it as an npm package, changing Drab.Client.run/2 to pass all the configuration options and modules to use. I could even split it into individual packages, so you could decide if you want Drab.Live or not. But, would this solve the issue with require and webpack?

Also, I could make require("phoenix").Socket as a configurable option, so you could do something like:

config :drab, socket_constructor: "window.socket"

What do you guys think?

1 Like

I don’t think the link is relevant, as the guy there want to use the plain net socket in the browser, we are here speaking about websockets…

1 Like

Sorry maybe strange question but why that didnt work ?
I added that to app.js window.socket = require("phoenix").Socket
and in drap.js i changed this.Socket = window.socket
I got that errorthis.Socket is not a constructor.

No idea. This is much above my understanding of javascript…

How can object.property = something complain that object.property is not a constructor? Obviously, it isn’t.

Or maybe it is one of those special, misleading errors which source is not exactly in this line?

1 Like

This is code is giving error

var params = Object.assign({ __drab_return: this.drab_return_token }, additional_token);
      params = Object.assign(params, {__client_lib_version: Drab.client_lib_version});
      this.socket = new this.Socket("/socket", { //error at this line
        params: params
      });
1 Like

I see. Now it is clearer.
Looks like your window.socket is not a correct object. You may try to debug what is there before you do this.Socket = window.socket in drab.js.

2 Likes

I found problem. Problem was i was using defer attribute on app.js i deleted it. And now drab is working thanks.:+1:

1 Like

Cool.

So, the configuration:

config :drab, socket_constructor: "window.socket"

would fix your issue? I understand you now just hacked Drab changing its JS file, yes?

2 Likes

Yes it fixes issue. I just added two line to my app.
app.js window.socket = require("phoenix").Socket,
drap.js this.Socket = window.socket

2 Likes

@dokuzbir did you extract the javascript generated by Drab.Client.run(@conn) to drap.js and change the require("phoenix").Socket there?

1 Like

You can change how it acquires the socket from the drab configuration.

However soon it may be abstracted out into a standalone module file anyway. :slight_smile:

1 Like

If you have latest drab you can use that way. I copied from drab source code

Custom socket constructor (Webpack “require is not defined” fix)

If you are using JS bundler other than default brunch, the require method may not be availabe
as global. In this case, you might see the error:
require is not defined
in the Drab’s javascript, in line:
this.Socket = require(“phoenix”).Socket;
In this case, you must provide it. In the app.js add a global variable, which will be passed
to Drab later:

      window.__socket = require("phoenix").Socket;

Then, tell Drab to use this instead of default require("phoenix").Socket. Add to config.exs:

      config :drab, MyAppWeb.Endpoint,
        js_socket_constructor: "window.__socket"

This will change the problematic line in Drab’s javascript to:

      this.Socket = window.__socket;
1 Like

hm, I’m adding
window.__socket = require("phoenix").Socket; to app.js, adding

<script src="<%= static_path(@conn, "/js/phoenix.js") %>"></script>

to layout, but now I get TWO same errors:

Uncaught ReferenceError: require is not defined
    at app.js:5
(anonymous) @ app.js:5
(index):111 Uncaught ReferenceError: require is not defined
    at Object.create ((index):111)
    at (index):1085
    at (index):1089

I have version 0.9.1 and --no-brunch phoenix app.

I think you get that error because webpack installation problem or wrong config

@dokuzbir thanks for the answer!
I don’t have webpack yet but I missed Endpoint part in config:

config :drab,MyAppWeb.Endpoint, js_socket_constructor: "Phoenix.Socket"
and
<script src="<%= static_path(@conn, "/js/phoenix.js") %>"></script> in layout.

This way it worked!

2 Likes

I am not js expert but as i know you have to install wepback, brunch etc… for using require() in app.js

1 Like

Is there a live project with drab as main UI engine? How do you guys use it? I find the whole idea very promising, but since you mention webpack, you still use JS on the front. What part the drab is for then? Just as a wrapper for socket connections?

1 Like

Drab uses channels to as replace to ajax and can change user interface from server side.