linemanjs / lineman

Lineman helps you build fat-client JavaScript apps. It produces happiness by building assets, mocking servers, running specs on every file change
MIT License
1.18k stars 82 forks source link

Are there guidelines to upgrade my linemanjs angular 1 environment to anguar 2? #388

Closed ghost closed 8 years ago

ghost commented 8 years ago

Thus far I've integrated TypeScript and replaced ng-app with a manual bootstrap. The next step is to add the angular 2 libraries which appear to be handled quite differently from their angular 1 siblings.

Before I embark on my own journey of figuring this out by myself I thought asking whether anyone on the linemanjs community has a cookbook to share!

Best Rodrigo

searls commented 8 years ago

Hi Rodrigo, I don't think we have any good prior art on this. I recommend that you take the work you've done so far and strip it down to a bare minimum to post some place as an example for others. Thanks!

ghost commented 8 years ago

Introduction

I started this journey with the intent to integrate the new NG2 with the existing NG1 build process; this seemed reasonable since my goal was to build an environment for the development of hybrid NG1 / NG2 applications.

There are fundamental differences between how NG1 and NG2 are built:

Approach

Well into the process to build the NG1 / NG2 integrated build environment, I came to the conclusion that the correct course of action would be to build the NG2 environment to be completely separate from the NG1 environment, but to co-exist. Once I reached this conclusion, it became obvious that this was the correct approach since once we migrate all of our NG1 software to NG2 we want to also seamlessly remove all of the NG1 build artifacts and software, which would be hard to do should the two be tightly intertwined.

With this in mind, the following changes were made:

files

See below for my config/files.js code and some ensuing comments:

module.exports = function(lineman) {
    //Override file patterns here
    return {
        dlabs: {
            targetIq: "../../../target/iq"
        },
        js: {
            vendor: [
                "vendor/js/hmac-md5.js",
                "vendor/js/hmac-sha1.js",
                "vendor/js/hmac-core-min.js",
                "vendor/js/hmac-enc-utf16-min.js",
                "vendor/js/hmac-enc-base64-min.js",
                "vendor/js/jquery.js",
                "vendor/js/bootstrap.js",
                "vendor/js/angular.js",
                "vendor/js/**/*.js"
            ],
            app: [
                "app/js/app.js",
                "app/js/**/*.js"
            ],
            concatenatedVendor: "generated/js/appVendor.js",
            "minifiedVendor": "dist/js/appVendor.js",
        },

        less: {
            compile: {
                options: {
                    paths: [
                        "vendor/css/angular-strap-docs.min.css",
                        "vendor/css/angular-strap-libs.min.css",
                        "vendor/css/bootstrap.css",
                        "vendor/css/**/*.css",
                        "vendor/components/**/*.css",
                        "app/ng2/styles.less",
                        "app/css/**/*.less"
                    ]
                }
            }
        },

        ng2: {
            libs: [
                "systemjs.config.js",
                "node_modules/@angular/**",
                "node_modules/systemjs/**",
                "node_modules/core-js/**",
                "node_modules/reflect-metadata/**",
                "node_modules/rxjs/**",
                "node_modules/zone.js/**",
                "node_modules/angular2-in-memory-web-api/**"
            ],
            css: [
                // used in conjunction with the CWD option
                "**/*.css"
            ],
            html: [
                // used in conjunction with the CWD option
                "**/*.html"
            ],
            "systemjs": {
                generated: "generated/",
                dist: "dist/"
            },
            ts: [
                // used in conjunction with the CWD option
                "**/*.ts"
            ],
            generated: "generated/ng2",
            dist: "dist/ng2"
        },

        webfonts: {
            root: "fonts"
        }
    };
};

Notes:

application

See below for my config/application.js code and some ensuing comments:

/* Exports a function which returns an object that overrides the default &
 *   plugin grunt configuration object.
 *
 * You can familiarize yourself with Lineman"s defaults by checking out:
 *
 *   - https://github.com/linemanjs/lineman/blob/master/config/application.coffee
 *   - https://github.com/linemanjs/lineman/blob/master/config/plugins
 *
 * You can also ask Lineman"s about config from the command line:
 *
 *   $ lineman config #=> to print the entire config
 *   $ lineman config concat.js #=> to see the JS config for the concat task.
 */
