Composer Extra Assets 1.1

I'm happy to announce a new release of composer-extra-assets, the composer plugin for installing bower and npm dependencies.

New in this version is the integration of the nodejs-installer composer plugin by moufmouf. This plugin downloads and installs nodejs binaries locally (in vendor) if not found globally. The installed nodejs can also be used in other php scripts, the installer will put it into vendor/bin/node.

This update basically removes any dependencies from composer-extra-assets, it should be able to be used in any environment.

If you found a bug or have troubles with the plugin please file a bug on github.

This entry was posted in Koala Framework, Web Development by Niko Sams

Source Maps Utilities Php Library

Public Announcement of a new php library for working with source maps: koala-framework/sourcemaps

Source maps help with debugging minified javascript or css files, see the html5rocks article for a short introduction.

This library originated from koala framework where we support source maps created by sass and uglifyjs.

Features

  • creating mappings
  • reading mappings
  • source map aware string replace for existing mapping
  • concat maps (optimized for best performance)

Use cases

Concat into a single file

A common pattern is the creating of a single javascript and css file out of many source files for better performance (as the browser has to make less requests).This library allows concating multiple source maps and keeps the mappings intact.

During development performance is key, so we implemented this concat as performant as possible: we don't parse and write the whole mapping information, instead we only work with the strings and put them together - with an offset correction injected - so the maps stay intact.

String replacements

When different versions of a file need to be generated (eg. translation or replacing a base path) it makes sense to cache the uglifyjs compiled file and do required string replacements on that.

Example usage

//read
$map = new Kwf_SourceMaps_SourceMap($mapContents, $minimiedFileContents);
$map->getMappings()
 
//create new map
$map = Kwf_SourceMaps_SourceMap::createEmptyMap($minimiedFileContents);
$map->addMapping(2, 3, 10, 12, 'foo.js'); //$generatedLine, $generatedColumn, $originalLine, $originalColumn, $originalSource, $originalName = null)
$map->getMapContents();
 
//merge two maps
$map1->concat($map2);
 
//perform string replacement
$map->stringReplace('foo', 'bar');

Found any issue, bug or have a question? Create an issue on github.

This entry was posted in Koala Framework, Web Development by Niko Sams

composer+npm+bower: Assets installation using composer-extra-assets

Short Version: a new composer plugin composer-extra-assets can help with installing bower & npm assets.


Long Version:

Composer is a great piece of software, it solves the problem of installing third party software for php quite nicely.

However a typical web application doesn't exist of php code only. You have got some javascript code that uses jQuery, some carousel, lightbox and whatever jQuery plugin. There might even be some server side running grunt task eg. for building modernizr.

But composer is for php code only, so it won't help us with installing those assets out of the box.

Oh, and there is one more thing that makes our live hard: it must be possible for packages to require assets indirectly, eg. a theme or a module (which is used by a project) must be able to require assets.

What are my options?

Ok, now that we know the requirements, how could this problem be solved?

1. Add assets to version control

While that is common practice for a number of projects it's not really a good idea:

  • Updating libraries is cumbersome
  • Different packages can't share a asset package

2. add asset package repository to root composer.json and install using composer

You can add any git repository in the root composer.json to use as composer package:

   "require": {
        "jquery/jquery": "1.11.1"
    },
    "repositories": [
        {
            "type": "package",
            "package": {
                "version": "1.11.1",
                "name": "jquery/jquery",
                "source": {
                    "url": "https://github.com/jquery/jquery.git",
                    "type": "git",
                    "reference": "1.11.1"
                }
            }
        }
    ]

