Grunt usemin and useminPrepare multiple targets
Asked Answered
M

6

28

From the usemin issues it appears that usemin and useminPrepare support multiple targets in the latest version:

Support multiple targets in useminPrepare:

usemin support:

I've tried using multiple targets with the following configuration:

useminPrepare: {
    foo: {
        dest: 'fooDist',
        src: ['foo/index.html']
    },
    bar: {
        dest: 'barDist',
        src: ['bar/index.html']
    }
},
usemin: {
    foo: {
        options: {
            assetsDirs : ['fooDist']
        },
        html: ['fooDist/**/*.html'],
        css: ['fooDist/styles/**/*.css']
    },
    bar: {
        options: {
            assetsDirs : ['barDist']
        },
        html: ['barDist/**/*.html'],
        css: ['barDist/styles/**/*.css']
    }
},

but I receive the following error:

Running "usemin:foo" (usemin) task Warning: Unsupported pattern: foo

Use --force to continue.

Using grunt-usemin 2.0.2

foo/index.html and bar/index.html being the main pages for 2 single page applications.

Thanks for your help!

Munsey answered 11/12, 2013 at 11:25 Comment(3)
Did you ever resolve this?Beck
@SeanAnderson: I ended up using 2 grunt configuration files as a hopefully temporary solution.Unmask
As @sorich87 pointed at the end of the thread here (github.com/yeoman/grunt-usemin/pull/206), multiple targets are supported but NOT multiple destinations yet. See github.com/yeoman/grunt-usemin/issues/157Irredeemable
G
5

by default usemin tries to detect parser type (html,css) from the target name. when you are using a target that it's name is not a valid parser type you should use the type option to specify the parser type manually. this will result in two target for every dest, one for html and one for css.

usemin:{
    'foo-html':
    {
       options:
       {
           assetsDirs : ['fooDist'],
           type:'html'
       },
       files: {src: ['fooDist/**/*.html']}
    },
    'foo-css':
    {
        options:
        {
            assetsDirs : ['fooDist'],
            type:'css'
        },
        files: {src: ['fooDist/styles/**/*.css']}
    },
    'bar-html':
    {
        options:
        {
            assetsDirs : ['barDist'],
            type:'html'
        },
        files: {src: ['barDist/**/*.html']}
    },
    'bar-css':
    {
        options:
        {
            assetsDirs : ['barDist'],
            type:'css'
        },
        files: {src: ['barDist/styles/**/*.css']}
    }
}

https://github.com/yeoman/grunt-usemin/issues/255

Gloucester answered 6/6, 2014 at 16:47 Comment(3)
what about multiply type:'js'?F
@user1828780, also consider referencing assets directly via js is a bad practice and sometimes it's impossible to find all references without executing js code. it's better to avoid this by keeping the separation of concerns, keep behavior in js and representation in css and semantic in html, js can manipulate this layers via css classes and data attributes.Gloucester
When using this with filerev, usemin doesn't replace the built js files with their revisioned file names. Does anyone know of any solution for this?Cruise
M
0

Do you need both projects to live under the same repository and the same Gruntfile?

You said yourself they are "main pages for 2 single page applications". If you can afford to divide it into two different projects, you'll probably save yourself some pain.

Alternatively, you can group both indexes under a common directory. This is how I use grunt-usemin with two different index files:

useminPrepare:
    html: ['build/<%= relativePath %>/index.html', 'build/<%= relativePath %>/orderPlaced/index.html']
    options:
        dest: 'build/'
        root: 'build/'

usemin:
    html: ['build/<%= relativePath %>/index.html', 'build/<%= relativePath %>/orderPlaced/index.html']
Mccullough answered 24/2, 2014 at 12:45 Comment(1)
This is how I would expect it to work, and I tried to use it this way, but with two index files in the same directory.. But for some reason it not working as expected and useminPrepare is not making the combined js files for each html file. No idea how to debug it. Can you refer to the versions of usemin you are using please.Aegis
F
0

Not sure if this will help, but I was able to succeed at doing what you were trying with a combination of Grunt-Contrib-Min and Grunt-Contr

'use strict';

