9

私は、jQuery、React、およびSocketIOに依存する「中規模の」Typescriptアプリケーション(自明ではありませんが、エンタープライズレベルでもなく、数千行のように)を持っています-他の小さなライブラリの中でも。

私の現在のgulpfileはこれです:

var gulp = require("gulp"),
    $ = require("gulp-load-plugins")(),
    _ = require("lodash"),
    tsify = require("tsify"),
    browserify = require("browserify"),
    source = require("vinyl-source-stream"),
    debowerify = require("debowerify"),
    watchify = require("watchify"),
    lr = require("tiny-lr"),
    buffer = require("vinyl-buffer");

var lrServer = lr();

var config = {
    scripts: {
        base: __dirname + "/Resources/Scripts",
        main: "Application.ts",
        output: "App.js"
    },

    styles: {
        base: __dirname + "/Resources/Styles",
        sheets: ["Application.less", "Preload.less"],
        autoprefixer: ["last 2 version", "safari 5", "ie 8", "ie 9", "opera 12.1", "ios 6", "android 4"]
    },

    publicPath: __dirname + "/wwwroot"
};

function printError(err) {
    $.util.log($.util.colors.red.bold(err.type + " " + err.name + ":"), $.util.colors.white(err.message));
    this.emit("end");
}

function buildScripts(watch, debug) {
    var bundler = browserify({
            basedir: config.scripts.base,
            debug: false,
            entries: [config.scripts.base + "/" + config.scripts.main],
            cache: {},
            packageCache: {}
        })
        .plugin(tsify, {
            module: "commonjs",
            target: "es5",
            jsx: "react"
        })
        .transform(debowerify);

    function build() {
        return bundler.bundle()
            .on("error", printError)
            .pipe(source(config.scripts.output))
            .pipe($.if(!debug, buffer()))
            .pipe($.if(!debug, $.uglify()))
            .pipe(gulp.dest(config.publicPath + "/" + "scripts"));
    }

    if (!watch)
        return build();

    bundler
        .plugin(watchify)
        .on("update", function () {
            $.util.log($.util.colors.grey("Building scripts..."));
            build();
        })
        .on("time", function (timeMs) {
            $.util.log(
                $.util.colors.grey("Finished"),
                $.util.colors.cyan("'dev.scripts.watch' after"),
                $.util.colors.magenta(timeMs.toLocaleString() + " ms"));
        });

    return build();
}

gulp.task("prod.scripts", function() {
    return buildScripts(false, false);
});

gulp.task("dev.scripts", function () {
    return buildScripts(false, true);
});

gulp.task("dev.scripts.watch", function () {
    return buildScripts(true, true);
});

gulp.task("prod.styles", function () {
    return gulp
        .src(_.map(config.styles.sheets, function (sheet) { return config.styles.base + "/" + sheet; }))
        .pipe($.less())
        .on("error", printError)
        .pipe($.autoprefixer(config.styles.autoprefixer))
        .pipe($.uglifycss())
        .pipe(gulp.dest(config.publicPath + "/styles/"));
});

gulp.task("dev.styles", function () {
    return gulp
        .src(_.map(config.styles.sheets, function (sheet) { return config.styles.base + "/" + sheet; }))
        .pipe($.sourcemaps.init())
        .pipe($.less())
        .on("error", printError)
        .pipe($.autoprefixer(config.styles.autoprefixer))
        .pipe($.sourcemaps.write())
        .pipe(gulp.dest(config.publicPath + "/styles/"));
});

gulp.task("dev.styles.watch", ["dev.styles"], function () {
    return gulp.watch(config.styles.base + "/**/*.{css,less}", ["dev.styles"]);
});

gulp.task("dev.watch", ["dev.scripts.watch", "dev.styles.watch"], function () {
    lrServer.listen(35729);

    gulp.watch(config.publicPath + "/styles/**").on("change", function(file) {
        lrServer.changed({ body: { files: [file.path] } });
    });
});

gulp.task("dev", ["dev.styles", "dev.scripts"]);
gulp.task("prod", ["prod.styles", "prod.scripts"]);

