angular-fullstack / generator-angular-fullstack

Yeoman generator for an Angular app with an Express server
https://awk34.gitbook.io/generator-angular-fullstack
6.12k stars 1.24k forks source link

enhancement(gulp): rfc(proposal): modularize/simplify gulpfile #2015

Closed macneib closed 3 years ago

macneib commented 8 years ago

in a generated project instead of gulp.babel.js containing ~780 LOC it would be possible to break task clusters into their own files under the directory of tasks/components

An example:

Overview tasks ├── components │ ├── task-build.js - Build tasks │ ├── task-clean.js - Clean tasks │ ├── task-coverage.js - Coverage tasks │ ├── task-serve.js - Serve tasks ├── task-test.js - all the test tasks ├── task-etc.js - add more tasks to specific files
  ├── config.js   - location of specific client/server files
  ├── utils.js      -  swiss army knife functions

I have to do this for a project now anyway but wasn't sure if a PR on this would be warranted.

Koslun commented 8 years ago

I think there's almost no better time than now to do this. As we're currently in beta on the 4.0.0 canary branch it would be ideal to change the file structure now rather than once it's become stable. The move to Webpack has also deprecated a few tasks, which in turn deprecated even more tasks they were depending on. All in all the gulp file is now slightly smaller at ~669 LOC and I think it can smaller by removing tasks that are not in use anymore (as they're done in Webpack now).

So think a modularization approach would help the work in removing deprecated tasks as well as it just being a generally good idea.

So I like it. Thoughts @Awk34?

EDIT: Did forget to ask if you're instead dead set on changing the 3.X.X branch. As that might not be as interesting but think it would probably be interesting enough. Could likely easily use it as a template to get it up and running in the 4.X.X branch.

Awk34 commented 8 years ago

Yeah, I was going to do this, but as the split-tasks-across-multiple-files recipe states, the way this is done will change in Gulp 4, which I hoped would have been released by now :confused:.

macneib commented 8 years ago

I've been looking around for a nice way to do this myself. So far I'm using this project as a roadmap to get my angular-fullstack project to use ng2 (I have to go to ng2 much sooner than planned)

https://github.com/dsebastien/modernWebDevBuild/tree/master/src/gulp

I'm changing the sematics of the dir structure as I prefer ./tasks/components versus ./gulp/tasks but that's just me. I'm open to ideas on that front.

Waiting for gulp 4.x.x. to land is probably a really smart idea. I really wish there was a firmer release date, because I could take that back to my project and make some timeline changes. No such luck. Still pumped for new gulp though.

Edit: Slightly off topic but I wonder whether going the systemJS/jspm route instead of webpack would offer a more direct route to the ultimate goal of becoming the canonical generator for ng2 scaffolding projects. (just wondering aloud, not pushing that direction)

example gulpfile.babel.js

/* Rather than manage one giant configuration file responsible
 for creating multiple gulp tasks, each task has been broken out into
 its own file. Any files in that directory get automatically required below.

 To add a new task, simply add a new task file that directory.
 gulp/tasks/default.js specifies the default set of tasks to run
 when you run `gulp`.

 Principle taken from gulp-starter: https://github.com/greypants/gulp-starter
 */

"use strict";

let gulp = require("gulp");
let help = require("gulp-help");

help(gulp); // provide help through "gulp help" -- the help text is the second gulp task argument (https://www.npmjs.com/package/gulp-help/)
import requireDir from "require-dir";
import runSequence from "run-sequence";

// Load all tasks in gulp/tasks, including subfolders
requireDir("./gulp/tasks", {
    recurse: true
});

// Default task
gulp.task("default", "Build production files", [ "prepare-default" ], (callback) =>{
    return runSequence("validate-package-json", [
        "scripts-javascript-dist"
    ], callback);
});

gulp.task("prepare-default", "Do all the necessary preparatory work for the default task", (callback) =>{
    return runSequence("clean", [
        "check-js-style",
        "check-js-quality"
    ], callback);
});

example generalTaskLoader.js

import utils from "./utils";

/**
 * Base abstract class for task loaders.
 * Reference: http://stackoverflow.com/questions/29480569/does-ecmascript-6-have-a-convention-for-abstract-classes
 */
export default class GeneralTaskLoader {
    constructor(){
        "use strict";

        // dangerous because of formatting issue in WebStorm (can break this code by splitting new.target in new .target)
        // issue to follow: https://youtrack.jetbrains.com/issue/WEB-18497
        //if(new.target === GeneralTaskLoader) {
        //  throw new TypeError("Cannot construct instances directly");
        //}
    }

    /**
     * Register a task in the provided gulp object.
     * @param gulp the gulp object where the task should be registered
     */
    registerTask(gulp){
        "use strict";

        utils.validateGulpObjectIsConfigured(gulp);
    }
}

example task-ts-lint.js

'use strict';

import GeneralTaskLoader from "../generalTaskLoader";
import config from "../config";
//import utils from "../utils";

import tslint from "gulp-tslint";
import iff from "gulp-if";
import size from "gulp-size";
//import debug from "gulp-debug";

let browserSync = require("browser-sync").get(config.webServerNames.dev);

class TsLintTaskLoader extends GeneralTaskLoader {
    registerTask(gulp){
        super.registerTask(gulp);

        gulp.task("ts-lint", "Lint TypeScript code", () =>{
            return gulp.plumbedSrc(// handle errors nicely (i.e., without breaking watch)
                config.typescript.srcAppOnly // only the application's code needs to be checked
                )

                // Display the files in the stream
                //.pipe(debug({title: "Stream contents:", minimal: true}))

                // Check the code quality
                .pipe(tslint())

                // Fail the build only if BrowserSync is not active
                .pipe(iff(!browserSync.active, tslint.report("prose")))
                .pipe(iff(browserSync.active, tslint.report("prose", {
                    emitError: false
                })))

                // Task result
                .pipe(size({
                    title: "ts-lint"
                }));
        });
    }
}

module.exports = new TsLintTaskLoader();
macneib commented 8 years ago

for the record I went with a significantly simplified variation on this.

Koslun commented 8 years ago

Edit: Slightly off topic but I wonder whether going the systemJS/jspm route instead of webpack would offer a more direct route to the ultimate goal of becoming the canonical generator for ng2 scaffolding projects. (just wondering aloud, not pushing that direction)

I think SystemJS/jspm does seem easier than webpack in general, still having some pains with using webpack myself, so I would guess that it'd be easier to implement for the 3.X.X/master branch too. @Awk34 has however already more or less completed the webpack route on the 4.X.X/canary branch with ng1 so I don't think it would take us to a ng2 scaffold faster at this point by opting for a new solution using SystemJS/jspm unless someone sends in a PR with a working pipeline with feature parity to the webpack solution. Think we would then also only use it as an option to the webpack approach more or less already made available by @Awk34.

macneib commented 8 years ago

@Koslun so far systemJS/jspm has been anything but easy to sort out. I'll gladly share what I have (no PR unfortunately but files if welcomed) once I have it running here.