module.exports = function(grunt) {
// Project Configuration
grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    copy: {
      main: {
        options: {
            encoding: 'UTF-16'
          },
        files:[
        {
          expand: 'true',
          flatten: 'true',
          src: 'src/audio/*',
          dest: 'bin/pro/audio/'
        },
        {
          expand: 'true',
          flatten: 'true',
          src: 'src/fonts/*',
          dest: 'bin/pro/fonts/'
        },
        {
          expand: 'true',
          flatten: 'true',
          src: 'src/adaptors/*.html',
          dest: 'bin/pro/adaptors/'
        },
        {
          expand: 'true',
          flatten: 'true',
          src: 'src/lib/*',
          dest: 'bin/pro/lib/'
        },
        {
          expand: 'true',
          flatten: 'true',
          src: 'src/img/*',
          dest: 'bin/pro/img/'
        },
        {
          expand: 'true',
          flatten: 'true',
          src: 'src/manifest.json',
          dest: 'bin/pro/'
        },
        {
          expand: 'true',
          flatten: 'true',
          src: 'src/audio/*',
          dest: 'bin/lite/audio/'
        },
        {
          expand: 'true',
          flatten: 'true',
          src: 'src/fonts/*',
          dest: 'bin/lite/fonts/'
        },
        {
          expand: 'true',
          flatten: 'true',
          src: 'src/adaptors/*.html',
          dest: 'bin/lite/adaptors/'
        },
        {
          expand: 'true',
          flatten: 'true',
          src: 'src/lib/*',
          dest: 'bin/lite/lib/'
        },
        {
          expand: 'true',
          flatten: 'true',
          src: 'src/img-lite/*',
          dest: 'bin/lite/img/'
        },
        {
          expand: 'true',
          flatten: 'true',
          src: 'src/lite/manifest.json',
          dest: 'bin/lite/'
        }
      ]
   },
 },
    uglify: {
        all: {
            files: {
              'bin/pro/js/cupid.min.js': ['src/popup.js','src/cupid.js','src/adaptors/*.js'],
              'bin/pro/background.js': ['src/background.js'],
              'bin/lite/js/cupid.min.js': ['src/popup.js','src/cupid.js','src/adaptors/*.js'],
              'bin/lite/background.js': ['src/background.js'],
              'bin/lite/lite.js': ['src/lite.js'],
              'bin/pro/pro.js': ['src/pro.js'],
            },
            options: {
                compress: false,
                mangle:false
            }
        }
    },
    targethtml: {
      dist: {
        files: {
          'bin/pro/popup.html': 'src/popup.html'
        }
      },
      lite: {
        files: {
          'bin/lite/popup.html': 'src/popup.html'
        }
      },
    },

    cssmin: {
        all: {
            files: {
              'bin/pro/cupid.min.css': ['src/*.css'],
              'bin/lite/cupid.min.css': ['src/*.css'],

            },
            options: {
                compress: true,
                mangle:true
            }
        }
    },
});


//Default task(s).
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-targethtml');

grunt.registerTask('default', ['uglify','cssmin','copy','targethtml']);

};

This Grunt File will take my App directory, output it all into the PRO folder with some special tags added, and also output everything AGAIN to the Lite folder, with other switches set.

Farmann answered 25/2, 2014 at 18:33 Comment(0)
S
0

Although multiple targets are not supported currently in usemin, they do allow you to define new patterns...

So in the meantime you can define new targets using something like:

usemin: {
            html: ['index.html'],
            css: ['styles/{,*/}*.css'],
            options: {
                assetsDirs: ['src'],
                patterns: {
                    templates: [[ /<img[^\>]+src=['"]([^"']+)["']/gm,
                        'Update the templates with the new img filenames'
                    ]]
                }
            },
            templates: "scripts/**/*.tpl.html"
        }
Slavic answered 3/3, 2014 at 16:1 Comment(0)
S
0

As a workaround (struggled with this for a while), we decided to run the entire grunt job twice and added a grunt option which toggled the target file to a different value. Not elegant, but simple.

Salvucci answered 11/3, 2015 at 20:1 Comment(0)
G
0

I was attempting to do something similar where I had multiple pages/templates with different dependent css/js/img files which I wanted to separately process through usemin. You can use a single Gruntfile.js and use a multitask to accomplish multiple targets and destinations with usemin. This would be your gruntfile:

var packageConfig = [];
var gruntConfig = {};
gruntConfig.useminPrepareMulti = {};
gruntConfig.useminPrepare = {};
gruntConfig.usemin = {
  html: [],
  css: [],
  options: {
    assetDirs: []
  }
};

var projectDirs = ['foo', 'bar'];

var src, dist;
projectDirs.forEach(function(dir) {
  src = path1 + dir;
  dist= path2 + dir;
  gruntConfig.useminPrepareMulti[dir] = {
    html: src + '*.html',
    options: {
      dest: dist,
      staging: '.tmp' + dir,
      flow: { html: { steps : { js : ['concat'] } } },
      post: {}
    }
  };
  packageConfig.push(src);
  gruntConfig.usemin.html.push(dist + '*.html');
  gruntConfig.usemin.css.push(dist + '/styles/*.css');
  gruntConfig.usemin.options.assetsDirs.push( dist, dist + '/styles');
});

grunt.initConfig(gruntConfig);

grunt.registerMultiTask('useminPrepareMulti', 'multi-target-usemin', function() {
  grunt.config.set('useminPrepare', this.data);
  grunt.task.run('useminPrepare');
});

With the tasks registered you can run all the different target/dest configurations with:

grunt.registerTask('default', ['useminPrepareMulti']);

Or run them individually from the packageConfig you created:

grunt.registerTask('single', ['useminPrepareMulti:' + packageConfig[0]]);

I also had to modify the usemin blocks in the html code to include the path relative to the root, e.g. :

<!-- build:js(./assets/dir/foo) scripts/vendor.js -->
<script src="scripts/file.js"></script>
<!-- endbuild -->
Gus answered 2/7, 2015 at 15:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.