10

I am having issues getting Angular2 to load correctly when incorporating RequireJS into the application.

For simplicity wise I am using the very simple Hello World Javascript tutorial on the Angular2 located here : https://angular.io/docs/js/latest/quickstart.html

I have this system working fine using Angular1 but I can't seem to replicate this success using Angular2.

Here is my index.html file:

<html>
<head>
    <title>Angular 2 QuickStart JS</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- 1. Load RequireJS -->
    <script type="text/javascript", src="bower_components/requirejs/require.js", data-main="/require.config.js"></script>

</head>

<!-- 3. Display the application -->
<body>
    <ireland-product-app>Loading...</ireland-product-app>
</body>

My require.config.js file:

require([
    'assets/requiredPathsAndShim.js'
], function(requirePathsAndShim) {
require.config({

    baseUrl: '/',

    paths: requirePathsAndShim.paths,

    shim: requirePathsAndShim.shim,

    /// Kick start app...
    deps: ['app/main']
});

});

I use the requiredPathsAndShim.js file to load all the dependencies I see that are required to start an Angular2 application. Here is the file:

"use strict";

(function(define) {
    define([], function() {
        return {
            waitSeconds : 10000,
            paths: {

                'shim'              : 'node_modules/core-js/client/shim.min',
                'zone'              : 'node_modules/zone.js/dist/zone',
                'Reflect'           : 'node_modules/reflect-metadata/Reflect',
                'Rx'                : 'node_modules/rxjs/bundles/Rx.umd',
                'core'              : 'node_modules/@angular/core/core.umd',
                'common'            : 'node_modules/@angular/common/common.umd',
                'compiler'          : 'node_modules/@angular/compiler/compiler.umd',
                'platform-browser'  : 'node_modules/@angular/platform-browser/platform-browser.umd',
                'platform-dynamic'  : 'node_modules/@angular/platform-browser-dynamic/platform-browser-dynamic.umd'
            },
            shim : {

            }
        }
    });
})(define);

I then load the 'app/main' file from my 'required.config' file which will load the bootstrap functionality of Angular2:

"use strict";

(function() {
    define([
        'app/app.component'
    ], function(app) {
        document.addEventListener('DOMContentLoaded', function() {
            ng.platformBrowserDynamic.bootstrap(app.AppComponent);
        });
    });
})();

The app/app.component file is a file which simply returns my Angular2 component which is passed into the main.js bootstrap function to start the app. this is the file:

"use strict";

(function() {
    define([

    ], function() {
        return {
            AppComponent : ng.core.Component({
                    selector : 'ireland-product-app',
                    template : '<h1>Product App</h1>'
                })
                .Class({
                    constructor : function() {}
                })
        }
    });
})();

I have been playing around with this for a few hours and can't seem to get this working. Can anyone point me in the right direction as to why this isn't working? I have a feeling some shims need to be added into the require.config but I have had no success setting script load dependencies as of yet.

Thanks

3
  • 1
    I know you don't want to hear this, but you are going to have a much easier time if you use System or WebPack (or even Browserify) with Angular2. System has support for asynchronous lazy loading as well. In addition you may want to look into using the ES6 module syntax with TypeScript, as it allows you to write your module imports once, and target whichever module system you choose. This decouples your code from a specific module system. Commented Jun 2, 2016 at 12:20
  • @martin, I need to do same thing, because our existing system uses requirejs and don't mind using system, but I think best is to load from existing code, since angular1 and angular2 will be co-host together until angular1 is completely removed. Commented Aug 18, 2016 at 20:54
  • 2
    I have the same problem - I try to run Angular2 app using RequireJS. But please notice that for RequireJS load some file, this file need to be in AMD syntax meaning the file need to be written inside a define([], function(){ ... }) block. However the Angular2's scripts are written with different syntax - with a import/export statement. Therefore Require can't load them, and the export key word (in the Angular2 scripts) throw an error - unexpected character - on the export key word. Commented Nov 20, 2016 at 13:26

2 Answers 2

15

What you are trying to do isn't possible (well, in software engineering, like in art - everything is possible, but to achieve this you'll need to edit the angular's script, and we don't want this).

Not like Angular1, which was developed in ECMAScript5 (the loved JavaScript language), Angular2 was developed in ECMAScript6 (and in TypeScript).

One of the differences is that in ECMAScript5 in order to load a script file (.js, .ts, etc.) we need to add a <script> tag with src attribute, which point to the script file. The alternative was to use 3rd party library, which loaded the scripts asynchronously (example for libraries like this are: RequireJS, WebPack, SestemJS, etc.).

The main disadvantage of RequireJS, is that it only works on scripts that are written in a AMD format (Asynchronous Module Definition), for example:

define(['dependence_1', 'dependence_2', ...], function(alias_1, alias_2, ...) {
// ...
});

This syntax is very efficient when working with Angular1 and RequireJS.

Now, when we look at Angular2 library we can see that it isn't written in AMD syntax, meaning it can't be loaded using RequireJS - without rewriting the code into AMD format. Angular2 is expecting you use some kind of universal module loader. The keyword here is universal, meaning a module loader that can load all kinds of script formats (AMD modules, CommonJS modules and ES6 modules). Examples of universal module loaders are: WebPack and SystemJS.

Now let's talk about the solution to your problem, I believe that you'll need to migrate from RequireJS to Webpack - since the migration isn't so complicated.

Step#1 - 3rd Party Libraries

When loading 3rd Party Libraries with RequireJS, we are using RequireJS's path and shims, that can be easily converted into Webpack's alias. But this isn't needed: once you are working with Webpack, you have a npm support. This mean that you can run npm install library-name and now you can use this library without RequireJS.

Step#2 - Application scripts

Fortunately for us we almost don't need to do nothing here. Since Webpack is a universal module loader, it can load scripts in AMD format. So all the application scripts that was developed in the RequireJS format, can be loaded using Webpack without any change.

For more info on how to migrate from RequireJS to Webpack see this article: https://gist.github.com/xjamundx/b1c800e9282e16a6a18e

Sign up to request clarification or add additional context in comments.

Comments

1

I was facing same issue what @devoncrazylegs faced..

My solution: Configure paths array used in require.config() in tsconifg.ts --> compilerOptions-->paths

Read below link to understand more

https://www.typescriptlang.org/docs/handbook/module-resolution.html#base-u

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.