Opened 7 years ago

Closed 7 years ago

Last modified 7 years ago

#15201 closed defect (worksforme)

dojo/domReady! called yet parser fails to find module in same require deps list

Reported by: Nick Fenwick Owned by: Nick Fenwick
Priority: undecided Milestone: tbd
Component: Loader Version: 1.7.2
Keywords: Cc:
Blocked By: Blocking:

Description

I've been using 1.7 branch (not 1.7.2 release) for a day now and ran into an an issue with the require() loader. I use a single require() statement, with a dependencies list that brings in a large layer module, the parser, and uses dojo/domReady! to wait until the dom is ready before calling the parser.

This fails if mydijits/Deps is built into a single layer file. It works if the same deps list is used in a non-built environment.

require([
        "dojo/parser",
        "mydijits/Deps",
        "dojo/domReady!"
], function(parser) {
        console.log("Calling parser, dijit is: ", dijit);
        parser.parse();
})

Nothing special there. mydijits/Deps is a simple big list of dependencies. Things to point out:

  1. The require callback is called, at which point all dependencies in the require list ought to be loaded.
  2. If I replace the "mydijits/Deps" require dependency with the same massive list of depencies, inline, it works fine, see http://dojo-sandbox.net/public/ebf15/0
  3. I believe none of the required modules have any old dojo.provide stuff in them, though I may be wrong. Since I'm using async:true I did run into trouble with e.g. dojox/cometd until I took that out of the Deps list.

To reproduce:

  1. Fetch 1.7 trunk into a '1.7' directory: svn checkout http://svn.dojotoolkit.org/src/branches/1.7
  2. unpack the attached requireproblem.tgz so you get mydijits, an index file, and a build profile.
  3. cd 1.7/utils/buildscripts
  4. ./build.sh -r -p ../../../test
  5. You now have 'dojostaging' containing the 1.7 branch dojo and mydijits/Deps.js large module layer file.
  6. load index.html in a browser, which will use dojo from the built 'dojostaging' directory

You should see it fail to parse with the error:

Uncaught Error: Could not load class 'dijit.layout.BorderContainer

Yet, BorderContainer is in the Deps.js layer file and should have been in scope when the parser was invoked.

Attachments (5)

requireproblem.tgz (1.0 KB) - added by Nick Fenwick 7 years ago.
Simple test case with Deps.js module, test profile.js and index.html.
build-report_when_using_require.txt (70.7 KB) - added by Nick Fenwick 7 years ago.
Build report when using require() in Deps.js
build-report_when_using_define.txt (66.5 KB) - added by Nick Fenwick 7 years ago.
Build report when using define() in Deps.js
requireproblem_with_package_json.tgz (1.3 KB) - added by Nick Fenwick 7 years ago.
Same build as before, but with 'this is AMD' package.json goodness for mydijits module.
build-report_when_using_require_and_package_json.txt (70.5 KB) - added by Nick Fenwick 7 years ago.
Build report when using require() in Deps.js when Deps.js is declared as AMD.

Download all attachments as: .zip

Change History (13)

Changed 7 years ago by Nick Fenwick

Attachment: requireproblem.tgz added

Simple test case with Deps.js module, test profile.js and index.html.

comment:1 Changed 7 years ago by ben hockey

try changing your require in mydijits/Deps.js to a define. let me know if its still broken

comment:2 Changed 7 years ago by ben hockey

Owner: changed from Rawld Gill to Nick Fenwick
Status: newpending

comment:3 Changed 7 years ago by ben hockey

and if that doesn't fix it... attach a copy of build-report.txt

comment:4 Changed 7 years ago by Nick Fenwick

Status: pendingnew

It's still broken.

Changing "require([list, of, deps])" to "define([list, of, deps])" certainly changes things. Before, mydijits/Deps.js was a massive file containing a concatenation of all the dijits it depended on. After, the build mydijits/Deps.js is a small file, containing:

    //>>built
    
    require(["dojo/i18n"], function(i18n){
    i18n._preloadLocalizations("mydijits/nls/Deps", []);
    });
    define("mydijits/Deps", [
    	"dijit/form/Button",
    	"dojox/layout/ContentPane",
    	"dijit/layout/BorderContainer",
    	"dijit/layout/TabContainer",
    	"dijit/TitlePane",
    	"dojox/widget/FisheyeLite",
    	"dijit/form/Form",
    	"dijit/form/DateTextBox",
    	"dijit/form/TimeTextBox",
    	"dijit/form/CurrencyTextBox",
    	"dijit/form/NumberTextBox",
    	"dijit/form/Button",
    	"dijit/form/CheckBox",
    	"dijit/form/Select",
    	"dijit/form/ComboBox",
    	"dijit/form/ComboButton",
    	"dijit/PopupMenuItem",
    	"dijit/CheckedMenuItem",
    	"dijit/Tree",
    	"dijit/tree/TreeStoreModel",
    	"dojo/data/ItemFileReadStore",
    	"dojo/data/ItemFileWriteStore",
    	"dojox/data/ClientFilter",
    	"dojox/fx/_base",
    	"dojox/form/RangeSlider",
    	"dijit/form/HorizontalRuleLabels",
    	"dojox/validate/regexp",
    	"dojox/widget/Dialog",
    	"dojo/fx/easing",
    	"dojo/fx/Toggler",
    	"dojo/io/iframe",
    	"dojo/currency",
    	"dojox/image/Lightbox",
    	"dijit/TooltipDialog",
    	"dojo/hash",
    	"dijit/_base/scroll"
    ])

I'm not sure what that's supposed to achieve. The index.html then loads Deps.js, but none of that list of dependcies is loaded (dojo/currency.js and so on), and the parser fails with the same error as before, logging that dijit.layout.BorderContainer? isn't defined.

The original attempt used require() in Deps.js, and with Chrome set to 'break on all exceptions' I can see the state at the point the parser is throwing its 'Could not load class 'dijit.layout.BorderContainer?' error, and I can see that the Deps.js containing the definition of dijit.layout.BorderContainer? has been loaded, in the Net pane.

I'll attach the build report from each build scenario, one using require() and one using define() in Deps.js.

Changed 7 years ago by Nick Fenwick

Build report when using require() in Deps.js

Changed 7 years ago by Nick Fenwick

Build report when using define() in Deps.js

comment:5 Changed 7 years ago by Nick Fenwick

I thought you might complain about the 'Module not tagged as pure AMD yet it contains AMD API applications' warning in both build logs about the mydijits module, so I've run another two builds, using require() and define() but with what I think are suitable package.json and mydijits.profile.js files in place that define Deps.js as an AMD module, and get exactly the same results. I'll attach a new tarball and build log for the record.

Changed 7 years ago by Nick Fenwick

Same build as before, but with 'this is AMD' package.json goodness for mydijits module.

Changed 7 years ago by Nick Fenwick

Build report when using require() in Deps.js when Deps.js is declared as AMD.

comment:6 Changed 7 years ago by ben hockey

make sure your module is defined as *something*

define([ ... ], 1);

if i get more time i'll try to run your build and give you the complete solution - for now these are just my best guesses.

comment:7 Changed 7 years ago by ben hockey

Resolution: worksforme
Status: newclosed

not sure if it matters but "none" is not a valid option for layerOptimize or optimize. if you want to have no optimization, use a falsy value like 0 or false. see http://dojotoolkit.org/reference-guide/1.7/build/transforms/writeOptimized.html#profile-knobs

apart from that, i tried what i suggested in my previous comment and it seems that everything works as expected. generally, modules need to be defined via define and they need a value.

note that my tests were conducted on trunk and the 1.7 branch.

comment:8 Changed 7 years ago by Nick Fenwick

This bug is closed, but I wanted to comment, thanks neonstalwart for going over it. I had convinced myself that require([list, of, deps]) was the right syntax in this kind of module, because i ran into trouble using define([list, of, deps]), probably for the reason you hint at, that a define() that returns no object is thrown away by something (loader, builder, who knows).

I've been using require([list, of, deps]) with no problems in production for a couple of months, so I'm rather confused why it worked for me in my main project. Changing to define(blah, 1) did cause breakage in my dojo/ready callbacks, but I managed to change one to dojo/domReady! instead for parser invocation and all seems stable again. Bit of a rocky road.

I've left feedback on the Modules tutorial, asking that the proper approach be documented somewhere.

Note: See TracTickets for help on using tickets.