SystemJS Builder – window not defined

I am trying to build my project as a Self-Executing Bundle (SFX) with Gulp and SystemJS-Builder. When I run my gulp task, I keep getting the error, “window is not defined.” I researched the issue and could not find a solution.

Here is my gulp build file

var gulp = require('gulp');
var path = require('path');
var uglify = require('gulp-uglify');
var concat = require('gulp-concat');
var Builder = require('systemjs-builder');

gulp.task('bundle:js', function () {
    var builder = new Builder('MyApplication/application/source', 'MyApplication/application/source/config.js');

    return builder.buildStatic('MyApplication/application/source/app.js', 'MyApplication/application/js/Site.min.js', {
        format: "amd"
    });
});

Here is my SystemJS configuration:

(function () {

    window.define = System.amdDefine;
    window.require = window.requirejs = System.amdRequire;

    var kendoVersion = "2016.3.914";

    var map = {
        text: "../Scripts/text.js",
        app: "app.js",
        main: "main.js",
        aes: "../../../Scripts/aes.js",
        jquery: "../../../Scripts/kendo/" + kendoVersion + "/jquery.min.js",
        kendo: "vendor/kendo/kendo.js",
        DataTables: "../../../Scripts/DataTables/datatables.js",
        k: "../../../Scripts/kendo/" + kendoVersion + "/",
        bootstrap: "../../../Scripts/bootstrap.js",
        lodash: "../../../Scripts/lodash.js",
        moment: "../../../Scripts/moment.js",
        ajaxSetup: "security/ajaxSetup.js",
        q: "../../../Scripts/q.js",
        toastr: "../../../Scripts/toastr.js",
        wizards: "viewmodels/shared",
        'kendo.core.min': "../../../Scripts/kendo/" + kendoVersion + "/kendo.core.min.js"
    };

    var paths = {
        'kendo.*': "../../../Scripts/kendo/" + kendoVersion + "/kendo.*.js",
        jquery: "../../../Scripts/kendo/" + kendoVersion + "/jquery.min.js",
        bootstrap: "../../../Scripts/bootstrap.js"
    };

    var meta = {
        app: { deps: ["kendo", "jquery"] },
        main: { deps: ["jquery"] },
        jquery: { exports: ["jQuery", "$"], format: "global" },
        kendo: { deps: ["jquery"] },
        bootstrap: { deps: ["jquery"] },
        'kendo.core.min': { deps: ["jquery"] },
        DataTables: { deps: ["jquery"], exports: "$.fn.DataTable" },
        toastr: { deps: ["jquery"] }
    };

    var packages = {
        pages: {
            main: 'views/*.html',
            format: 'amd',
            defaultExtension: 'html'
        }
    };

    var config = {
        baseURL: "application/source",
        defaultJSExtensions: true,
        packages: packages,
        map: map,
        paths: paths,
        meta: meta
    };

    System.config(config);
    System.import("main");

})(this);

I load SystemJS in my index page. Here is my Index.cshtml page

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>My Application</title>
    <meta name="description" content=""/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
    @Styles.Render("~/application/css/site.min.css")
    <script src="@Url.Content("~/Scripts/modernizr-2.8.3.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/localStoragePolyFill.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/system.js")" type="text/javascript"></script>
</head>
<body>

    @Html.AntiForgeryToken()
    <div id="applicationHost" class="page-wrap">

        <!-- The application is rendered here -->

    </div>

    <script src="@Url.Content("~/application/source/config.js")" type="text/javascript"></script>

</body>
</html>

I believe the issue is this line of code in the config

window.define = System.amdDefine;
window.require = window.requirejs = System.amdRequire;

Where does the above line of code go if not in the config?

Answer

I have fixed the issue by splitting out the configuration and startup. I previously had the configuration and startup in the same file. My configuration file has configuration only, I have a separate startup file that actually starts the application.

Index.cshtml

@using System.Web.Optimization;

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>My Application</title>
    <meta name="description" content=""/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
    @Styles.Render("~/application/css/site.min.css")
    <script src="@Url.Content("~/Scripts/modernizr-2.8.3.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/localStoragePolyFill.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/system.js")" type="text/javascript"></script>
</head>
<body>

    @Html.AntiForgeryToken()
    <div id="applicationHost" class="page-wrap">

        <!-- The application is rendered here -->

    </div>

    <script src="@Url.Content("~/application/source/startup.js")" type="text/javascript"></script>

</body>
</html>

Startup.js

// make sure we can load AMD files
window.define = System.amdDefine;
window.require = window.requirejs = System.amdRequire;

// fire startup
window.require(["application/source/config.js"], function () {

    // start app once config is done loading
    System.import("main");

});

config.js

System.config({

    baseURL: "application/source",
    defaultJSExtensions: true,
    packages:{
        pages: {
                main: 'views/*.html',
                format: 'amd',
                defaultExtension: 'html'
        }
    },
    map: {
        text: "../Scripts/text.js",
        app: "app.js",
        main: "main.js",
        aes: "../../../Scripts/aes.js",
        jquery: "../../../Scripts/kendo/2016.3.914/jquery.min.js",
        kendo: "vendor/kendo/kendo.js",
        DataTables: "../../../Scripts/DataTables/datatables.js",
        k: "../../../Scripts/kendo/2016.3.914/",
        bootstrap: "../../../Scripts/bootstrap.js",
        lodash: "../../../Scripts/lodash.js",
        moment: "../../../Scripts/moment.js",
        ajaxSetup: "security/ajaxSetup.js",
        q: "../../../Scripts/q.js",
        toastr: "../../../Scripts/toastr.js",
        wizards: "viewmodels/shared",
        'kendo.core.min': "../../../Scripts/kendo/2016.3.914/kendo.core.min.js"
    },
    paths: {
        'kendo.*': "../../../Scripts/kendo/2016.3.914/kendo.*.js",
        jquery: "../../../Scripts/kendo/2016.3.914/jquery.min.js",
        bootstrap: "../../../Scripts/bootstrap.js"
    },
    meta: {
        app: { deps: ["kendo", "jquery"] },
        main: { deps: ["jquery"] },
        jquery: { exports: ["jQuery", "$"], format: "global" },
        kendo: { deps: ["jquery"] },
        bootstrap: { deps: ["jquery"] },
        'kendo.core.min': { deps: ["jquery"] },
        DataTables: { deps: ["jquery"], exports: "$.fn.DataTable" },
        toastr: { deps: ["jquery"] }
    }
});

I am not sure that this is the correct solution, but it did solve the “window not defined” issue.

Leave a Reply

Your email address will not be published. Required fields are marked *