11

I studied the build tutorial, found the web build (1.7.2 only), and tested several examples - however, I could not find an easy explanation of the build system.

Let's say my app is a single web page:

<script src="./js/App/other_non_amd_stuff_working_independently.js">
<script src="./js/lib/dojo/dojo.js" data-dojo-config="async: true"></script>
<script src="./js/App/Main.js">

The Dojo SDK is in ./lib/, Main.js contains the Dojo config + app boot:

require({
    packages:[{
        name:"App",
        location:"../../App"
    }]
},  
[ "dojo/query",
  "dijit/layout/BorderContainer", 
  "App/Foo",
  "dojo/domReady!"], function(query, BorderContainer, Foo) { ... });

My question now is as simple as this: How can I create one single script file out of all my Dojo/AMD stuff? I just want to replace

<script src="./js/lib/dojo/dojo.js" data-dojo-config="async: true"></script>
<script src="./js/App/Main.js">

with a single

<script src="./js/Main.minified.js">

Getting the build system to work on this seems somewhat non-trivial. It either trys to convert all files in ./App/ to AMD modules (that's not what I want .. yet) or fails to find App/Main. I tried building a build profile (app.profile.js), but I don't get the point of this except that it's adding (IMO unnecessary) complexity. How can I make the build system just concatenate my App/Main.js incl. dependencies ?

Any hints for better tutorials on understanding the build system are appreciated, too.

Maximilian Hils
  • 6,309
  • 3
  • 27
  • 46
  • 1
    I'm trying to do the same thing right now. If I make any progress, I'll let you know. Please do the same. – les2 Aug 16 '12 at 15:55
  • 1
    I just gave up after spending several hours on this. A setup a custom build for a dojo based application "back in the day" and it was a pain then. Now, I'm not really trying to build a dojo application. Just an AMD application. I have a few libraries that I am stringing together. I will stick with r.js - the requirejs optimizer script + bash script. – les2 Aug 16 '12 at 18:15
  • 1
    A solution would be highly appreciated. I'll put a 100 bounty on this one as soon as the question is eligible. – Maximilian Hils Aug 16 '12 at 18:50
  • 1
    There's a +1 from me :) Feel free to bounty even though allready get your answer *gG* – mschr Aug 16 '12 at 20:20
  • 1
    PS: for repeat-builds (you change something and need a new release) delete the release-dir (instead of using overwrite) as it will take about 3 times as long – mschr Aug 16 '12 at 20:25

1 Answers1

4

See this QnA for building your layer into the dojo.js file. I might as well share my experiences, as it has taken me a few trial and errors to get my bootstraps working properly. Actually the answer is easily found within the 'dojosdk/util/buildscripts/profiles/baseplus.profile.js' file.

Dojo Custom Build 1.6 into a single file (same setup as new buildsystem, may still undergo a few changes for 2.0 though)

Howto create main application layer sutured together with dojo.js

dependencies ={
  layers:  [
      {
      name: "dojo.js", // overwrites regular dojo.js and ++'s your layer
      dependencies: [
         "app.main"
      ]
  }
}

Remember to prefix locations properly

Since youre having the 'App' module placed outside the dojo SDK root, the same would need to be applied as you assign packages in dojoConfig. The attribute key though, is instead prefixes for a layer profile.

prefixes: [
    [ "dijit", "../dijit" ],
    [ "dojox", "../dojox" ],
    [ "App", "../../App" ]
]

Howto create sub module layer

You may want to build a sub-module of your App, so that if a popup-dialog for instance requires extra extra - they can be downloaded at runtime in a separate package. To make sure that dependencies, which are allready loaded through your main-module-layer is not included in the sub-module-layer, the attribute key youre looking for is layerDependencies.

It would look like this for a combined result:

dependencies ={
  layers:  [
      {
        name: "../dojo/dojo.js", // overwrites regular dojo.js and ++'s your layer
        dependencies: [
         "app.Main"
        ]
      }, {
        name: "../../App/JITModule.js",
        layerDependencies: [
         "../../App/Main"   // tells this layer that the dependencychain in Main is allready loaded (programmer must make sure this is true ofc)
        ]
        dependencies: [
         "App.JustInTimeDialog"
        ]
      }
  ]
  prefixes: [
    [ "dijit", "../dijit" ],
    [ "dojox", "../dojox" ],
    [ "App", "../../App" ]
  ]
}

This should result in two optimized layerfiles, one with the standard one-line-dojo.js plus a dojo.cache entry, containing the files from your App. Example usage follows. Note, that you still need to call require for any cached modules or they will simply remain in the cache.

Putting it together in HTML

NOTE Putting your dojoConfig into the ./js/App/Main.js file will not work as expected, dojo.js regular contents are loaded above the layers.

<head>
  <script>
     function JITDialog() {
          require([ "App.JITDialog" ], function(dialoglayer)  {
             var dialog = new App.JustInTimeDialog();
             dialog.show();
          });
     }

     var dojoConfig = {
         async: true,
         packages:[{
            name:"App",
            location:"../../App"
         }]
     }
  </script>

  <script src="./js/lib/dojo/dojo.js"></script>

  <script>    
     require("App.Main", function() {
        // loads the layer, depending on the structure of App.Main class,
        // you can call your initializations here
        var app = new App.Main();
        app.run();
     });
  </script>

</head>
<body>
  <button onclick="JITDialog();">
      Download sub-module-layer and show a dialog on user interaction
  </button>
</body>
Community
  • 1
  • 1
mschr
  • 8,531
  • 3
  • 21
  • 35
  • 1
    Thanks a lot for the great reply! Anyway, one question: How do you start the build process? – Maximilian Hils Aug 16 '12 at 21:51
  • 1
    basically **sh /path/to/dojotoolkit/utils/buildscripts/build.sh --profile | --release ** – mschr Aug 17 '12 at 06:16
  • 1
    That's what I was doing: Using the minified file I get a 404 for http://localhost/app/js/selector/acme.js - shouldn't that be included in the main file? – Maximilian Hils Aug 17 '12 at 12:37
  • 1
    Except that: I would prefer a 1.7+ buildfile with `profiles = {...}` - any chance to get this working? Thanks! – Maximilian Hils Aug 17 '12 at 12:54
  • 1
    there will still be a slight amount of browser sniffed stuff. For instance _firebug-lite and like if isDebug flag is set. The acme.js is loaded, If the browser does not support all features of CSS queries which dojo.query supports. Some have native implementation and therefore its a confitional. The 404 error, i dont really get hmm.. Try include `selectorEngine:"acme"` such that it reads `dependencies.selectorEngine` – mschr Aug 17 '12 at 12:55
  • Yes, I tried that already. Doesn't work :/ I have experimented with the new profile definition today, which at least compiles now. The problem is the same here - I get a 404 for acme unless I specify it as an explicit dependency in the profile. This problem also occurs for some other classes, and I have no idea why this is happening. Here's my [profile](https://github.com/mhils/HoneyProxy/blob/dojo_build/gui/js/release.profile.js). Would you mind having a look what might be wrong? Thanks a lot, I really appreciate your help! – Maximilian Hils Aug 17 '12 at 13:48
  • you should find acme.js under /dojo-release-1.X.Y-src/dojo/selector/acme.js. I think youre trying to only copy dojo.js file and not the full toolkit? Since youre 404 is on an url: /app/js/dojo.js, this is because dojo.js is found at url: /app/js/dojo/dojo.js right? - and then dojoConfig.baseUrl = '/app/js'. – mschr Aug 17 '12 at 14:31
  • Correct! My situation is a little bit different. I really don't care about requests a lot (everything is localhost), but I care about size. That's why I don't want to ship the whole dojo toolkit with my release (~8mb), only the few files I need (concatenated together if possible). – Maximilian Hils Aug 17 '12 at 15:52
  • include everything in dojo/ dir then, leave out rest - but remember that language (nls) files are also a just-in-time resource – mschr Aug 17 '12 at 15:59
  • Hum. This leaves me with my original problem, the dojo/ dir is quite heavy. Any other ways to explore? – Maximilian Hils Aug 21 '12 at 11:18
  • considered adding it as dependency?? – mschr Aug 21 '12 at 13:19
  • Adding what as a dependency? In my understanding, the dojo build script searches for dependencies in my main.js and adds them automatically (+ their deps and so on...). My question is why it doesn't add some packages, e.g. acme. Of course, I can add them all manually, but then whats the point of the buildfile again? – Maximilian Hils Aug 21 '12 at 13:45
  • @what: 'dojo/selector/acme'. The point is not to avoid having to upload 5k files to server.. the point is to avoid having to load 250 requests each time a page refreshes. If you have a checkout or the -src package extracted - comments and full-variable names gives a lot of overhead. The buildscript takes this away by optimizing scripts. A build profile will run on *Your* module's dependencies and compile a sutured-cache-file. It will not make include stuff (mentioned in #5 comment) thats only needed for some users (user/browser dependency not module dependency) unless it is told to do so. – mschr Aug 25 '12 at 15:23