Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 with RequireJS

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

like image 487
James Avatar asked Jun 02 '16 12:06

James


People also ask

Is RequireJS outdated?

RequireJS has been a hugely influential and important tool in the JavaScript world. It's still used in many solid, well-written projects today.

What is RequireJS used for?

RequireJS is a JavaScript library and file loader which manages the dependencies between JavaScript files and in modular programming. It also helps to improve the speed and quality of the code.

What is RequireJS Shim?

As per RequireJS API documentation, shim lets you. Configure the dependencies, exports, and custom initialization for older, traditional "browser globals" scripts that do not use define() to declare the dependencies and set a module value. - Configuring dependencies.

Is RequireJS synchronous?

So, RequireJS doesn't support it. From your use case it seems that you don't need synchronous RequireJS, you need to return result asynchronously. AMD pattern allows to define dependencies and load them asynchronously, but module's factory function must return result synchronously.


2 Answers

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

like image 180
Gil Epshtain Avatar answered Sep 20 '22 04:09

Gil Epshtain


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

like image 42
Roshan Kumar Avatar answered Sep 19 '22 04:09

Roshan Kumar