3

I am using Kendo UI version 2013.1.514 and RequireJS (r.js version 2.1.6)

My project runs perfectly under the standard RequireJS on-demand loading.

However, when I try to use the optimizer, none of the Kendo will load. Including any of them gives the famous-and-irritation Uncaught Error: Mismatched anonymous define() module: error.

This is my configuration:

{
    "baseUrl": "../Scripts",
    "name": "../Scripts/js_modules/base_module.js",
    "include": [],
    paths: {
        k: "Frameworks/kendo-2013.1.514-fixed",
        jquery: "Frameworks/jQuery/jquery.min",
        jplugin: "Frameworks/jQuery",
        f: "Frameworks/"
    },
    shim: {
        'jquery.dataSelector': {
            deps: ['jquery'],
            exports: 'jquery.dataSelector'
        },

    },
    "exclude": [],
    "optimize": "none",
    "out": "built-base-modules.js"
}

And base_module.js

define( function( require ) {

// Don't do anything with them.
// Just define them.

    require("jquery");
    require("k/kendo.core.min");
    //require("k/kendo.userevents.min");
    //require("kendoize/kendoize")
});

I am not sure if this is related or not, but the dependency tracing does not appear to work correctly either. (It will successfully trace one level deep, but not two levels deep. I had attempted to add core.min and userevents.min manually to see if that resolved the issue.)

Has anyone experienced this issue with Kendo? Or perhaps something similar? I checked through a bunch of existing questions, but didn't find anything connected to this setup.

I can post additional information, if needed, but the detailed console.log message crashed somewhere inside of require.js -- not at a usable syntax error.

Additional Information

The HTML/Javascript on the page itself

    <script src="/Business/Scripts/require.js"></script>

<script>
    (function () {
        "use strict";

        var configObject = {
            shim: {
                'jquery.dataSelector': {
                    deps: ['jquery'],
                    exports: 'jquery.dataSelector'
                },
            },
            baseUrl: "http://760.j6.local:80/Business/Scripts",
                paths: {
                    app: "http://760.j6.local:80/Business",
                    k: "http://760.j6.local:80/Business" + "/Scripts/Frameworks/kendo-2013.1.514",
                    jquery: "http://760.j6.local:80/Business" + "/Scripts/Frameworks/jQuery/jquery.min",
                    jplugin: "http://760.j6.local:80/Business" + "/Scripts/Frameworks/jQuery",
                    f: "http://760.j6.local:80/Business" + "/Scripts/Frameworks/",
                }
            };

            requirejs.config(configObject);
        }());
</script>

    <script src="/Business/_build/built-base-modules.js"></script>
Jeremy J Starcher
  • 23,369
  • 6
  • 54
  • 74

2 Answers2

2

I solved it.

While Kendo does support RequireJS, it uses the 'require' is a dynamic way that is not very friendly to optimizer.

My solution was to write a script that would "unwrap" the script, extract out the needed dependencies and then write the script into a new file.

var kendoFiles = ["kendo.autocomplete.min.js", "kendo.binder.min.js",
  "kendo.calendar.min.js", "kendo.colorpicker.min.js",
  "kendo.columnmenu.min.js", "kendo.combobox.min.js",
  "kendo.core.min.js", "kendo.data.min.js", "kendo.data.odata.min.js",
  "kendo.data.xml.min.js", "kendo.dataviz.chart.min.js",
  "kendo.dataviz.core.min.js", "kendo.dataviz.gauge.min.js",
  "kendo.dataviz.min.js", "kendo.dataviz.sparkline.min.js",
  "kendo.dataviz.stock.min.js", "kendo.dataviz.svg.min.js",
  "kendo.dataviz.themes.min.js", "kendo.dataviz.vml.min.js",
  "kendo.datepicker.min.js", "kendo.datetimepicker.min.js",
  "kendo.draganddrop.min.js", "kendo.dropdownlist.min.js",
  "kendo.editable.min.js", "kendo.editor.min.js",
  "kendo.filtermenu.min.js", "kendo.fx.min.js", "kendo.grid.min.js",
  "kendo.groupable.min.js", "kendo.imagebrowser.min.js",
  "kendo.list.min.js", "kendo.listview.min.js", "kendo.menu.min.js",
  "kendo.mobile.actionsheet.min.js",
  "kendo.mobile.application.min.js", "kendo.mobile.button.min.js",
  "kendo.mobile.buttongroup.min.js", "kendo.mobile.listview.min.js",
  "kendo.mobile.loader.min.js", "kendo.mobile.min.js",
  "kendo.mobile.modalview.min.js", "kendo.mobile.navbar.min.js",
  "kendo.mobile.pane.min.js", "kendo.mobile.popover.min.js",
  "kendo.mobile.scroller.min.js", "kendo.mobile.scrollview.min.js",
  "kendo.mobile.shim.min.js", "kendo.mobile.splitview.min.js",
  "kendo.mobile.switch.min.js", "kendo.mobile.tabstrip.min.js",
  "kendo.mobile.view.min.js", "kendo.multiselect.min.js",
  "kendo.numerictextbox.min.js", "kendo.pager.min.js",
  "kendo.panelbar.min.js", "kendo.popup.min.js",
  "kendo.reorderable.min.js", "kendo.resizable.min.js",
  "kendo.router.min.js", "kendo.selectable.min.js",
  "kendo.slider.min.js", "kendo.sortable.min.js",
  "kendo.splitter.min.js", "kendo.tabstrip.min.js",
  "kendo.timepicker.min.js", "kendo.tooltip.min.js",
  "kendo.touch.min.js", "kendo.treeview.min.js",
  "kendo.upload.min.js", "kendo.userevents.min.js",
  "kendo.validator.min.js", "kendo.view.min.js",
  "kendo.window.min.js"
];

