javascriptnode.jstypescriptgulptsify

Bundle a typescript library to one .js file and one .d.ts


I'm developing a library to use in the webbrowser using TypeScript.

I'm writing separate typescript files as modules using "system" as --module, for example this is the main file:

/// <reference path="../typings/tsd.d.ts" />
/// <reference path="./typings/simple-html-tokenizer/simple-html-tokenizer" />

export * from "./Decorators/Component";
export * from "./Decorators/Directive";
export * from "./Decorators/Inject";
export * from "./Decorators/Injectable";
export * from "./Events/EventEmitter";
export * from "./Core/Bootstrap";
export * from "./Decorators/Output";
export * from "./Decorators/Input";
export {OnChanges, OnInit, OnDestroy} from "./Core/LifeCycle/LifeCycleHooks";

And this is the first module:

import {serviceNormalize} from "../Utils/AngularHelpers";

export interface IComponentMetadata {
    template?: string;
    templateUrl?: string;
    selector?: string;
    directives?: Function[];
    outputs?: string[];
    inputs?: string[];
    styles?: string[];
    providers?: (Function|string)[];
}

/**
 * Register metadata into class to be used by bootstrap.
 */
export function Component(componentMetadata: IComponentMetadata) {
    return (target: any) => {

        /// ...
        /// ...
        /// ...

        return target;
    }
}

Well, I'm building it using gulp-typescript, I transpile it to es5 and create one .js and one .d.ts file per each .ts file. So far so good, I have a npm package and I can use my project from other npm projects. But ...

I want to use it from the webbrowser too. I would like to bundle all .js files in one and use this way:

<script src="~/Scripts/Ng2Emulation-bundle.js"></script>

I have generated a .d.ts file using dts-bundle and I have tried to bundle the .js files from two ways:

  1. Using concat:

    gulp.src('dist/js/src/**/*.js') .pipe(concat('Ng2Emulation-bundle.js')) .pipe(gulp.dest('dist/release'));

  2. Using tsify:

    browserify() .add('src/ng2emulation.ts') .plugin(tsify, { noImplicitAny: false }) .bundle() .on('error', function (error) { console.error(error.toString()); }) .pipe(gulp.dest("Ng2Emulation-bundle.js"));

Two ways create the bundle but when I try to use it from the browser it tries to load each module, getting errors like:

GET http://localhost:55411/Utils/AngularHelpers.js 404 (Not Found)D @ system.js:4(anonymous function) @ system.js:4(anonymous function) @ system.js:4V @ system.js:5t.metadata.deps @ system.js:5r @ system.js:5n @ system.js:5r @ system.js:5(anonymous function) @ system.js:5(anonymous function) @ system.js:4
system.js:4 GET http://localhost:55411/Templates/HttpInterceptor.js 404 (Not Found)D @ system.js:4(anonymous function) @ system.js:4(anonymous function) @ system.js:4V @ system.js:5t.metadata.deps @ system.js:5r @ system.js:5n @ system.js:5r @ system.js:5(anonymous function) @ system.js:5(anonymous function) @ system.js:4
system.js:4 GET http://localhost:55411/Directives/NgProperty.js 404 (Not Found)D @ system.js:4(anonymous function) @ system.js:4(anonymous function) @ system.js:4V @ system.js:5t.metadata.deps @ system.js:5r @ system.js:5n @ system.js:5r @ system.js:5(anonymous function) @ system.js:5(anonymous function) @ system.js:4
system.js:4 GET http://localhost:55411/Templates/HtmlParser/Parser.js 404 (Not Found)

I'm using Visual Studio 2013, an MVC ASP.NET application. My main html (_layout.cshtml) is like it:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <link href="~/node_modules/angular-material/angular-material.css" rel="stylesheet"/>
    <script src="~/Scripts/jquery-2.2.0.js"></script>
    <script src="~/Scripts/angular.js"></script>
    <script src="~/Scripts/angular-aria.js"></script>
    <script src="~/Scripts/angular-animate.js"></script>
    <script src="~/Scripts/angular-messages.js"></script>
    <script src="~/node_modules/angular-material/angular-material.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.15/system.js"></script>
    <script type="text/javascript">
        // set our baseURL reference path
        System.config({
            baseURL: '/TypeScript',
            map: {
                "HTML5Tokenizer": "/Scripts/simple-html-tokenizer.js",
                "Ng2Emulation": "/Scripts/Ng2Emulation-es5.js"
            }
        });
        System.defaultJSExtensions = true;

        System.import('App/Boot');
    </script>
</head>
<body>
    @RenderBody()
    @RenderSection("scripts", required: false)
</body>
</html>

And this is my App/Boot.ts:

import {bootstrap, Component} from "Ng2Emulation";

@Component({
    selector: "my-app",
    template: "<h1>My First Angular 2 App</h1>"
})
export class AppComponent { }

bootstrap(AppComponent);

I have tried to load the bundle via: <script src="~/Scripts/Ng2Emulation-bundle.js"></script> and remove the Ng2Emulation map from system.config but I don't have luck :(

I think that there is something that I don't understand in the bundle creation process or in the modules behaivor ...

How to bundle it? How could I do it?


Solution

  • Yeah, after deep search I have found one way. I have found systemjs builder project. I have wrote a task in my gulp file, this way:

    gulp.task("system-builder", function () {
        var builder = new Builder('dist/js/src');
    
        builder.config({
            meta: {
                'HTML5Tokenizer.js': { // HTML5Tokenizer is a external módule
                    build: false       // Not to include in a bundle.
                }
            },
            defaultJSExtensions: true
        });
    
        builder
            .bundle('Ng2Emulation.js', 'dist/release/Ng2Emulation-bundle.js')
            .then(function () {
                console.log('Build complete');
            })
            .catch(function (err) {
                console.log('Build error');
                console.log(err);
            });
    });
    

    I have found it looking at Angular2 gulp files :D Now I can include the file using html script tag, my html is like that:

    <script src="~/Scripts/simple-html-tokenizer.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.15/system.src.js"></script>
    <script type="text/javascript">
        // set our baseURL reference path
        System.config({
            baseURL: '/TypeScript',
            map: {
                "HTML5Tokenizer": "/Scripts/simple-html-tokenizer.js"
            }
        });
        System.defaultJSExtensions = true;
    </script>
    <script src="~/Scripts/Ng2Emulation-es5.js"></script>
    <script type="text/javascript">
    
        System.import('App/Boot');
    </script>
    

    It works like a charm.

    Still, if anyone knows other ways to do I would like to know. I don't understand what mudule system is better, when use one or other, ...