icambron / twix.js

:hourglass::left_right_arrow: A date range plugin for moment.js
https://isaaccambron.com/twix.js/
MIT License
379 stars 54 forks source link

Problems with gulp-requirejs-optimize #97

Closed dwright213 closed 7 years ago

dwright213 commented 7 years ago

After changing to a setup where I am using gulp to concatenate all of my javascripts into a single file and almond.js to load them as AMDs, I get "Uncaught TypeError: moment(...).twix is not a function" on my files that use twix.

Here's the "define" section from the top of the js file that I use twix on:

define([ 'jquery', 'underscore', 'vendor/moment', 'vendor/twix' ], function($, _, moment) {

In the context of this file, I have access to jquery, underscore, and moment, but running something like moment("1982-01-25T09:30").twix("1982-01-25T13:30") just gets me the same "not a function" error.

I put a "debugger;" inside the twix.js file (line 660) and stepping though the function calls, wound up on line 15: Can't find moment

I feel like there must be some really basic thing about loading modules with almondjs versus loading them over the network with require that I am just not comprehending. There's a lot of moving parts here though, and all my google searches containing the words "almond", "moment", and "twix" seem to mostly get me ads and websites about candybars.

Please let me know if you need more info, and thanks for making this library. I'm pretty sure this is an id10t on my part, so sorry if I'm spamming you with that.

icambron commented 7 years ago

So, I've never used almond.js, so I'm not sure. I'd have expected your define code to work. For example, this file works, albeit with a different AMD implementation.

Here's all the relevant loading code (taken from here), with annotations added about how they might be breaking for you:

# this is a possible failure point. It's meant to handle Node and never AMD, but perhaps it's getting tripped? See the def of `hasModule` at the top of the file
return module.exports = makeTwix(require 'moment') if hasModule

# if your bug came from here, that would mean that Almond isn't respecting Twix's demand for a reference to Moment, which would be odd
if typeof(define) == 'function'
  define 'twix', ['moment'], (moment) -> makeTwix(moment)

# these can't fail because they guard the failure condition. I think.
if @moment
  @Twix = makeTwix(@moment)
else if moment?
  @Twix = makeTwix(moment)

So I guess the trick would be to find what's one stack frame higher in your error; which of these calls to makeTwix is throwing that exception?

dwright213 commented 7 years ago

Thanks for the reply!

It's the second one, it always winds up in the if typeof(define) == 'function'. I tried changing to a relative link to "define" line, so it looks like this:

if typeof(define) == 'function' define 'twix', ['vendor/moment'], (moment) -> makeTwix(moment) (the same way I successfully call moment in other files) but same result, maybe I've got the relative path wrong. In my gulpfile I'm using the requirejs-optimize plugin with the setting findNestedDependencies: true (my thought was that this would be an example of a nested dependency) but it doesn't seem to make a difference.

I'm gonna see if there is some almond or require setting I am overlooking..

icambron commented 7 years ago

OK, at least it's calling the right thing. Yeah, it seems likely that it can't match "moment" to "vendor/moment". Perhaps Almond has an analog to this, which is how you do it in require.js?

require.config({
        paths: {
          moment: "vendor/moment"
        }
});

Then you would change your own define call to just use "moment" and Almond would know to use that path everywhere, including in Twix's own attempt to load it

dwright213 commented 7 years ago

Okay, I'm not sure what exactly was going on there with almond, but I was able to (kind of) sort this out with a shim, so the gulp-requirejs-optimize part of my javascript compiling task looks like this:

.pipe(plugins.requirejsOptimize({
    optimize: 'none',
    logLevel: 4,
    findNestedDependencies: true,
    shim: {
        'twix': {
            deps: ['moment'],
            exports: 'Twix'
        }
    }
}))

At this point, Gulp was telling me no such file or directory, open '/opt/site/static/js/moment.js' (as opposed to "/opt/site/static/js/vendor/moment.js"), so I just edited that same "define" line of twix.js, to look for "vendor/moment" instead of "moment".

I'm sure there's way smarter ways of doing this, but it's almost quittin time today, haha

icambron commented 7 years ago

Going to close this out. LMK if you need more help.