Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concat bower components with grunt

I'm building an application which require few front-end lib/frameworks such as:

  • jQuery
  • JQueryUI
  • AngularJS
  • Foundation

I'm using bower to download the components. At this moment my HTML looks like:

<script src="components/jquery/jquery.js"></script>
<script src="components/angular/angular.js"></script>
<script src="components/etc/etc.js"></script>

My goal is to make a grunt script which automatically takes the installed components, concat and minify them and output them as lib.js.

Questions:

With all my researches I figure out how to concat all files from a directory. My goal here is to get the bower components and concat them without listing them one by one in the gruntfile. How I can archieve this?

Also Is it possible to make a custom jQuery UI build with just the modules I want instead of having the entire UI.

Thanks.

like image 459
Deepsy Avatar asked Jan 15 '14 20:01

Deepsy


2 Answers

usemin is your friend here.

Install usemin, copy, concat and uglify:

npm install --save-dev grunt-usemin
npm install --save-dev grunt-contrib-copy
npm install --save-dev grunt-contrib-concat
npm install --save-dev grunt-contrib-uglify

Set up a build block in your HTML file:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>usemin</title>
  <!-- build:js lib.js -->
    <script src="components/jquery/jquery.js"></script>
    <script src="components/angular/angular.js"></script>
    <script src="components/etc/etc.js"></script>
  <!-- endbuild -->
</head>
<body>
<h1>usemin</h1>
</body>
</html>

Set up your Gruntfile:

module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    copy: {
      dist: {
        files: [ {src: 'index.html', dest: 'dist/index.html'} ]
      }
    },

    'useminPrepare': {
      options: {
        dest: 'dist'
      },
      html: 'index.html'
    },

    usemin: {
      html: ['dist/index.html']
    }
  });

  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-usemin');

  grunt.registerTask('default', ['useminPrepare', 'copy', 'concat', 'uglify', 'usemin']);
};

Run grunt

grunt

Results:

├── Gruntfile.js
├── components
│   ├── angular
│   │   └── angular.js
│   ├── etc
│   │   └── etc.js
│   └── jquery
│       └── jquery.js
├── dist
│   ├── index.html
│   └── lib.js
├── index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>usemin</title>
  <script src="lib.js"></script>
</head>
<body>
<h1>usemin</h1>
</body>
</html>
like image 182
steveax Avatar answered Oct 31 '22 03:10

steveax


"My goal here is to get the bower components and concat them without listing them one by one in the gruntfile"

You can take all javascript files from your dependencies directory and sub-directories, and have them concatenated that way:

grunt.config('concat.mydeps', {
  files: [{
    src: ['components/**/*.js'],
    dest: 'dist/lib.js'
  }]
})

... but if the order of script execution is important, this is a recipe for disaster :-).

Also, it's quite likely that these folder would contain minified and non minified versions, leading you to include some scripts twice...

A way to avoid that side effect would be in the line of:

grunt.config('concat.mydeps', {
  files: [{
    src: ['components/**/*.js', '!components/**/*min.js'],
    dest: 'dist/lib.js'
  }]
})

... but again, this is certainly not bulletproof - a given component may very well have a builded version, and a splitted source alongside.

IMHO, the only sane way out is to list explicitly the files you want aggregated, in the order you need (just like you do in your html for now).

like image 22
Mangled Deutz Avatar answered Oct 31 '22 03:10

Mangled Deutz