Utilities

All the little things that add up to win.

Mimosa comes with Bower support built in via the mimosa-bower module.

What is Bower?

This is how Bower describes itself:

Bower is a package manager for the web. It offers a generic, unopinionated solution to the problem of front-end package management, while exposing the package dependency model via an API that can be consumed by a more opinionated build stack. There are no system wide dependencies, no dependencies are shared between different apps, and the dependency tree is flat.

It mentions an "opinionated build stack". That would be Mimosa. Mimosa wraps Bower with its opinions of where Bower managed assets should be placed. Mimosa will handle placement on its own when it can, but it provides configuration to control placement at a fine-grained level if that is necessary.

mimosa new created projects will include a bower.json that mimosa-bower will use to pull in both jQuery and require.js when you run Mimosa for the first time.

"I know what Bower is and I don't want it!"

Before Mimosa v1.0.0, mimosa-bower existed, but was not an automatically included module. That means it is not tied in to the core of Mimosa in any way and can be removed without any side effects. Just remove bower from your list of modules.

How does Mimosa use Bower?

$ mimosa bower
21:16:50 - Info - Starting Bower install...
21:16:51 - Info - mimosa-bower created file assets/javascripts/vendor/requirejs/require.js
21:16:51 - Info - mimosa-bower created file assets/javascripts/vendor/jquery/jquery.js
21:16:51 - Info - Cleaned temp bower output directory .mimosa/bower/bower_components
bower:
  bowerDir:
    path: ".mimosa/bower/bower_components"
    clean: true
  copy:
    enabled: true
    trackChanges: true
    outRoot: null
    exclude:[]
    unknownMainFullCopy: false
    mainOverrides: {}
    strategy: "packageRoot"
    forceLatest: true
    pathMod: []

When mimosa bower, mimosa watch or mimosa build are executed, Mimosa will assess whether or not any packages need to be installed and install them to the bower.bowerDir.path directory, by default .mimosa/bower/bower_components. Mimosa will also watch the bower.json for changes while running mimosa watch and if any changes occur, Mimosa will immediately kick off a Bower install.

If bower.copy.trackChanges is set to true (the default), Mimosa keeps track of two artifacts to help it determine if installs need to occur. First, it keeps track of the bower.json that was last used for an install. If the current bower.json is different, an install will be executed. Second, Mimosa keeps track of the bower section of your project's mimosa-config for the last install. If it changes, an install will be executed.

If bower.copy.trackChanges is set to false and bower.bowerDir.clean is set to false, Bower default processing will check to see if an install is necessary based on the contents of the bower.bowerDir.path. If it detects that nothing has changed, no install will be run.

If bower.copy.trackChanges is set to false and bower.bowerDir.clean is set to true (not recommended), then Mimosa has no way to determine if an install is necessary so the Bower functionality does not register itself to be run during mimosa watch and mimosa build. In this case it must be executed using the mimosa bower command.

If any packages are installed, Mimosa then moves them into the vendor directories as indicated by Mimosa's vendor config. The bower.copy.strategy determines how the files are copied over. They can be copied to the root of the vendor directory (vendorRoot), to the root of the component directory (packageRoot, the default), or can be copied keeping the entire folder structure intact, none.

Mimosa requires a valid bower.json at the root of project (in the same directory as mimosa-config).

If Bower encounters any version collisions, it will automatically choose the latest version for that library because the forceLatest flag is set to true. If it is not set to true, the Bower install will error out and the collision will need to be addressed.

If Mimosa cannot identify the main files for a package because it hasn't been provided by the package author, Mimosa will indicate that via a console log message. The bower.copy.mainOverrides can be used to indicate which files from the package are to use used.

The Configuration page has details on how to use mainOverrides and strategy to properly place the right files from Bower modules in the desired project location.

And this gist covers a real world mainOverrides example which includes all the various ways to use mainOverrides to place files.

Mimosa comes with loads of AMD/RequireJS support all provided by the mimosa-require module. That module will...

  • Verify paths when JavaScript successfully compiles. Mimosa will follow relative paths for dependencies, and also use config paths whether they resolve to an actual dependency, jquery: 'vendor/jquery', or they resolve to a module, moduleX:'a/path/to/module/x'.
  • Detect dependencies embedded within define and require callbacks. i.e. deferred require calls.
  • Verify map, shim and package paths, and keep track of those configs for path verification.
  • Verify plugin paths.
  • Notify when paths are broken. An unresolved path is as crucial as a compiler error: code is broken.
  • Catch circular dependencies and notify on the console.
  • Catch when a non-vendor piece of compiled JavaScript isn't wrapped in require or define and notify you on the console.
  • Run RequireJS' optimizer when the optimize flag is enabled for mimosa build, and on every file change for mimosa watch.
  • Need no config at all for the optimizer, which takes some time to configure. Mimosa will keep track of dependencies and build a vanilla optimizer configuration.
  • Use your modules config to create many r.js outputs for your dynamic requirejs calls.
  • For complex r.js configurations, allow modification of pre-built inferred configs rather than needing from-scratch configurations.
  • Handle multi-page applications with multiple modules.
  • Detect and use common RequireJS configuration used across multiple modules
  • Only compile those modules that need compiling based on changed code.
  • Bundle optimized JavaScript with Almond