That solution is quite simple, but:

  • Works for root composer.json only (you can't add repositories in other packages)
  • packages can't specify dependencies to other packages

3. use shim repositories and install them using composer

Shim repositories are built & stripped down versions of packages. You can try to find existing packages or even create your own and add them to packagist.org.

There is even a component-installer plugin and a number of commonly used packages on github.

That solution already works pretty well.

  • includes manual work to replicate the contents of bower & npm repositories to packagist (especially indirect dependencies get cumbersome)
  • new releases have to be pushed by someone
  • not-so-common packages have to be created by yourself
  • this won't help for npm packages

Luckily there are already existing tools - like Php has composer & packagist, there is npm for node and bower for web assets - which both have their own package repositories. So how can we use those repositories in a composer project?

4. create own satis/packagist server containing all bower & npm packages and install them using composer

Re-use the existing npm and bower repositories and build a composer compatible repository out of it's contents.

There is event a proof of concept implementation.

What I think is difficult for this to work properly:

  • That are too many packages that need to be updated regularly
  • Updates will appear with delay
  • This repository needs to be hosted somewhere
  • The repository needs to be added to the root composer.json although it's possibly only required by eg. a theme package

5. create composer plugin that converts all bower & npm packages on the fly to composer packages

To solve some of the issues of (4) this can also be implemented as composer plugin that queries the npm & bower repositories directly.

This also already has a working implementation. (Requires this composer PR to be accepted)

This plugin works pretty good in theory, but in practice is has a few issues:

  • Performance: many requests to github are required to read version information. Problem is that composer is internally a lot different than bower or npm. Caching is possible though
  • Larger dependency chains don't work reliable
  • it's basically a re-implementation of npm and bower clients, so it will always be "behind" (bugs & features)

6. use native bower & npm manually

Or, why not simply use the existing tools (npm, bower) instead of inventing something new?

Obviously this requires those tool being installed.

  • You need to create a bower.json and package.json manually containing all requirements of used packages. Not very convenient.
  • bower install and npm install needs to be called after every composer install, this can be automated by adding scripts to the root composer.json though:
    "scripts": {
        "post-install-cmd": [
            "bower install"
        ],
        "post-update-cmd": [
            "bower install"
        ]
    }

7. use native bower & npm with composer-extra-assets

And finally... drum roll... a solution I have come up with:

composer-extra-assets, a composer plugin that automatically calls bower & npm after package installation and gets required asset packages from all composer packages.

Npm packages will be installed in package folder, bower will be installed in root - with all dependencies merged.

Requirements:

npm needs to be in your path. (no need for bower, that's installed using npm)

Example Usage:

$ cat composer.json 
{
    "require": {
        "koala-framework/composer-extra-assets": "dev-master"
    },
    "extra": {
        "require-bower": {
            "jquery": "*"
        }
    }
}
 
$ composer install 
Loading composer repositories with package information
Installing dependencies (including require-dev)
  - Installing koala-framework/composer-extra-assets (dev-master 0d3324a)
    Cloning 0d3324aeafc33fe21de98aa1ff4dd834ebe32eca
 
Writing lock file
Generating autoload files
 
installing npm dependencies in 'vendor/koala-framework/composer-extra-assets'...
bower@1.3.10 node_modules/bower
├── is-root@1.0.0
├── junk@1.0.0
├── stringify-object@1.0.0
├── which@1.0.5
├── abbrev@1.0.5
├── chmodr@0.1.0
├── osenv@0.1.0
├── opn@1.0.0
├── archy@0.0.2
├── graceful-fs@3.0.2
├── rimraf@2.2.8
├── bower-logger@0.2.2
├── lru-cache@2.5.0
├── bower-endpoint-parser@0.2.2
├── lockfile@1.0.0
├── nopt@3.0.1
├── retry@0.6.1
├── tmp@0.0.23
├── q@1.0.1
├── semver@2.3.2
├── p-throttler@0.1.0 (q@0.9.7)
├── shell-quote@1.4.2 (array-filter@0.0.1, array-red
├── bower-json@0.4.0 (intersect@0.0.3, deep-extend@0
├── request-progress@0.3.1 (throttleit@0.0.2)
├── chalk@0.5.1 (escape-string-regexp@1.0.2, ansi-st
├── fstream@1.0.2 (inherits@2.0.1)
├── mkdirp@0.5.0 (minimist@0.0.8)
├── promptly@0.2.0 (read@1.0.5)
├── fstream-ignore@1.0.1 (inherits@2.0.1, minimatch@
├── glob@4.0.5 (once@1.3.0, inherits@2.0.1, minimatc
├── tar-fs@0.5.0 (mkdirp@0.3.5, pump@0.3.5, tar-stre
├── decompress-zip@0.0.8 (nopt@2.2.1, mkpath@0.1.0, 
├── request@2.42.0 (caseless@0.6.0, json-stringify-s0, node-uuid@1.4.1, qs@1.2.2, mime-types@1.0.2, bl@0
├── bower-registry-client@0.2.1 (graceful-fs@2.0.3, 
├── cardinal@0.4.4 (ansicolors@0.2.1, redeyed@0.4.4)
├── mout@0.10.0
├── bower-config@0.5.2 (osenv@0.0.3, graceful-fs@2.0
├── update-notifier@0.2.1 (string-length@1.0.0, semv
├── inquirer@0.7.1 (figures@1.3.3, mute-stream@0.0.4
├── handlebars@2.0.0 (optimist@0.3.7, uglify-js@2.3.
└── insight@0.4.3 (object-assign@1.0.0, async@0.9.0,
 
installing bower dependencies...
bower jquery#*                  cached git://github.
bower jquery#*                validate 2.1.1 against
bower jquery#*                 install jquery#2.1.1
 
jquery#2.1.1 vendor/bower_components/jquery

...and you have jquery installed in vendor/bower_components/jquery!

Issues

No lock. Bower has no feature like composer's lock file. To work around that always specify tags.

Multiple versions of the same package. If composer package A and package B both require jquery but each with a different version this is not handled correctly yet - you only get a warning currently.

Dependencies. You think having npm/node as a dependency is not a good thing? Well, that is true for production environment, but not for development environment. What we do is building locally and deploying the result (i.e. the vendor folder) to production.


If you have any other issues with this plugin, create an issue or fork me on github.

This entry was posted in Koala Framework, Web Development by Niko Sams

Why I don't like Twitter Bootstrap

Bootstrap is a really great thing, especially for people like me who don't want (and can) create their own layout for a website. Just use bootstrap and everything has nice default styles.

Other modules like the grid system are very handy to create grid based layouts which greatly help when creating responsive websites.

But, you are doing it wrong!

Why? Take a look at this very basic example:

<div class="clearfix">
    <div class="pull-right">
        <button type="button" class="btn btn-primary btn-lg">Settings</button>
    </div>
</div>

what's wrong about it? You are more-or-less using inline styles! (ok - not technically but semantically) And we all know that inline styles are bad.

Using class="pull-right" is exactly the same as style="float:right".

Ok... but what now?

Html should only contain content with classes describing what the element contains:

<div class="footer">
    <div class="buttons">
        <button type="button" class="settingsButton">Settings</button>
    </div>
</div>

With the help of sass, compass and sassy-buttons you can easily add the required styles: 

@import "compass/utilities/general/clearfix";
@import "sassy-buttons";
 
.footer {
    @import clearfix;
    .buttons {
        float: right;
        button.settingsButton {
            @include sassy-button("flat", 15px, 26px, #ffd71a, #ffaa1a);
        }
    }
}
 

Obviously this will not look like the bootstrap version, it's just an example how simple it is to do complex styling without having to repeat yourself.

Another issue is adding additional styling bootstrap doesn't have classes prepared for.  Basically you'll have to add (semantically correct) classes and end up with a mixture of bootstrap and my second example.

Sass libraries

There are many sass libraries, here a short list of popular ones: 

I don't know of a mixin library that provides mixins similar to bootstrap classes. Maybe someone should create one...

Less

What about Less? Less is similar to Sass, you can also use that one. I personally just prefer Sass.

What do you think? Are my concerns valid?

This entry was posted in Web Development by Niko Sams