【问题标题】:Grunt usemin, get final path of compressed files to allow preloadGrunt usemin,获取压缩文件的最终路径以允许预加载
【发布时间】:2025-11-25 00:15:01
【问题描述】:

我有一个这样的 HTML 块用于缩小 css 和 js 文件:

<!-- build:css static/assets/css/combined.css -->
<link rel="stylesheet" href="static/bower_components/font-awesome/css/font-awesome.css">
<link rel="stylesheet" href="static/bower_components/photoswipe/dist/photoswipe.css" />
<link rel="stylesheet" href="static/bower_components/photoswipe/dist/default-skin/default-skin.css" />
<link rel="stylesheet" href="static/assets/css/jasny-bootstrap.min.css">
<link rel="stylesheet" href="static/assets/css/main.min.css">
<link rel="stylesheet" href="static/assets/css/custom.css">
<link rel="stylesheet" href="static/common/da-angular-spinkit/angular-spinkit.min.css">
<!-- endbuild -->

我需要对资源static/assets/css/combined.css进行预加载,但最终文件的名称末尾有一个哈希,所以最终路径类似于static/assets/css/combined.min-af5890ce41.css,所以我不知道如何包含以下内容标签:

<link rel="preload" href="static/assets/css/combined.min-af5890ce41.css"/>
 -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^

因为我不知道生成的缩小文件的最终名称是什么。

我怎样才能得到这个生成文件的输出?我只需要最终的路径名。我搜索grunt-usemin,但似乎是“极简主义”。

谢谢。

编辑

我在项目中发现了一些 grunt 代码,如果你能看到什么模块正在作用于文件哈希:

/client/static/bower_components/bootstrap/Gruntfile.js:

在这里我可以看到:

  • jshint
  • 丑化
  • csslint
  • cssmin
  • csscomb
  • htmlmin

我看不到这些模块对 index.html 中的 build:jsbuild:css 起作用。

/client/static/bower_components/photoswipe/Gruntfile.js:

在这里我可以看到 npm 任务:

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-sass');
  grunt.loadNpmTasks('grunt-autoprefixer');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-jekyll');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-aws-s3');
  grunt.loadNpmTasks('grunt-svgmin');

编辑 2

在文件夹/dev/ 上有一个带有此代码的 gruntfile.js(似乎不相关):

var src = "../src/client/";

module.exports = function (grunt) {
    grunt.loadNpmTasks("grunt-angular-gettext");

    // We extract translations with 'grunt nggettext_extract'. Those files go to '/dev/translations-extract' directory.
    grunt.initConfig({
        nggettext_extract: {
            pot: {
                files: {
                    'translations-extract/template.pot': [src + 'static/common/**/*.html', src + 'static/states/**/*.html', src + 'index.html', src + 'indexMobile.html']
                }
            },
        },
        // We compile those files (*.po) with 'grunt nggettext_compile. The translations.js file goes to /client/static/util/translations/ dir.
        nggettext_compile: {
            all: {
                options: {
                    module: 'alvarez',
                },
                files: {
                    '../src/client/static/common/translations/translations.js': ['translations-extract/*.po']
                }
            },
        },
    })
}

然后,在/dev/bower_components/ 上有大量插件,每个插件都包含其 gruntfile.js。

编辑 3

/ops/ 一个 gulpfile.js 上找到并且似乎是相关的

/**
 * Crea una versión de distribución concatenada y minificada
 */

var gulp = require('gulp');
var run = require('gulp-run');
var gulpif = require('gulp-if');
var useref = require('gulp-useref');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var debug = require('gulp-debug');
var del = require('del');
var ngAnnotate = require('gulp-ng-annotate');
var minifyHTML = require('gulp-minify-html');
var cleanCSS = require('gulp-clean-css');
var rev = require('gulp-rev');
var revReplace = require('gulp-rev-replace');
var embedTemplates = require('./embed-templates/index.js');
var dist = './dist/';
var indexDist = dist + 'client/';
var HTMLDist = indexDist + 'static/';
var src = '../src/';
var assetsSrc = src + 'client/static/assets/'
var cssSrc = assetsSrc + 'css/';
var serverDist = dist + 'server/';
var libDist = dist + 'lib/';

// pm2
// Init-dist
gulp.task('pm2', function () {
    run('pm2 start ' + serverDist + 'alvarez.js').exec();
});

// Init-stop
gulp.task('pm2-stop', function () {
    run('pm2 stop ' + serverDist + 'alvarez.js').exec();
});

//Init-restart
gulp.task('pm2-restart', function () {
    run('pm2 restart ' + serverDist + 'alvarez.js').exec();
});

// npm-install on dist
gulp.task('npm-install-dist', function () {
    run('npm install --production --prefix ' + serverDist).exec();
})

// Dist subtasks

// Cleaning dist
gulp.task('del-dist', function () {
    del(dist, {
        force: true
    }, console.log('Files deleted'));
});

// Moving index.js
gulp.task('move-server-js', function () {
    return gulp.src([src + 'server/alvarez.js', src + 'server/package.json'])
        .pipe(gulp.dest(serverDist));
});

gulp.task('move-config-js', function () {
    return gulp.src([src + 'server/lib/**/*.js'])
        .pipe(gulp.dest(serverDist + 'lib/'))
})

//gulp.task('move-lib-js', function () {
//    return gulp.src(src + 'lib/config.js')
//        .pipe(gulp.dest(libDist));
//});
//
//gulp.task('move-boot-pro', function () {
//    return gulp.src(src + 'lib/boot.pro.js')
//        .pipe(rename('boot.js'))
//        .pipe(gulp.dest(libDist));
//})

// Moving html
gulp.task('move-html', function () {
    var opts = {
        empty: true
    };
    return gulp.src([src + 'client/static/**/**/*.html', src + 'client/static/**/**/*.swf'])
        .pipe(minifyHTML(opts))
        .pipe(gulp.dest(HTMLDist));
});

gulp.task('minify-css', ['move-assets', 'move-html-index', 'move-html-index-mobile'], function() {
    return gulp.src(HTMLDist + 'assets/css/*.css')
        .pipe(cleanCSS())
        .pipe(gulp.dest(HTMLDist + 'assets/css/'));
})

gulp.task('move-assets', function () {
    return gulp.src(src + '/client/static/assets/**/*.*')
        .pipe(gulp.dest(HTMLDist + 'assets/'));
});

// Moving html index
gulp.task('move-html-index', function () {
    var assets = useref.assets();
    //.pipe(gulpif('**\/da-*.js', embedTemplates()))
    return gulp.src(src + 'client/index.html')
        .pipe(assets)
        .pipe(gulpif('*.js', embedTemplates()))
        .pipe(gulpif('.*\.js', ngAnnotate()))
        .pipe(gulpif('.*\.js', uglify()))
        .pipe(rev())
        .pipe(assets.restore())
        .pipe(useref())
        .pipe(revReplace())
        .pipe(debug())
        .pipe(gulp.dest(indexDist));
});

gulp.task('move-html-index-mobile', function () {
    var assets = useref.assets();
    return gulp.src(src + 'client/indexMobile.html')
        .pipe(assets)
        .pipe(gulpif('*.js', embedTemplates()))
        .pipe(gulpif('.*\.js', ngAnnotate()))
        .pipe(gulpif('.*\.js', uglify()))
        .pipe(assets.restore())
        .pipe(useref())
        .pipe(gulp.dest(indexDist));
})

gulp.task('embed-templates', [], function () {
    return gulp.src([src + 'client/static/states/**/da*/*.js', src + 'client/static/common/**/da*/*.js'])
        .pipe(gulpif('*.js', embedTemplates()))
        .pipe(ngAnnotate())
        .pipe(uglify())
        .pipe(gulp.dest(indexDist))
});

// Build dist task
gulp.task('build-dist', ['move-html', 'move-server-js', 'move-config-js', 'minify-css'], function () {
    console.log('Dist ready...');
});

【问题讨论】:

  • 请把Gruntfile.js的内容贴出来
  • @muecas 完成,代码更新,如果您需要更多,请告诉我。
  • 不,Gruntfile.js 与问题无关。也许您可以检查项目中的所有Gruntfile.js 文件。或者只是发布这个/client/static/bower_components/photoswipe/Gruntfile.js的内容。也许你有其他的Gruntfile.js 控制这个问题。
  • 是的,我的主要问题是找不到正确的 gruntfile。我已经通过搜索两天了,这是因为我决定在 * 上提问,哈哈。我会努力找出正确的 gruntfile。
  • 哈哈,那太好了。找到整个项目中的所有Gruntfile.js。您需要检查所有文件。

标签: angularjs gruntjs preload grunt-usemin


【解决方案1】:

grunt-usemin 中的答案是否定的,但在依赖项之一中:grunt-filerev。最后一个模块是用来创建你cssjs和其他文件的文件修订的。

grunt-filerev 执行后(作为grunt-usemin 的子任务执行),它会创建一个摘要(存储在您的 grunt 任务中,在grunt.filerev.summary 下)。摘要包含以下信息:

{
   “original.js” : “destination.59bcc35a.js”
}

因此您可以稍后在您选择的字符串替换方法/模块中使用它。

你可以找到更多关于grunt-filerevhere的信息。

希望对你有帮助。

【讨论】:

  • 好吧,这似乎合乎逻辑,但我是该项目的新手,并且没有更多的开发人员可以询问。我在所有项目的代码中都没有找到关于 filerevgrunt-hashgrunt-file-hash 的任何信息。如果文件grunt.filerev.summary 存在,我在哪里可以找到它?
  • 假设哈希文件名可以通过这种方式获得,将grunt-usemin的块注释(即&lt;!-- build:css static/assets/css/combined.css --&gt;)更新为反映新哈希文件名的注释仍然是一个问题。为此,您可以使用带有grunt-text-replace 的正则表达式(例如this one),并在这样的任务中配置fromtoreplacements: [{ from: /(&lt;!-- build:css static\/assets\/css\/)(.*?) --&gt;/g, to: '$1' + hashedFileName + ' --&gt;' }]- 其中hashedFileName 是检索到的引用。
  • 它本身不是文件。当您运行grunt 任务时,数据会临时存储在 grunt 任务本身中。所以你应该使用另一个任务来替换你的文件名的哈希版本,在你可以使用的其他文件中。预加载的css的链接写在哪里?
  • 您可以使用@RobC 解释的技术;让我为您提供一个如何实现这一目标的工作示例。
  • Marcos,强调 "Assuming" 在我之前的评论中是有意的,据我了解,它无法检索(警告:我没有使用 grunt-usemin,也不是filerev)。提示:通过执行my answer here) 之类的操作,您自己在构建中生成随机哈希。一旦您创建了哈希引用,它可以为您在构建中的其他地方提供更大的控制。如果你将 Gruntfile.js 的相关部分添加到你的 OP 中,我会看看我是否可以访问 refs 来散列。
最近更新 更多