socketio / socket.io-client

Realtime application framework (client)
https://socket.io
10.63k stars 3.04k forks source link

version 1.0.x is not AMD compatible but 0.9.x works #690

Closed reidlai closed 3 years ago

reidlai commented 10 years ago

I keep on getting error when I use dojo AMD loader to load socket.io.js but no problem at branch 0.9.x. I tried both server version and GitHub version. Please follow up

michaelwittig commented 10 years ago

same problem for me using requirejs on the browser side to load socket.io

"shim": {
  "socketio": {
    exports: "io"
  }
}

when building the minified version of my app requirejs complains about:

socket.io.js has more than one anonymous define. May be a built file from another build system like, Ender. Skipping normalization.

And the browser throws:

Error: Mismatched anonymous define() module: function (){var e,t,n;return function r(e,t,n){function i(o,u){if(!t[o]){if(!e[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(s)return s(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=t[o]={exports:{}};e[o][0].call(f.exports,function(t){var n=e[o][1][t];return i(n?n:t)},f,f.exports,r,e,t,n)}return t[o].exports}var s=typeof require=="function"&&require;for(var o=0;o<n.length;o++)i(n[o]);return i}({1:[function(e,t,n){t.exports=e("./lib/")},{"./lib/":2}],2:[function(e,t,n){function a(e,t){typeof e=="object"&&(t=e,e=undefined),t=t||{};var n=r(e),i=n.source,a=n.id,f;return t.forceNew||!1===t.multiplex?(o("ignoring socket cache for %s",i),f=s(i,t)):(u[a]||(o("new io instance for %s",i),u[a]=s(i,t)),f=u[a]),f.socket(n.path)}var r=e("./url"),i=e("socket.io-parser"),s=e("./manager"),o=e("debug")("socket.io-client");t.exports=n=a;var u=n.managers={};n.protocol=i.protocol,n.connect=a,n.Manager=e("./manager"),n.Socke
reidlai commented 10 years ago

There is no shim plugin in Dojo AMD loader. I tried to use use-amd but no luck. I assumed that socket.io.js of version 0.9.x and version 1.0.x are compatible with CommonJS. But feel strange that I can load the javascript file of 0.9.x but fail if using 1.0.x....now I fall back Socket.IO to 0.9.x and everything works fine.

rauchg commented 10 years ago

@substack is the browserify standalone build not AMD friendly?

JamesHenry commented 10 years ago

+1 for require build failing. Thanks in advance for looking into this - socket.io is awesome and I would love to be able to use v1.0+

rauchg commented 10 years ago

We're using browserify to make the build. I would imagine the standalone option would produce a AMD-ready module.

JamesHenry commented 10 years ago

Hi @guille,

I tried to run the socket.io.js file through browserify with the standalone option, but I ran into the following issue:


➜  browserify public/js/libs/socket.io.js --standalone io > test.js

/usr/local/lib/node_modules/browserify/node_modules/resolve/lib/async.js:28
    if (x.match(/^(?:\.\.?\/|\/|([A-Za-z]:)?\\)/)) {
          ^
TypeError: Object 33 has no method 'match'
    at resolve (/usr/local/lib/node_modules/browserify/node_modules/resolve/lib/async.js:28:11)
    at /usr/local/lib/node_modules/browserify/node_modules/browser-resolve/index.js:153:20
    at /usr/local/lib/node_modules/browserify/node_modules/browser-resolve/index.js:71:24
    at fs.js:271:14
    at Object.oncomplete (fs.js:107:15)

Is the solution you suggested above something you would need to do as a separate/complementary build?

rauchg commented 10 years ago

The socket.io.js build was already built with that option, hence it should have AMD support. Correct me if I'm wrong @substack

reidlai commented 10 years ago

Thanks , let me try again.

On Thu, Jun 26, 2014 at 4:49 AM, Guillermo Rauch notifications@github.com wrote:

The socket.io.js build was already built with that option, hence it should have AMD support. Correct me if I'm wrong @substack https://github.com/substack

— Reply to this email directly or view it on GitHub https://github.com/Automattic/socket.io-client/issues/690#issuecomment-47156624 .

TooTallNate commented 10 years ago

FWIW you guys, this very minimal example was able to load the socket.io client via require.js (all using CDN service urls):

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.11/require.js"></script>
    <script>
      requirejs.config({
        "paths": {
          "socket.io": "http://wzrd.in/standalone/socket.io-client@1.0.x?noext"
        }
      });

      require(["socket.io"], function(sio) {
        console.log(sio);
      });
    </script>
  </body>
</html>

When I load the page I see the socket.io instance creation function being logged in the console.

Hope that helps!

JamesHenry commented 10 years ago

To be clear what I, and what @michaelwittig seems to be referring to, is an issue with building the require.js modules with its standard build tool, r.js.

It works fine unminified (in dev), but throws the error @michaelwittig shows when you try and build and so just gets skipped altogether.

socket.io.js has more than one anonymous define. May be a built file from another build system like, Ender. Skipping normalization.

It is AMD compatible in the sense that it has the relevant define, which means you do not need the shim, but the fact that it has more than one appears to be problematic.

TooTallNate commented 10 years ago

@JamesHenry Try this build file and let me know if you have better luck: https://raw.githubusercontent.com/Automattic/socket.io-client/update/browserify-v4/socket.io.js

JamesHenry commented 10 years ago

Hi @TooTallNate, I am afraid I still seem to get the same error when building:

Tracing dependencies for: main
libs/socket.io.js has more than one anonymous define. May be a built file from another build system like, Ender. Skipping normalization.

The file seems to contain 3 define()'s.

A "wrapper" around the file, from line 1 (which might be what is generated by the standalone option in your browserify build?):

!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.io=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){

And then two other references within the file:

(Line 4236)

// Some AMD build optimizers, like r.js, check for specific condition patterns
  // like the following:
  if (
    typeof define == 'function' &&
    typeof define.amd == 'object' &&
    define.amd
  ) {
    define(function() {
      return utf8;
    });
  } else if (freeExports && !freeExports.nodeType) {
    if (freeModule) { // in Node.js or RingoJS v0.8.0+
      freeModule.exports = utf8;
    } else { // in Narwhal or RingoJS v0.7.0-
      var object = {};
      var hasOwnProperty = object.hasOwnProperty;
      for (var key in utf8) {
        hasOwnProperty.call(utf8, key) && (freeExports[key] = utf8[key]);
      }
    }
  } else { // in Rhino or a web browser
    root.utf8 = utf8;
  }

AND

(Line 6005)

// Export for asynchronous module loaders.
  if (isLoader) {
    define(function () {
      return JSON3;
    });
  }

Sure enough, only by commenting these two other define()'s out does the build succeed. (At the cost of the script working).

Many thanks,

James

alexis-gruet-deel commented 10 years ago

Not sure this is the same issue, but looks similar.
While switching on the client side from 0.9.16 to 1.0.6 a r.js build gives :

libs/socket.io.js has two many anonymous modules in it.
TooTallNate commented 10 years ago

So utf8 and json3 modules have weird AMD wrappers that appear to be tripping up r.js.

alexis-gruet-deel commented 10 years ago

Commenting the two define() anonymous functions has solved the r.js build issue.

rauchg commented 10 years ago

cc @mathias @kitcambridge

ghost commented 10 years ago

Oh, interesting—does r.js generate names for all anonymous modules as part of the build process? (Incidentally, I wonder if Lo-Dash would be affected, too, since all three projects use similar AMD wrappers...)

bnjmnt4n commented 10 years ago

cc @mathias @kitcambridge

You mean @mathiasbynens ;)

Inateno commented 10 years ago

Hey guys I was stuck on problems with socket.io to and found a tricky solution (not the best but it's work perfectly and prevent the "bad define" from socket.io). In my app I wanted to load socket.io after some client side initialization, and making a client totally independent from server, also this allow me to call socket.io on different path depending on my client options, and I don't add socket in the require path list.

At the good moment I call the socket.io script through DSL method This is a good way to call socket.io without make a dependence that'll break your client if the server is down, or not accessible, or something. The problem now is socket.io contain a "define" condition and if you load socket.io with script tag (without require) it's going inside require because of define, so I removed the define function from window scope and set it when socket.io is loaded, or on error.

var tag = document.createElement( 'script' ); tag.src = config.app_url + '/socket.io/socket.io.js'; var oldDefine = window.define; window.define = undefined; tag.onload = function() { console.log( '%cGet Socket.io !' ); // do stuff with io now window.define = oldDefine; } tag.onerror = function() { // oops window.define = oldDefine; }

Got it ? With this it's easy to create application launching on localStorage if no socket, or going to ajax. Hoe it's help for some guys stuck ^^

kreegr commented 10 years ago

I'm running into this issue with r.js 2.1.14 as well. Works fine when running from un-processed sources, but fails silently after run through the optimizer.

marcbenito commented 10 years ago

I have this issue for a long time. Update your r file and require compiler to 2.1.15 and this error never more occurs!

Tug commented 9 years ago

Updating r.js to 2.1.15 didn't work for me. Only removing the define calls in socket.io as @JamesHenry pointed out did the trick. Beware of the utf8 module, the whole require.js test should be removed too:

(Line 4236)

  var utf8 = {
    'version': '2.0.0',
    'encode': utf8encode,
    'decode': utf8decode
  };
  if (freeExports && !freeExports.nodeType) {
    if (freeModule) { // in Node.js or RingoJS v0.8.0+
      freeModule.exports = utf8;
    } else { // in Narwhal or RingoJS v0.7.0-
      var object = {};
      var hasOwnProperty = object.hasOwnProperty;
      for (var key in utf8) {
        hasOwnProperty.call(utf8, key) && (freeExports[key] = utf8[key]);
      }
    }
  } else { // in Rhino or a web browser
    root.utf8 = utf8;
  }

Otherwise socket.io will loop forever on the initial request because utf8.decode (L3620) will be undefined so parser.decodePacket will return an error but I don't see any error handling in onPacket

Tug commented 9 years ago

Relevant: https://github.com/jrburke/requirejs/issues/883 So it is supposed to be fixed in version 2.1.10

kashifshamaz21 commented 9 years ago

I'm using r.js version 2.1.15 and socket.io-client v1.3.2, and when i minify the build i don't see the "too many anonymous modules issue", so the build went through fine. But when i load the built output file of r.js in the browser, it throws up the following error:

Uncaught ReferenceError: module is not defined

The built output file after r.js optimization has the following line from index.js(of root folder),

module.exports = require('./lib/');

which i believe would result in the module is not defined error.

Anybody ran into this, and figured out a way to resolve it?

maxbeatty commented 9 years ago

I was able to work around this by upgrading to the latest requirejs (2.1.17) and including require.js with our main built output file like from the optimization docs

node ../../r.js -o baseUrl=. paths.requireLib=../../require name=main include=requireLib out=main-built.js

Since "require" is a reserved dependency name, you create a "requireLib" dependency and map it to the require.js file.

kashifshamaz21 commented 9 years ago

@maxbeatty The issue i was facing was due to a different reason altogether. It was a build system issue at my end, nothing to do with socket-io-client library. Thanks for the info anyways.

reidlai commented 9 years ago

Dear All, finally I worked it out using third-party engine.io AMD client to talk with Socket.IO's new engine "engine.io". I believe socket-io-client is based on CommonJS....there may be some problems when we use dojo build.

kent78 commented 9 years ago

We are using the namespace option for our RequireJS optimize build step. And got a "Mismatched anonymous define() module" error for JSON3 and utf8 but if we changed the source code as below we got it to work (not using anonymous define calls).

define('utf8', [], function() {
    return utf8;
});

...

define('JSON3', [], function () {
    return JSON3;
});
bailinx commented 8 years ago

amd-optimize also has this problem

Error: A module must not have more than one anonymous 'define' calls.

darrachequesne commented 3 years ago

That should be fixed in latest release, thanks for the heads-up.