In the normal course of development (in a pre source maps world) assets are best loaded individually rather than in one merged file. And assets definitely should not be minified or mangled. This all makes for easier debugging.
But when an application is taken to production, all the performance improvements that come with merging, optimizing, and minifying assets should be included. For both the
watch commands, Mimosa provides
--minify flags that combine to provide both the ability to fully optimize an application, and to have a more control over what gets optimized.
mimosa-require module that comes with Mimosa by default, Mimosa uses the r.js optimizer which is perfect for optimizing RequireJS applications. Underneath the hood, that optimizer is using Uglify to shrink a codebase down as tiny as possible. Mimosa bundles Uglify2, and can use it to individually shrink assets. And Mimosa's Uglify and the r.js optimizer can be combined to provide more fine-grained control over a minification strategy.
For both the
watch commands, Mimosa provides an
--optimize flag that will turn on optimization. Mimosa wraps the r.js optimizer and runs it with a default configuration gleaned from the setup of the application.
When a codebase is optimized and pulled together into one file, the RequireJS library is no longer necessary. Mimosa will wrap r.js optimized code in Almond, a replacement AMD loader for RequireJS that provides the minimal functionality necessary for optimized files. (If you are loading modules/resources from a CDN, Almond does not support that. See this Mimosa issue for help dealing with CDN resources.)
Mimosa's RequireJS optimization support comes courtesy of the
mimosa-require module, a default Mimosa module that comes with Mimosa when it is installed.
Mimosa will infer the following default settings for the r.js optimizer.
baseUrl: set by combining the mimosa-config
out: optimized files are output into the
mainConfigFile: set to the file path of the main module unless a common config (
require.commonConfigsetting) is detected. If a common config is found,
mainConfigFileis set to that.
include: set to the name of the module being compiled
insertRequire: set to the name of the module being compiled
name: set to
logLevel: set to
3which is the r.js error logging level
optimize: set to
uglify2unless both the
--minifyflags are used, in which case it is set to
These settings will package up each individual module into its own optimized file wrapped with Almond.
Any of the other RequireJS optimizer configuration options can be included in the mimosa-config. Just uncomment the
require.optimize.overrides setting and include those settings there. Settings can be both overridden and removed. To override a Mimosa setting, put the override in
overrides. To remove a default setting, set it to
require.optimize.overrides can also be configured as a function. That function is passed the full inferred r.js config for the module being optimized. This provides the opportunity to amplify the inferred config rather than just replace it.
Mimosa can also be configured to not infer anything and to go entirely with a custom config. Set
require.optimize.inferConfig to false and Mimosa will run r.js with only the settings provided in
requirejs method calls) are in script tags on an HTML page, Mimosa will not find any modules to compile for optimization and therefore will not run optimization, so a custom configuration will need to be provided in
inferConfig set to
Mimosa can't know all the intricacies of a project. It can make a lot of educated guesses and put together a really good base r.js config, but there are times when complicated alterations must be made to the r.js config.
overrides allows static changes to the r.js configuration, but that isn't always ideal.
require.optimize.inferConfig:false loses all of the smarts Mimosa puts into building a r.js config. Ideally a project can take advantage of the work Mimosa puts into building the r.js config, and dynamically alter it as well.
Mimosa's building of the inferred r.js config, and the execution of the r.js optimization are pulled apart in two separate steps in Mimosa's workflows. Config building executes during the
beforeOptimize step, and execution during the
optimize step. This means a custom module can programmatically and dynamically alter the Mimosa-prepared r.js configs before r.js execution occurs.
For instance, maybe there are files to include in the r.js execution that are not pulled in as dependencies by r.js, maybe all .html files via the requirejs text plugin, and rather than listing them one by one in the overrides, they could be dynamically added so a list need not be maintained. A module could do this, executing during the
beforeOptimize step, but after the configs have been built. In that module the codebase could be scanned for .html files and push them onto the r.js config
Doing this provides both Mimosa's smarts, and the intelligence Mimosa can't provide by way of a custom module. To get started building such a module, check out the long-named example module mimosa-requirebuild-textplugin-include which performs just the task mentioned above.
mimosa watch is used with
--optimize (and not also
--minify which does minification outside of requirejs), Mimosa will generate source maps for easy debugging in browser dev tools.
mimosa build does not generate source maps. All cleans performed by various Mimosa tasks will clean up the generated
.map files. Because generation of source maps is configured via the r.js config, which can already be overridden in the
require config, no additional config settings have been added to change the default behaviors.
For both the
watch commands, Mimosa provides an
minify.exclude setting. By default any file already possessing
.min. in the path name will be excluded as it is assumed to already be minified.
Mimosa's Minification support comes courtesy of the
mimosa-minify module, a default Mimosa module that comes with Mimosa when it is installed.
For either the
watch commands, using the
--optimize flags together provides increased control over the optimization workflow.
The r.js optimizer by itself is often good enough to handle minifying, compressing and pulling modules into single files; however, the occasional file does not take kindly to being run through Uglify and will be broken when compressed. The r.js optimizer is all or none. It does not allow choose to omit a file from compression if it is not compressing correctly.
When both minifying and optimizing, r.js minification is turned off. Specifically the
optimize setting of r.js is set to
none. The optimizer is still used to pull all of an application's files together into the same file and wrap it in Almond. But Mimosa will Uglify files first, before calling the optimizer, and Mimosa provides the opportunity to not Uglify whatever files are not making it through Uglifying in working order.
If a project has many pages, and therefore many optimized files that need to be written, using both flags at the same time will also speed up the build. If Mimosa writes minified files, then the files are minified once and the minified versions are used to build the many optimized files.If Mimosa writes un-minified files, then those files have to be minified by the r.js optimizer. The optimizer is going to minify each file every time it is used. So if the unminified jQuery source is in a project's codebase, and it is used on 10 pages and therefore is bundled into 10 optimized files, then r.js will minify it 10 times, which can slow the build. So, if a build is running slow, try using both flags at once to speed it up.
The AngularFunMimosa demo project is a perfect example of a project that benefits from this functionality. This commit from that project shows the effect of the minify+optimize feature being added to Mimosa. Previously optimization was turned off via Mimosa's r.js overrides, because when r.js Uglified the code, it also broke the application. When this Mimosa feature was added, the r.js override was removed, and the file that was not surviving Uglifying,
main.js, was simply omitted from minification. What comes out the other side is a fully r.js optimized and zipped up file that is fully compressed with the exception of the file that cannot be minified.
--optimize flag is used, Mimosa will minify CSS files too. And that about covers that.
The external mimosa-combine module can be used to do things like pull compiled or vendor CSS files together...or anything really. All mimosa-combine wants is a folder to merge and a place to put the result, but it also allows assets to be excluded and an order to be provided.
Just tack the string
"combine" onto the
modules array and Mimosa will fetch the module for immediate use.