如何使用Grunt重写供应商CSS文件中图像的URL

29

我正在尝试将前端依赖项移出版本控制系统。Bower.io和Grunt的组合应该能够做到这一点。

然而,我遇到了一个问题,那就是我还无法通过捆绑多个供应商库来解决。例如,假设我有以下目录结构,其中components目录是Bower.io保存依赖项的目录:

├── assets
└── components
    ├── bootstrap
    │   ├── img
    │   │   └── glyhs.gif
    │   └── less
    │       └── bootstrap.css
    └── jquery-ui
        ├── css
        │   └── style.css
        └── images
            ├── next.gif
            └── prev.gif

现在假设我想捆绑jQuery的style.css和Bootstrap的bootstrap.css。我将把这个捆绑后的文件保存在assets/bundled.css中。

然而,在这个文件中,对原始图片(../images/next.gif和../img/glyhs.gif)的引用是不正确的。它们必须被重新编写以使其正常工作(所以../images/next.gif => ../components/jquery-ui/images/next.gif)。我相信重新编写URL是Grunt应该能够做到的事情。但是,使用cssmin/less/copy任务,我似乎无法让它工作。例如,以下Grunt设置(仅移动1个文件)无法工作:

module.exports = function (grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        less: {
            options: {
                compile: false,
                relativeUrls: true
            },
            bootstrap: {
                src: 'components/bootstrap/less/bootstrap.less',
                dest: 'assets/bootstrap.css'
            }
        }
    });
    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.registerTask('dist-css', ['less']);
};

两种可能:

  • 我是否配置Grunt出错或者做错了什么?

  • 或者我描述的工作流程不正确,应该使用其他替代方案。

谢谢!


试试这个...https://dev59.com/o4Hba4cB1Zd3GeqPTZuK#24932294 它对我很有帮助! - Leon
3个回答

6
您可能想查看这个grunt包:https://github.com/Ideame/grunt-css-urls。该包似乎旨在解决您的问题。
编辑:在查看了这个插件之后,我不喜欢重写我的标记以使生成过程更加平滑的想法。因此,我最终编写了自己的小函数来帮助我进行重写。
我使用grunt的concat插件来捆绑我的css文件。这个插件的好处是它支持在连接之前进行文件处理功能。现在我的gruntfile看起来像这样:
grunt.initConfig({
concat: {
    options: {
    separator: '\n',
    process: function (src, filepath) {
        var cssPatt = new RegExp('app(\/.*\/).*\.css$');

        //filter out everithing except css files
        var file = cssPatt.exec(filepath);

        if (file) {
            var urlPatt = /url\(\'(.*)\'\)/g;

        console.log('In file: ' + filepath);

        //replace every url(...) with its absolute path
        return src.replace(urlPatt, function (match, p1) {
            console.log(' * ' + match + ' -> ' + 'url(\'' + file[1] + p1 + '\')');
            return 'url(\'' + file[1] + p1 + '\')';
        });
        }

        return src;
    }
    },
}

感谢您的评论。然而,我的问题现在已经以更加优雅的方式得到解决。我应该更新我的问题:抱歉! - Roel van Duijnhoven
我更新了我的答案。希望你同意这种方法更加简洁。再次感谢! - Roel van Duijnhoven
1
谢谢你的回答!帮助我自己找到了解决方案。然而,你的答案没有检查一行中的多个url()定义,就像Bootstrap 3在其字体定义中所做的那样:src: url('../fonts/glyphicons-halflings-regular.eot?#iefix')format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff')format('woff'),url('../fonts/glyphicons-halflings-regular.ttf')format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular')format('svg'); - Robin van Baalen

5

仅供参考:现在有一个可用的解决方案。我将这个问题发布到了CleanCss grunt插件上,并且他们接受了它并在新的1.1版本中发布了这种行为。

您可以在GitHub跟踪器上找到该问题,链接在这里:https://github.com/GoalSmashers/clean-css/issues/129

该库使得可以使用绝对重写(从根目录)或者基于新的输出目录修改相对图像路径。寻找--root--ouput指令。

感谢大家的提示和回答!


19
可以分享你的配置文件吗?我和你几乎处于同样的情况,但是在配置 usemin 和 cssmin 的时候遇到了一些麻烦。 - Cemo
3
请提供一个Grunt配置文件,展示您的操作步骤,我们无法通过您提供的链接弄清楚具体情况。 - Always Learning

-2

你需要对你的dist css文件进行一些搜索/替换操作,以生成正确的相对路径。有许多grunt插件可以为您完成此操作,个人更喜欢grunt-replace。使用变量设置未压缩的资源,然后生成带有动态生成的URL的dist css。

body {
    background:url(@@IMG_PATH/background.jpg);
}

在dist中变成了这样:

body {
    background:url(path/to/background.jpg);
}

希望这能有所帮助。

1
对于我们自己构建的样式表,这确实可以是一个解决方案。然而,对于供应商库(如示例中提到的Bootstrap和jQuery UI),如果不更改这些文件的内容,则无法完成此操作。 - Roel van Duijnhoven
我认为修改Bootstrap的副本没有任何问题(可以动态地将其作为dist文件夹中的副本,也可以直接在原始文件中进行搜索和替换),毕竟它只是帮助您构建网站的工具。另一种选择可能是复制原始目录结构以保留图像但保留未压缩版本,或者在生产站点上上传组件目录时应该使用符号链接。 - Ben
3
我认为手动更新供应商库不是一个好的实践方法。除了其他方面,这使得更新更加困难。当然,如果以系统化的方式自动完成操作,则可以接受。除了相对路径之外的一种选择是自动将所有图像路径重写为绝对路径。也许通过Grunt可以实现这一点? - Roel van Duijnhoven
是的,使用其中一个搜索和替换插件:https://npmjs.org/package/grunt-text-replace、https://npmjs.org/package/grunt-replacer 或 https://npmjs.org/package/grunt-combine。 - Ben
但是你只能在生产模式下测试应用程序,对吧?没有开发者模式可以进行测试。 - CodyBugstein

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