すべてが期待どおりに機能しますが、watch タスクを使用するときのビルド時間は数秒かかります。奇妙なことに、スクリプトの再コンパイルが 500 ミリ秒 (「時間」イベントのイベント ハンドラー) 未満で発生したとタスクが報告しているのに、頭の中でカウントすると、3 ~ 4 秒後まで完了しません。 .

既存の TypeScript コードを貼り付ける前に、jQuery、React、Moment、および使用していたその他のライブラリをすばやくロード/バンドルしていたことに注意してください。このため、別のベンダー バンドルを使用しても速度が向上するとは思いません。また、ソースマップを書き出さなくてもパフォーマンスに影響はないようです。

browserify に切り替える前は、コンパイルに gulp-typescript を使用し、モジュールのロードに requirejs を使用していました。これらのビルドには 1 秒もかかりませんでした。ただし、requirejs は他の理由で問題を引き起こしていました。いずれにせよ、AMD から CommonJS に移行したいと考えています。

今のところ大きな懸念事項ではありませんが、プロジェクトが大きくなるにつれて、開発フローに問題が生じる可能性があります。これだけの規模のプロジェクトでは、これよりも大きなプロジェクトを処理するのにどれくらいの時間がかかりますか?

さらに、Visual Studio でも問題が発生しています。これは ASP.NET 5 アプリケーションであり、Visual Studioはバンドルされた JavaScript ファイルが変更されるたびに再ロード/再解析を要求しているようで、変更のたびに IDE で 1 ~ 2 秒の遅延が発生します。再コンパイル自体には 3 ~ 4 秒かかります。スクリプトは wwwroot フォルダーにレンダリングされており、ASP.NET 5 ツールを使用してスクリプト サブフォルダーを "除外" する方法はないようです。

私はどこかで何かが欠けていることを知っています。考えられる問題は、tsify が typescript の「プロジェクト」機能を使用してリロードを実装していないため、TypeScript コンパイラが変更ごとに各ファイルを再処理することです。

とにかく、おもちゃのプロジェクトを超えてこれらのツールを使用したのは私だけではないので、より良い解決策があるかどうかをここで尋ねています。この問題を除けば、すべてが非常にうまく機能しているためです。

編集 - - - - - - - - - - - - - - - -

わかりました、自分の言葉を食べなければなりません。サードパーティのライブラリを独自のバンドルにバンドルしているため、ビルドは約 1 秒に短縮されています。これが更新された gulpfile です (新しい dev.scripts.vendor タスクと buildScripts 関数の .external 呼び出しに注意してください)

var gulp = require("gulp"),
    $ = require("gulp-load-plugins")(),
    _ = require("lodash"),
    tsify = require("tsify"),
    browserify = require("browserify"),
    source = require("vinyl-source-stream"),
    debowerify = require("debowerify"),
    watchify = require("watchify"),
    lr = require("tiny-lr"),
    buffer = require("vinyl-buffer");

var lrServer = lr();

var config = {
    scripts: {
        base: __dirname + "/Resources/Scripts",
        main: "Application.ts",
        output: "App.js",
        vendor: ["react", "jquery", "moment", "socket.io-client", "lodash", "react-dom"]
    },

    styles: {
        base: __dirname + "/Resources/Styles",
        sheets: ["Application.less", "Preload.less"],
        autoprefixer: ["last 2 version", "safari 5", "ie 8", "ie 9", "opera 12.1", "ios 6", "android 4"]
    },

    publicPath: __dirname + "/wwwroot"
};

function printError(err) {
    $.util.log($.util.colors.red.bold(err.type + " " + err.name + ":"), $.util.colors.white(err.message));
    this.emit("end");
}

function buildScripts(watch, debug) {
    var bundler = browserify({
            basedir: config.scripts.base,
            debug: false,
            entries: [config.scripts.base + "/" + config.scripts.main],
            cache: {},
            packageCache: {}
        })
        .plugin(tsify, {
            module: "commonjs",
            target: "es5",
            jsx: "react"
        });

    if (debug)
        bundler.external(config.scripts.vendor);

    function build() {
        return bundler.bundle()
            .on("error", printError)
            .pipe(source(config.scripts.output))
            .pipe($.if(!debug, buffer()))
            .pipe($.if(!debug, $.uglify()))
            .pipe(gulp.dest(config.publicPath + "/" + "scripts"));
    }

    if (!watch)
        return build();

    bundler
        .plugin(watchify)
        .on("update", function () {
            $.util.log($.util.colors.grey("Building scripts..."));
            build();
        })
        .on("time", function (timeMs) {
            $.util.log(
                $.util.colors.grey("Finished"),
                $.util.colors.cyan("'dev.scripts.watch' after"),
                $.util.colors.magenta(timeMs.toLocaleString() + " ms"));
        });

    return build();
}