var sourcePath = "../../Scripts/Frameworks/kendo-2013.1.514";
var destPath = "../../Scripts/kendo-rs";


function processFiles() {
  var i = -1;
  var l = kendoFiles.length;

  function nextStep() {
    i++;
    if (i < l) {
      var fileName = kendoFiles[i];
      processOne(fileName, nextStep);
    } else {
      console.log("All finished");
    }
  }
  nextStep();
}

function processOne(fileName, callback) {
  console.log("Processing: " + fileName);

  var fullName = sourcePath + "/" + fileName;
  fs = require('fs');
  fs.readFile(fullName, 'utf8', function (err, data) {
    if (err) {
      console.log(err);
    } else {
      getFileDependencies(fileName, data);
      callback();
    }
  });
}

function saveCode(fileName, code, moduleDependencies) {
  var fs = require('fs');

  var moduleDependenciesString = '"' + moduleDependencies.join('", "') +
    '"';

  var newCode = "define([" + moduleDependenciesString + "]," + "\r\n" +
    code + "\r\n" +
    ");";

  fs.writeFile(destPath + "/" + fileName, newCode, function (err) {
    if (err) {
      console.log(err);
    } else {
      console.log(fileName + " was saved!");
    }
  });
}

function getFileDependencies(fileName, code) {
  // * This is where the magic happens.
  // the kendo modules call define with the dependencies and the function.
  define = function (moduleDependencies, code) {
    for (i = 0; i < moduleDependencies.length; i++) {
      var str = moduleDependencies[i];
      str = str.replace("./", "k/");
      moduleDependencies[i] = str;
    }

    /// OPTIONAL STEP
    /// Set this to your jQuery path.  If you don't include jQuery globally,
    /// you run the risk of a race condition.
    moduleDependencies.push("jquery");

    console.log("Found dependencies: [" + moduleDependencies.join(":") +
      "]");
    saveCode(fileName, code, moduleDependencies);
  };
  define.amd = true; // Needed to make sure define gets called


  try {
    var z = eval(code);
  } catch (e) {
    // Yes, pokeman error handling...
    // We don't care if the code actually runs, so long as 'define' gets called.
  }
}


console.log("Starting");
processFiles();
Jeremy J Starcher
  • 23,369
  • 6
  • 54
  • 74
  • 2
    This sounds like something we (the Kendo UI Team) should address. I will try to reproduce the problem based on your explanations and file it as an issue on our side. – Petyo Ivanov Jun 23 '13 at 11:18
  • @underlog - Sending this in as a ticket has been on my TODO list at work. One of those things I've never gotten around to doing yet. – Jeremy J Starcher Jun 23 '13 at 13:59
  • @underlog Could you please tell me the status of this issue. If you have created the issue please send the link so that i can track the issue. – Sandeepan Nath Sep 03 '13 at 10:36
  • @SandeepanNath - I didn't open the ticket on this one, but to paraphrase the answer: Telerik is considering, in a future release, adding a `/kendo` prefix to the dependency chain. – Jeremy J Starcher Sep 03 '13 at 15:03
1

We have the same problem as described: require.js + kendo + optimization resulting in the very same error after a successful build process.

However, the solution from above does not suite me well as it deals with 3rd party code. I looked for another solution and I found out that if I exclude the whole kendo from the build it will be still downloaded at runtime. I use kendo.mobile.min.js which includes all dependencies and plays nicely with the rest of the project, which is optimized. As a result the whole app needs to download just 3 js files: require, optimized build and kendo.

In other words, if you can afford loading kendo as a separate resource, add the following to the build config:

{
    baseUrl: "...",
    exclude: ['kendo.min'],
    include: ['jquery'],
(...)
}
ikarami
  • 66
  • 2