使用 ASP.NET 核心从 `project.json` 中的发布中排除非缩小文件

Exclude non-minified files from publish in `project.json` with ASP.NET Core

我正在尝试为 project.json(ASP.NET Core 1.0 / Full Framework)中的 publishOptions 找到合适的配置,以便不发布非缩小文件。

官方文档帮助不大:project.json reference.

搜索 globbing 模式,并找到一些带有 gulp 示例的文章,我想出了这个 wwwroot/js/**/*!(*.min.js),但它似乎不起作用。

我的语法有误吗?或者,只是 project.jsondotnet publish 不支持这种语法?

"publishOptions": {
    "include": [
        "wwwroot",
        "Views",
        "Areas/**/Views",
        "appsettings.json",
        "web.config"
    ],
    "exclude": [
        "wwwroot/lib",
        "wwwroot/js/**/*!(*.min.js)",
        "wwwroot/css/*.less",
        "wwwroot/_references.js"
    ],
    "includeFiles": [],
    "excludeFiles": []
},

JavaScript files/libraries 管理的典型工作流程是使用 gulp 或 g运行t 任务将必要的文件复制到 wwwroot某些事件(构建前、构建后、项目打开、清理)时可能发生的文件夹。

在最新的工具中,默认 MVC 不再包含 gulpfile.js,因为最常见的用途是缩小和捆绑 js 文件,即使没有使用外部库也是如此 gulp 可能对于新用户来说有点不知所措。

但是当您在解决方案资源管理器中右键单击 bundleconfig.json 文件并选择 "Bundler & Minifier" > "Convert to Gulp" 时,它可以很容易地恢复。

这会在项目的根目录中创建 gulpfile.jspackage.json(nodejs 依赖项),并将 npm 文件夹添加到解决方案资源管理器的 "Dependencies" 部分。当您在 Windows 资源管理器中观看时,您会在项目根文件夹中看到一个 node_modules 文件夹。这就是 npm 将下载所有包及其依赖项的地方。

生成的 gulpfile.js 看起来像这样并且有一些预定义的任务。我不会使用此文件作为示例,因为它强烈基于 bundleconfig.json 及其结构,并使用我的 gulpfile.json,它曾经与旧模板一起提供。

"use strict";

var gulp = require("gulp"),
    rimraf = require("rimraf"),
    concat = require("gulp-concat"),
    cssmin = require("gulp-cssmin"),
    uglify = require("gulp-uglify");

var webroot = "./wwwroot/";

var paths = {
    app: webroot + "app/",
    libs: webroot + "lib/",
    js: webroot + "js/**/*.js",
    minJs: webroot + "js/**/*.min.js",
    css: webroot + "css/**/*.css",
    minCss: webroot + "css/**/*.min.css",
    concatJsDest: webroot + "js/app.min.js",
    concatCssDest: webroot + "css/app.min.css"
};

gulp.task("clean:js", function (cb) {
    rimraf(paths.concatJsDest, cb);
});

gulp.task("clean:libs", function (cb) {
    rimraf(paths.libs, cb);
});

gulp.task("clean:css", function (cb) {
    rimraf(paths.concatCssDest, cb);
});

gulp.task("clean", ["clean:js", "clean:css", "clean:libs"]);

gulp.task("min:js", function () {
    return gulp.src([paths.js, "!" + paths.minJs], { base: "." })
        .pipe(concat(paths.concatJsDest))
        .pipe(uglify())
        .pipe(gulp.dest("."));
});

gulp.task("min:css", function () {
    return gulp.src([paths.css, "!" + paths.minCss])
        .pipe(concat(paths.concatCssDest))
        .pipe(cssmin())
        .pipe(gulp.dest("."));
});

gulp.task("min", ["min:js", "min:css"]);

gulp.task("libs", function (cb) {
    gulp.src([
        'bootstrap/**/*.js',
        'bootstrap/**/*.css',
        'jquery/**/*.js`, // we can also limit this to `jquery/dist/**/*.js to only include distribution files
        'jquery/**/*.css'
    ], {
        cwd: "node_modules/**"
    })
    .pipe(gulp.dest(paths.libs));
});

gulp.task("app", function (cb) {
    gulp.src([
        'app/**.js'
    ])
    .pipe(gulp.dest(paths.app));
});