module.exports = function(lineman) {
    // DO NOT REMOVE
    var app = lineman.config.application;

    //Override application configuration here. Common examples follow in the comments.
    return {
        // grunt-angular-templates assumes your module is named "app", but
        // you can override it like so:
        //
        // ngtemplates: {
        //   options: {
        //     module: "myModuleName"
        //   }
        // }

        server: {
            pushState: true
            // API Proxying
            //
            // During development, you"ll likely want to make XHR (AJAX) requests to an API on the same
            // port as your lineman development server. By enabling the API proxy and setting the port, all
            // requests for paths that don"t match a static asset in ./generated will be forwarded to
            // whatever service might be running on the specified port.
            //
            // apiProxy: {
            //   enabled: true,
            //   host: "localhost",
            //   port: 3000
            // }
        },

        loadNpmTasks: lineman.config.application.loadNpmTasks.concat("grunt-contrib-copy", "grunt-exec", "grunt-contrib-clean", "grunt-ts"),

        /* *************************************************************************************************************
         * Task Definition
         ************************************************************************************************************ */

        clean: {
            "vendor": ["vendor"],
            "generated": {
                src: "<%= files.ng2.generated %>" + "/*",
                options: {
                    force: true
                }
            },
            "targetIq": {
                src: "<%= files.dlabs.targetIq %>" + "/*",
                options: {
                    force: true
                }
            }
        },

        "concat_sourcemap": {
            "js": {
                "src": [
                    "<%= files.js.app %>",
                    "<%= files.coffee.generated %>",
                    "<%= files.template.generated %>"
                ],
                "dest": "<%= files.js.concatenated %>"
            },
            "vendor": {
                "src": [
                    "<%= files.js.vendor %>"
                ],
                "dest": "<%= files.js.concatenatedVendor %>"
            }
        },

        copy: {
            "dl-deploy-dev": {
                files: [
                    {
                        expand: true,
                        cwd: "generated/",
                        src: ["**"],
                        dest: "<%= files.dlabs.targetIq %>"
                    },
                    {
                        expand: true,
                        flatten: true,
                        dest: "../../../target/iq/css",
                        src: [
                            "vendor/static/fonts/ui-grid.ttf",
                            "vendor/static/fonts/ui-grid.woff"
                        ]
                    }
                ]
            },
            // Copies the ng2 libraries to the target folder, instead of generated.
            // Copying to generated and then to target is too expensive while watching.
            "ng2-libs-to-target": {
                files: [
                    {expand: true, src: "<%= files.ng2.libs %>", dest: "../../../target/iq/" }
                ]
            },
            "ng2-css-files-to-generated": {
                // See Copy files to different directory (https://github.com/gruntjs/grunt-contrib-copy/issues/58)
                // I used to ensure that the compiled ts files (js / map) and their companions (ts / html / css) landed on the same folder
                expand: true,
                cwd: "app/ng2",
                src: "<%= files.ng2.css %>",
                dest: "<%= files.ng2.generated %>"
             },
            "ng2-files-to-generated": {
                // See Copy files to different directory (https://github.com/gruntjs/grunt-contrib-copy/issues/58)
                // I used to ensure that the compiled ts files (js / map) and their companions (ts / html / css) landed on the same folder
                expand: true,
                cwd: "app/ng2",
                src: ["<%= files.ng2.css %>", "<%= files.ng2.html %>"],
                dest: "<%= files.ng2.generated %>"
            },
            "ng2-html-files-to-generated": {
                // See Copy files to different directory (https://github.com/gruntjs/grunt-contrib-copy/issues/58)
                // I used to ensure that the compiled ts files (js / map) and their companions (ts / html / css) landed on the same folder
                expand: true,
                cwd: "app/ng2",
                src: "<%= files.ng2.html %>",
                dest: "<%= files.ng2.generated %>"
            },
            "ng2-ts-files-to-generated": {
                // See Copy files to different directory (https://github.com/gruntjs/grunt-contrib-copy/issues/58)
                // I used to ensure that the compiled ts files (js / map) and their companions (ts / html / css) landed on the same folder
                expand: true,
                cwd: "app/ng2",
                src: "<%= files.ng2.ts %>",
                dest: "<%= files.ng2.generated %>"
            },
            "ng2-files-to-dist": {
                // See Copy files to different directory (https://github.com/gruntjs/grunt-contrib-copy/issues/58)
                // I used to ensure that the compiled ts files (js / map) and their companions (ts / html / css) landed on the same folder
                expand: true,
                cwd: "app/ng2",
                src: ["<%= files.ng2.css %>", "<%= files.ng2.html %>"],
                dest: "<%= files.ng2.dist %>"
            },
            // Copies the angular 2 libraries to the dist folder.
            // Executed by the "lineman build" command
            "ng2-libs-to-dist": {
                files: [
                    {expand: true, src: "<%= files.ng2.libs %>", dest: "dist/"}
                ]
            },
            "systemjs-to-dist": {
                src: "systemjs.config.js",
                dest: "<%= files.ng2.systemjs.dist %>"
            },
            "systemjs-to-generated": {
                src: "systemjs.config.js",
                dest: "<%= files.ng2.systemjs.generated %>"
            }
        },

        // Added this to fix the following error:
        // Warning: Path must be a string. Received null Use --force to continue.
        // found out about this error here: https://github.com/jshint/jshint/issues/2922
        jshint: {
            options: {
                reporterOutput: ""
            }
        },

        // Task to compile typescript files
        // Look here for config options: https://www.npmjs.com/package/grunt-ts
        ts: {
            development: {
                "src": "app/ng2/**/*.ts",
                "outDir": "<%= files.ng2.generated %>",
                "options": {
                    "emitDecoratorMetadata": true,
                    "module": "system",
                    "moduleResolution": "node",
                    "noImplicitAny": false,
                    "removeComments": false,
                    "sourceMap": true,
                    // using es5 is problematic with NG2-beta
                    // http://stackoverflow.com/questions/33332394/angular-2-typescript-cant-find-names
                    "target": "es6"
                }
            },
            production: {
                "src": "app/ng2/**/*.ts",
                "outDir": "<%= files.ng2.dist %>",
                "options": {
                    "emitDecoratorMetadata": true,
                    "module": "system",
                    "moduleResolution": "node",
                    "noImplicitAny": false,
                    "removeComments": false,
                    "sourceMap": false,
                    // using es5 is problematic with NG2-beta
                    // http://stackoverflow.com/questions/33332394/angular-2-typescript-cant-find-names
                    "target": "es6"
                }
            }
        },

        uglify: {
            vendor: {
                files: {
                    "<%= files.js.minifiedVendor %>": "<%= files.js.concatenatedVendor %>"
                }
            }
        },

        /*
         Custom watch to copy changed files to the target folder based on suggestion by justin@testdouble.com
         */
        watch: {
            "systemjs-config-js": {
                "files": "systemjs.config.js",
                "tasks": ["copy:systemjs-to-generated"]
            },
            // renamed & deleted files remain in place, restarting lineman run will fix it
            "ng2-css": {
                "files": "<%= files.ng2.css %>",
                "tasks": ["copy:ng2-css-files-to-generated"]
            },
            // renamed & deleted files remain in place, restarting lineman run will fix it
            "ng2-html": {
                "files": "<%= files.ng2.html %>",
                "tasks": ["copy:ng2-html-files-to-generated"]
            },
            // renamed & deleted files remain in place, restarting lineman run will fix it
            "ng2-ts": {
                "files": "<%= files.ng2.ts %>",
                "tasks": ["ts:development"]
            },
            target: {
                "files": [
                    "systemjs.config.js",
                    "app/**/*",
                    "spec/**/*",
                    "spec-e2e/**/*"],
                "tasks": "copy:dl-deploy-dev"
            }
        },

        webfonts: {
            files: {
                "vendor/components/FontAwesome/fonts/": "vendor/static/fonts/FontAwesome.*",
                "vendor/components/fontawesome-webfont/fonts/": "vendor/static/fonts/fontawesome-webfont.*",
                "vendor/components/glypicons-halflings-regular/fonts/": "vendor/static/fonts/glypicons-halflings-regular.*",
                "vendor/components/ui-grid/fonts/": "vendor/static/fonts/ui-grid.*"
            }
        },

        /* *************************************************************************************************************
         * Workflow Definition
         ************************************************************************************************************ */

        /*
         I struggled with getting this right. I got it to work after carefully reading:
         - Creating Lineman Plugins http://linemanjs.com/#creating-lineman-plugins
         - https://github.com/linemanjs/lineman-dogescript/blob/master/config/plugins/dogescript.coffee#L13-L14
         */
        prependTasks: {
            dev: [
                "clean:targetIq",
                "clean:generated",
                "copy:ng2-libs-to-target",
                "ts:development",
                "copy:ng2-files-to-generated",
                "copy:dl-deploy-dev"].concat(app.prependTasks.dev),
            common: ["concat_sourcemap:vendor", "dl-install-libs"].concat(app.prependTasks.common),
            dist: [
                "copy:ng2-libs-to-dist",
                "ts:production"].concat(app.prependTasks.dist)
        },
        appendTasks: {
            dist: [
                "uglify:vendor",
                "copy:systemjs-to-dist",
                "copy:ng2-files-to-dist"].concat(app.appendTasks.dist)
        },
        removeTasks: {
            dev: ["server"]
        }
    };
};

Notes: