【问题标题】:usemin and rewriting urls of images in vendor CSS files using Grunt使用 Grunt 在供应商 CSS 文件中使用最小和重写图像的 url
【发布时间】:2013-10-31 11:56:55
【问题描述】:

grunt-usemin 帮助我转变

<link href="/dependencies/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="/dependencies/nanoscroller/bin/css/nanoscroller.css" rel="stylesheet" />
<link href="/dependencies/dropzone/downloads/css/dropzone.css" rel="stylesheet" />

到一个完美组合和缩小的 js:

<link href="scripts/8e1991c7.libraries.js" rel="stylesheet" />

在 concat、cssmin 和 uglify 之后,我有了一个几乎完美的文件夹结构,除了图像及其位置。

这是我的问题:

所有这些供应商的 css 文件都包含图像位置。不好的是,他们都共享不同类型的位置。其中一些在 css 文件夹中使用图像,而另一些在 img 文件夹中使用。

如何配置 grunt usemin 以重写所有图像 url?

【问题讨论】:

    标签: gruntjs yeoman grunt-usemin


    【解决方案1】:

    1) 修订图像。将图像路径添加到 rev 任务中。

    rev: {
        dist: {
            files: {
                src: [
                    '<%= yeoman.dist %>/static/scripts/{,*/}*.js',
                    '<%= yeoman.dist %>/static/styles/{,*/}*.css',
                    '<%= yeoman.dist %>/static/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
                ]
            }
        }
    }
    

    2) 将包含图像位置的文件路径添加到 usemin 任务中。

    usemin: {
        html: ['<%= yeoman.dist %>/{,*/}*.html'],
        css: ['<%= yeoman.dist %>/static/styles/{,*/}*.css'],
        options: {
            assetsDirs: ['<%= yeoman.dist %>','<%= yeoman.dist%>/static/images'],
        }
    }
    

    3) 运行咕噜声。

    【讨论】:

    • 您好,您能解释一下 assetsDirs 的工作原理吗?尝试查看文档/示例,但我仍然不完全清楚。
    • 抱歉,回复晚了,但此配置如何帮助减少 Bower 依赖关系?
    • @Cemo 这不是为了“缩小 bower 依赖”,而是在 html/css 文件中重写图像的路径。
    • 我查看了您的问题,我意识到我的回答根本无法解决您的问题。我通过将所有图像复制到一个文件夹并替换所有引用来解决这个问题:(
    【解决方案2】:

    我已经使用以下方法解决了这个问题。

    useminPrepare: {
        html: 'src/index.html',
        options: {
            dest: 'build',
            flow: {
                html: {
                    steps: {
                        js: ['concat', 'uglifyjs'],
                        css: ['cssmin']
                    },
                    post: {}
                }
            }
        }
    },
    cssmin: {
        options: {
            root: 'src'
        }
    }
    

    首先,我们覆盖 useminPrepareflow,从 css 流中删除 concat 任务。这是必需的,因为 concat 会破坏相对路径信息。由于 cssmin 本身会将多个文件连接在一起,因此单独的 concat 任务只会有害。 (https://github.com/yeoman/grunt-usemin/issues/225)

    最后,我们告诉cssmin,您的项目的“根”来自 Gruntfile。这有助于cssmin 重写它找到的相对于这个“根”目录的相对 url。

    【讨论】:

    • 对于项目中提供的 css 和图像,这看起来像是一个干净的解决方案,但我认为它不能解决供应商提供的 css 引用供应商提供的图像的问题。
    • 假设您有一个供应商在src/vendor/blah 中提供了css/图像,blah/style.css 引用了“image.png”。只要将vendor/blah/image.png 复制到构建目录,就可以完美运行。这是因为编译后的 css 将被重写以引用“vendor/blah/image.png”,而不仅仅是 @Cemo 所面对的“image.png”。
    • 我有 app/bower_components/select2/{select2.css|select2.png}。 select2.css 被 cssmin 连接到 app/{rev}.vendor.css。使用您的解决方案我最终遇到了两个问题:首先,cssmin 假设 png 仍与 css 文件位于同一目录中,它没有意识到 png 仍在 bower_components/select2 中。其次,不管我把什么作为根,我最终都会在 css 文件中得到我的语言环境系统目录的绝对路径。
    • 听起来你在运行cssmin之前还在使用concat任务。如果 only cssmin 运行,我的相对 url 将被重写 'bower_components/select2/select2.png'。
    • 我确实删除了 concat,但我会再次调查。
    【解决方案3】:

    为我修复 CSS background-image revving 的方法是在 options 中添加一个 CSS 模式,它会在 CSS 中查找所有资产引用并将它们替换为 revved 资产。

    // Performs rewrites based on rev and the useminPrepare configuration
    usemin: {
      ...
      ...
      options: {
        ...
        ...
        // This is so we update image references in our ng-templates
        patterns: {
          js: [
            [/(assets\/images\/.*?\.(?:gif|jpeg|jpg|png|webp|svg))/gm, 'Update the JS to reference our revved images']
          ],
          css: [
            [/(assets\/images\/.*?\.(?:gif|jpeg|jpg|png|webp|svg))/gm, 'Update the CSS to reference our revved images']
          ]
        }
      }
    },
    

    【讨论】:

    • 这与assetDirs 相结合让它对我有用。
    • 这是我需要的最后一块。谢谢!
    【解决方案4】:

    我做了一些挖掘,发现了一对看起来可以完成工作的任务:https://github.com/yeoman/grunt-filerevhttps://github.com/richardbolt/grunt-cssurlrev。唯一的问题是您必须手动配置 Gruntfile 中的路径,如下所示:

    grunt.initConfig({
        filerev: {
          images: {
            src: ['img1.png', 'img2.png'],
            dest: 'tmp'
          }
        },
        cssurlrev: {
          dist: {
            src: ['public/css/*.css']
          },
        }
    });
    

    据我所知,没有插件可以自动执行此任务。

    【讨论】:

    • 谢谢。这个插件有点小错误,这就是为什么我必须实现一个类似的。
    【解决方案5】:

    我必须执行一项新任务。这是我的初步实现。

    grunt.registerMultiTask('rewriteCssUrl', 'rewrite url in css', function () {
      var options = this.options({
         assets: grunt.filerev ? grunt.filerev.summary : {},
         postFilter: function identity(input){ return input}
      });
    
      var self = this;
      var assets = options.assets;
    
      self.filesSrc.forEach(function (file) {
         var css = grunt.file.read(file);
         var original = css;
    
         css = css.replace(/(?:src=|url\(\s*)['"]?([^'"\)]+)['"]?\s*\)?/gm, function (match, src) {
            var key = path.join(path.dirname(file), src);
            var asset = assets[path.normalize(key)];
            var val =  options.postFilter(asset);
            return match.replace(src, val || match);
         });
    
         if(original !== css) {
            grunt.log.writeln('✔ '.green + file + (' was changed.').grey);
            grunt.file.write(file, css);
         }
      });
    });
    

    【讨论】:

      【解决方案6】:

      我解决这个问题的方法基本上是为每个供应商样式创建一个单独的styles/select2/select2.css,然后 Grunt 可以将所有相关图像复制到styles/select2(不必担心相对路径或覆盖等)作为一部分的脚本。那就是:

      app/index.html

      <!-- build:css(.tmp) styles/select2/select2.css -->
      <link rel="stylesheet" href="bower_components/select2/select2.css">
      <!-- endbuild -->
      

      Gruntfile.js

      添加一个新的copy 任务,它将在使用cssmin 最小化之前将供应商样式复制到.tmp 目录中:

          copy: {
              // this copies bower_components/*.css into .tmp so they can be compiled
              styles: {
                  expand: true,
                  cwd: '<%= yeoman.app %>',
                  dest: '.tmp/',
                  src: [
                      'styles/{,*/}*.css',
                      'bower_components/**/*.css'
                  ]
              },
              dist: ...
      

      然后,一旦它们被最小化,复制相关资产(在这种情况下,我假设只是 PNG 和 GIF 图像):

              // and once we have compiled all of our stylesheets, we need to also copy over any necessary image files
              distAssets: {
                  expand: true,
                  cwd: '<%= yeoman.app %>/bower_components',
                  dest: '<%= yeoman.dist %>/styles',
                  src: [
                      '**/*.png',
                      '**/*.gif'
                  ]
              }
          },
      

      最后,将新任务添加到build 任务中:

      grunt.registerTask('build', [
          'clean:dist',
          'replace:dist',
          'copy:styles',  // -- added
          'useminPrepare',
          // ... etc ...
          'copy',
          'rev',
          'usemin',
          'copy:distAssets'  // -- added
      ]);
      

      【讨论】:

        猜你喜欢
        • 2013-08-17
        • 2013-04-28
        • 2016-04-21
        • 2012-01-03
        • 1970-01-01
        • 2014-02-17
        • 2015-06-26
        • 2015-03-15
        • 2014-03-30
        相关资源
        最近更新 更多