使用ASP.NET Core,在`project.json`中发布时排除非最小化文件

4
我正在尝试找到一种适当的配置方式,使得在 project.json(ASP.NET Core 1.0 / Full Framework)中的publishOptions不会发布未压缩文件。官方文档没有提供太多帮助:project.json reference
我搜索了通配符模式,并找到一些带有 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": []
},

你本来就不应该把它们放在那里,而是使用gulp清除wwwroot文件夹并复制正确的文件,然后进行实际部署。VS中的默认模板已经提供了min和non-min任务。使用构建服务器,您可以调用特定的任务,首先清除文件夹,然后运行min脚本,将脚本复制和压缩到wwwroot文件夹中,然后运行发布/部署脚本。 - Tseng
1
@Tseng 为了在开发时使用js文件,它们仍然必须位于wwwroot下面,否则如果它们位于其他地方,您将不得不在每次编辑后运行任务。即默认位置是bower组件的wwwroot/lib,因此可以直接从那里使用它们。我认为应该将缩小的文件复制到wwwroot下面的不同子文件夹中,然后可以从发布中排除所有其他开发文件夹。 - Joe Audette
@JoeAudette:不是的。当你在Visual Studio中使用bower或npm时,它们会将它们的依赖项拉入项目根目录下的bower_modulesnode_modules目录中。通常的工作流程是设置一个gulp或grunt任务(取决于你使用/喜欢哪个),并将所需的文件(默认情况下存在不同的任务,可以是最小化或非最小化的)复制到i.e. wwwroot/lib/**。然后,您可以将特定任务绑定到某些事件,如“构建前”和“构建后”。除此之外,您还可以启用监视模式,以便在更改时自动缩小/复制您自己的文件。 - Tseng
小更新。我不好意思,我忘记了他们从默认模板中删除了gulpfile.js文件,因为现在它自带压缩器。我会尝试使用gulp任务放入一个小示例。 - Tseng
@JoeAudette:这就是为什么我通常只限制任务复制所需的文件,而不是复制整个文件夹内容。为什么要麻烦呢?我通常不想在每次部署时都部署50 MB的JavaScript,因为bower/npm将整个包(包括开发人员文件)放入其中,并且通常不希望非minifed/*.ts文件存在于公共文件夹wwwroot中。 - Tseng
显示剩余7条评论
2个回答

7
JavaScript文件/库的典型工作流程是使用gulp或grunt任务将必要的文件复制到“wwwroot”文件夹中,这可能发生在某些事件(预构建、后构建、项目打开、清理)上。
在最新的工具中,默认MVC不再包括gulpfile.js,因为最常见的用法是压缩和捆绑js文件,即使没有使用外部库,所以gulp可能对新用户来说有点困难。
但是它可以很容易地重新引入,当您在解决方案资源管理器中右键单击“bundleconfig.json”文件并选择“Bundler & Minifier”>“Convert to Gulp”时。
这将在项目根目录中创建一个gulpfile.js和package.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']);

看起来比实际复杂。有几个压缩的任务(min:js, min:css)和一个通用的压缩任务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文件,并将它们复制到配置为wwwroot/lib/path.libs中。 app任务对我们自己的代码执行相同的操作。clean清除文件夹(例如,在从调试切换到发布版本之前或发布之前)。
最后,您可以将任务绑定到特定的VS事件。您需要打开“任务运行器资源管理器”视图(视图>其他窗口>任务运行器资源管理器)。在那里,您可以选择一个任务,右键单击它,然后选择“绑定”,并选择一个绑定(在生成之前、在生成之后、清理、项目打开)。它们非常容易理解,“清理”表示当您执行“生成>清理解决方案”时。
现在是发布部分。您可以在发布应用程序时(通过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
虽然这些信息并不完全是我所寻找的,但我真的很感谢你在回答中付出的努力。谢谢。 - lalibi

1
一个简单的替代方案是:
  1. 将未压缩的源文件重命名为*.debug.js和*.debug.css

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

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

我认为未压缩的源代码应该突出并显得不正常。它比压缩后的代码更值得拥有文件名上的瑕疵。

这也使生成的输出文件与其他.NET构建配置保持一致。它清楚地表明您的调试版本可能包括额外的日志记录和调试工具,并且不适用于生产环境。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接