gulp.task("prod.scripts", function() {
    return buildScripts(false, false);
});

gulp.task("dev.scripts", ["dev.scripts.vendor"], function () {
    return buildScripts(false, true);
});

gulp.task("dev.scripts.vendor", function() {
    return browserify({
            debug: true,
            cache: {},
            packageCache: {},
            require: config.scripts.vendor
        })
        .bundle()
        .on("error", printError)
        .pipe(source("Vendor.js"))
        .pipe(gulp.dest(config.publicPath + "/" + "scripts"));
});

gulp.task("dev.scripts.watch", ["dev.scripts.vendor"], function () {
    return buildScripts(true, true);
});

gulp.task("prod.styles", function () {
    return gulp
        .src(_.map(config.styles.sheets, function (sheet) { return config.styles.base + "/" + sheet; }))
        .pipe($.less())
        .on("error", printError)
        .pipe($.autoprefixer(config.styles.autoprefixer))
        .pipe($.uglifycss())
        .pipe(gulp.dest(config.publicPath + "/styles/"));
});

gulp.task("dev.styles", function () {
    return gulp
        .src(_.map(config.styles.sheets, function (sheet) { return config.styles.base + "/" + sheet; }))
        .pipe($.sourcemaps.init())
        .pipe($.less())
        .on("error", printError)
        .pipe($.autoprefixer(config.styles.autoprefixer))
        .pipe($.sourcemaps.write())
        .pipe(gulp.dest(config.publicPath + "/styles/"));
});

gulp.task("dev.styles.watch", ["dev.styles"], function () {
    return gulp.watch(config.styles.base + "/**/*.{css,less}", ["dev.styles"]);
});

gulp.task("dev.watch", ["dev.scripts.watch", "dev.styles.watch"], function () {
    lrServer.listen(35729);

    gulp.watch(config.publicPath + "/styles/**").on("change", function(file) {
        lrServer.changed({ body: { files: [file.path] } });
    });
});

gulp.task("dev", ["dev.styles", "dev.scripts"]);
gulp.task("prod", ["prod.styles", "prod.scripts"]);

しかし、私はまだ奇妙な問題を抱えています。ソースマップを無効にすると (現在は速度に影響があるようです)、 on("time", () => {}) コールバックはファイル変更ごとに 60 ~ 80 ミリ秒を報告していますが、それでも約 1 秒間ハングします。 . これを待つのは 1 秒程度なので、プロジェクトが大きくなるにつれて、この待ち時間も長くなる可能性があるのではないかと心配しています。

イベントがはるかに小さなものを報告しているときに、この追加の 1 秒が何に費やされているかを確認するのは興味深いことです。おそらく、誰もすぐに答えを持っていないように見えるので、ソースを少し掘り下げ始めます。

別の問題これは単なる補足ですが、 debowerifyはこれで機能しなくなりました。debowerify+bower を使用すると、そのモジュールが「外部」リストにリストされている場合でも、最終出力で必要なモジュールをレンダリングし続けます。したがって、現在この設定では、アプリ バンドルにコンパイル時間を追加しても問題ない場合を除き、npm モジュールしか使用できません。

また、debowerify は npm モジュールをオーバーライドし、bower 構成ファイルではなく、bower_components のディレクトリ リストに基づいていることを知りました。jQuery を npm にインストールし、Bower でのみブートストラップしました。しかし、ブートストラップが依存関係として jQuery をプルダウンしたため、bower jQuery モジュールが NPM jQuery よりも優先的に読み込まれていました。人々のために頭を上げてください。

4

1 に答える 1

2

これを忘れて、最新のTS + webpackを使用してください:)

于 2016-10-16T21:34:58.783 に答える