18:59:06 - ERROR - RequireJS dependency controller for path alias c, inside file /public/javascripts/main.js, cannot be found.
18:59:22 - ERROR - RequireJS shim ang inside file public/javascripts/main.js refers to a dependency that cannot be found vendo/modernizr.
18:59:33 - ERROR - RequireJS dependency c/gitHu, inside file /public/javascripts/main.js, cannot be found.
18:59:43 - ERROR - RequireJS mapping inside file public/javascripts/main.js, for module * has path that cannot be found vendor/angular-resourc.
require:
  exclude:[]
  commonConfig:"common"
  tracking:
    enabled: true
    path: ".mimosa/require/tracking.json"
  verify:
    enabled: true
    plugins:
      css: "css"
      hbs: "hbs"
  optimize :
    modules: null
    moduleCachingPath: ".mimosa/require/moduleCaching"
    inferConfig:true
    overrides:

Path verification can be turned off using the configuration shown here. Set require.verify.enabled to false. For information about how Mimosa uses RequireJS to optimize your application, check out the Optimization tab.

Path verification is always disabled for vendor assets, that is, assets in the configured vendor.javascripts directory. Vendor assets often use creative means to turn themselves into AMD modules that prove hard to verify. That said, if a vendor asset is placed outside the vendor folder, Mimosa is coded to handle how some of the methods vendor assets are AMDed. But Mimosa may complain that some vendor assets are throwing errors or are not properly wrapped.

Mimosa also has the ability to cache dependency information between Mimosa runs, making startup time fast for large applications.

To read more about Mimosa's RequireJS support, head over to the Optimization page.

To 'lint' code is to check it for common mistakes or variances from the idiom. Using the mimosa-csslint and mimosa-jshint modules, Mimosa will automatically lint all of the CSS and JavaScript it moves from source directories to compiled directories. Any errors or warnings that come out of linting will be printed to the console but will not stop or fail the compilation. The config snippets to the right control the linting for a project's CSS and JavaScript.

Linting Compiled Assets

The compiled flags control whether or not linting is enabled for compiled code. So when Mimosa compiles SASS, LESS or Stylus, Mimosa will send the resulting CSS through a linting process. Similarly for the JavaScript transpilers, Mimosa will lint the resulting JavaScript.

Linting Copied Assets

The copied flags determine whether or not to lint copied files, like hand-coded JavaScript and CSS.

jshint:
  exclude:[]
  compiled: true
  copied: true
  vendor: false
  jshintrc: ".jshintrc"
  rules: {}

csslint:
  exclude:[]
  compiled: true
  copied: true
  vendor: false
  rules: {}

Linting Vendor Assets

Linting is, by default, disabled for vendor assets, that is, those assets located inside the vendor.javascripts or vendor.stylesheets directory. Vendor libraries often break from the idiom or use hacks to solve complex browser issues for you. For example, when run through CSSLint, Bootstrap emits 400+ warnings.

To enable vendor asset linting, uncomment and set the vendor flag to true.

Lint Rules

The rules block is where linting rules for each of the linting tools are overridden or changed. Example overrides are provided in the default configuration. Those are examples, they are not actual overrides.

Default Rules

For CoffeeScript and IcedCoffeeScript some jshint rules are turned off by default. Those compilers output JavaScript that violates jshint and there is nothing that can be done other than turn the rules off. So when compiling those files, Mimosa will turn off the listed rules by default.

boss: true
eqnull: true
shadow: true
expr: true

JSHint, CSSLint

Both of the lint/hinters come with default configurations that Mimosa uses. Here are links to the tools, as well as to the configuration for those tools.

Mimosa provides live reload support by default via the mimosa-live-reload module. Live reload will immediately refresh a page any time an asset is compiled or a view changes.

mimosa-live-reload handles CSS and JavaScript assets differently. For CSS the page does not need a full reload. The new CSS is re-evaluated without reloading anything other than the CSS. The page is simply repainted. When JavaScript assets are updated, the entire page refreshes. (Note: With version 2.3 of Mimosa, live reload of CSS is handled differently in Chrome. See the Release Notes for details.)

This sounds like a fairly small nice-to-have feature, but it quickly becomes one of the handiest time savers in your workflow. Mimosa and Live Reload are often fast enough to get the page reloaded before the browser can be toggled to.

If mimosa new was used to create the project, then live reload will already be included. If enabling it on an existing project, some minor things need to change on both the client and server to use it.

Client Scripts