gulp.task("default", ['clean', 'libs']);

看起来比实际更复杂。有几个 minizier 任务(min:jsmin:css)和一个通用 minifier 任务 min,它只是 运行 按顺序排列所有其他任务。

wwwroot 中删除输出文件的清理任务。从模板转换时,它仅删除默认的 wwwroot/js/site.min.js 文件。

由于默认模板中没有使用 javascript 库,除了 wwwroot/lib 文件夹中的内容外,包不会以这种方式处理。

所以你可能想要的第一件事是从 npm 中获取 bootstrap 和 jquery 而不是模板提供的静态版本。所以我们将依赖添加到package.json

{
  "name": "app",
  "version": "0.0.0",
  "private": true,
  "dependencies": {
    "bootstrap": "3.3.6",
    "jquery": "2.2.0"
  },
  "devDependencies": {
    "gulp": "3.8.11",
    "gulp-concat": "2.5.2",
    "gulp-cssmin": "0.1.7",
    "gulp-uglify": "1.2.0",
    "rimraf": "2.2.8"
  }
}

例如上面 gulpfile.js 中的 libs 任务会将包的所有必需文件复制到 wwwroot。我说是必需的,因为在包中经常有用于调试和其他东西的未捆绑文件,我们通常不希望在 wwwroot 内(它们可以变得很大)。

gulp.task("libs", function (cb) {
    gulp.src([
        'bootstrap/**/*.js',
        'bootstrap/**/*.css'
    ], {
        cwd: "node_modules/**"
    })
    .pipe(gulp.dest(paths.libs));
});

它将在 node_modules 文件夹中查找 bootstrap 文件夹中的所有 *.js*.css 文件,并将它们复制到已配置的 path.libs作为 wwwroot/lib/

app 任务对我们自己的代码执行相同的操作。 clean 清除文件夹和(即在从调试切换到发布构建之前或发布之前)。

最后,您可以将任务绑定到某些 VS 事件。您需要打开 "Task Runner Explorer" 视图(视图 > 其他 Window > 任务运行器资源管理器)。在那里您可以选择一个任务并右键单击它,然后 "Binding" 并选择一个绑定(构建前、构建后、清理、项目打开)。他们非常自我解释,"Clean" 意味着当你做 "Build > Clean Solution"。

现在到发布部分。当您发布应用程序时(通过 dotnet 或 Visual Studio),您可以 运行 某些命令。

project.json 中有一个脚本部分。

"scripts": {
  "prepublish": [ "npm install", "bower install", "gulp clean", "gulp min", "gulp libs" ],
  "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}

每个条目"prepublish"是一个要执行的命令。在此示例中,在发布开始之前,将首先执行 npm install 以恢复所有 npm 依赖项。然后 bower install 安装由 bower 管理的依赖项(如果你不使用 bower 并通过 npm 完成所有操作,请将其删除)。

接下来的三个命令很有趣,它们将执行 gulp 个任务。我们还可以通过添加 "publish" 任务来简化这一点。

gulp.task("publish", ['clean', 'libs', 'min']);

"scripts": {
  "prepublish": [ "npm install", "bower install", "gulp publish" ],
  "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}

这会将发布所需的所有文件复制到 wwwroot 文件夹,发布文件,然后调用 "postpublish" 脚本。

这是 gulp 中的粗略介绍。它有一个学习曲线,但一旦你开始使用它,它就会改进整个工作流程。

这里没有提到的是添加一个 watch 任务,它可能会查看某个文件夹(我通常使用项目根目录中的 app 文件夹)并且当任何文件在那里更改时 运行 app 任务,所以我们的代码被缩小并复制到 wwwroot 并且在我们调试它时可用。

一个简单的替代方法是:

  1. 将未缩小的源重命名为 *.debug.js 和 *.debug.css

  2. 他们现在更容易排除:

"publishOptions": { "include": [ "wwwroot" ], "exclude": [ "wwwroot/**/*.debug.*" ] }

恕我直言,未缩小的来源应该突出并且看起来不正常。它比压缩代码更值得一个文件名。

这也会使构建输出文件与其余的 .Net 构建配置保持一致。它清楚地表明您的调试版本可能包含额外的日志记录和调试实用程序,并且它不适用于生产。