For live reload to work, two scripts need to be added to the page. If using dynamic templating for views, then the scripts need to be included for development and not included when in production.

The paths to use for the two scripts are:

  • /socket.io/socket.io.js: This is socket.io. Mimosa will serve this file, so it need not be in the project's codebase, but a script tag must pull it in. socket.io is what allows instant communication of server-side changes to the client. socket.io will emit events on the client that indicate that a JavaScript or CSS file has changed.
  • /javascripts/reload-client.js: This is a small piece of code that reacts to events emitted by socket.io. When it hears from socket.io that a piece of CSS has changed, it reloads the CSS. When it hears that some JavaScript has changed, it refreshes the page.

Server Component

If Mimosa is serving assets, there is nothing to do on the server.

If running a node server that Mimosa is starting, then the callback that Mimosa passes startServer needs to be passed the http server object. This is the same object returned by require('http').createServer() and by express().listen(). The mimosa-live-reload module needs access to the server to establish a connection between the socket.io client and the server.

Already using socket.io?

This pertains to those who are using their own server, not Mimosa's. The mimosa-live-reload module uses socket.io in conjunction with the server passed to the startServer callback function to provide live reload functionality. But if socket.io is already being used, Mimosa's use of socket.io will cause problems.

If socket.io is already being used, then it must also be given to the callback function executed at the end of startServer. The first parameter passed to the callback should be the server, and the second should be the object returned by socketio.listen(server). If this object is provided, mimosa-live-reload will not create its own socketio connection, and instead use the existing one.

Try a Chrome Extension?

There is a Chrome Extension that can provide live reload without needing to embed scrips on your page in your app. It embeds them in the browser.

Logging

Mimosa's core code and its various modules will all attempt to log events. Errors, warnings, information, debugging and success messages emanate from Mimosa at various times.

Mimosa provides an ability to configure its logger. Various types of messages can be turned off and colors can be edited. The configuration listed here is fairly self-explanatory.

Growl

If Growl is installed and turned on, a Growl notification will be created for each failed or successful asset compile. In the event Growl gets too spammy, Growl notifications can be turned off for successful compiles or turned off entirely. Growl has its own setting in Mimosa, the defaults are to the right.

If clean in run on a project and then watch is started, Mimosa will compile every asset. If there are dozens or hundreds of assets, Growl notifications may not be desirable for each successful compile during startup. Startup success notifications are off by default, but can be turned on by uncommenting the config and setting the growl.onStartup flag to true. Post-startup success notifications can be turned off by altering the growl.onSuccess flats. These notifications are on by default.

To allow Mimosa to use Growl, an extra library needs to be installed. For details on installation on your system, check out the node-growl page.

logger:
  info:
    enabled: true
    color: null
  warn
    enabled: true
    color: 'yellow+bold'
  success:
    enabled: true
    color: 'green'
  error:
    enabled: true
    color: 'red+bold'
  debug:
    color: 'blue'
  embeddedText:
    enabled: true
    color: 'cyan'
  growl:
    enabled: true
    onStartup: false
    onSuccess: true

All static assets will be served up GZip-ed! 'nuff said.

No forcing a refresh to bypass caching issues. All JavaScript and CSS files are cache-busted during development.

JavaScript cache-busting is done via the urlArgs parameter with RequireJS. That can cause some problems if you are doing breakpoint debugging in the client. You'll want to comment out the urlArgs if you do that kind of debugging.

Profiles allow for overriding of mimosa-config settings via external config files. A project might have a "build" profile that is used for automated builds, and for those builds maybe certain modules aren't needed. For instance the "lint" module can be left out of the modules array.

Profiles are implemented as mimosa-config files. Any properties of a project's mimosa-config that need to be overridden would be the properties placed in a profile file.

By default, profile files should be located in a profiles/ directory at the root of a Mimosa project. This location can be overridden via the profileLocation property in the project's mimosa-config. profileLocation is relative to the root of the project.

Profiles can be used for the watch, build and clean commands. Each of those commands have a -P/--profile flag. Follow the flag with the name of the profile to use and Mimosa will pull that profile in and use it to override the settings in the mimosa-config. Ex: mimosa build -P build.

Multiple Profiles

New with version 2.2.14 of Mimosa, multiple profiles can be provided at the command line. Ex: mimosa build -P foo#bar. Profiles are applied from left to right. So, in this case if the bar profile contains the same configuration as the foo profile, the bar profile information will overwrite foo.

Default Profiles

New with version 2.3.2 of Mimosa is the introduction of default profiles. Profiles are a powerful feature. Using a profile is easy enough, but if you have a set of profiles that you are constantly applying, you find yourself typing -P profileName quite a bit. Now you can keep a default profile in a `.mimosa_profile` file at the root of your project. This file, a \n-delimited list of profile names, will be the first profiles applied. You can also append -P profileName and those profiles will be applied last (and therefore override any settings in a default profile).