├── .gitignore ├── LICENCE ├── Makefile ├── README.md ├── examples ├── connect │ ├── README.md │ ├── app.js │ ├── assets │ │ └── css │ │ │ ├── all.less │ │ │ └── reset.less │ └── bin │ │ └── precompile_assets.js ├── express │ ├── README.md │ ├── app.js │ ├── assets │ │ ├── css │ │ │ ├── all.css.less │ │ │ └── reset.css │ │ └── js │ │ │ ├── application.js.ejs │ │ │ ├── main.coffee.ejs │ │ │ └── models │ │ │ ├── post.coffee │ │ │ └── user.coffee │ ├── bin │ │ └── precompile_assets.js │ ├── vendor │ │ └── js │ │ │ ├── jquery.js │ │ │ └── modernizer.js │ └── views │ │ └── home.ejs └── nib │ ├── README.md │ ├── app.js │ ├── assets │ └── css │ │ └── main.css.styl │ └── views │ └── index.ejs ├── index.js ├── lib └── connect_mincer.js ├── package.json └── test ├── apps └── basic │ ├── assets │ ├── css │ │ └── layout.css.less.ejs │ ├── img │ │ └── background.png │ └── js │ │ ├── app.js │ │ └── libs.js │ ├── index.js │ ├── vendor │ └── js │ │ ├── jquery.js │ │ └── underscore.js │ └── views │ └── index.ejs ├── mocha.opts ├── requests └── basic.js └── unit └── connect_mincer.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | .tern-port -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Dave Clark 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | test: 2 | NODE_ENV=test ./node_modules/.bin/mocha test/unit test/requests 3 | 4 | .PHONY: test -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # connect-mincer 2 | 3 | This is an Express-compatible, Connect middleware for [Mincer](https://github.com/nodeca/mincer). 4 | 5 | ## What is Mincer and why do I want this? 6 | 7 | Mincer is an excellent port of Sprockets, which means it is a robust and comprehensive asset manager for your Node app. However, Mincer makes no assumptions about your application so by default it requires some work to get going with a typical Express app. 8 | 9 | Using connect-mincer, you can skip that work and simply: 10 | 11 | * Write and serve CoffeeScript, LESS, Stylus, Sass, etc 12 | * Have everything recompiled on each request (in development) 13 | * Serve files with an MD5 digest (for caching) 14 | * Use whatever directory structure you want 15 | * Precompile all your assets and have your Connect app read from the compile manifest 16 | 17 | If you're used to the Rails asset pipeline, using this will give your Connect/Express application almost all the same capability - the only thing missing is a built-in precompile, but that's easily added (see the [example app](https://github.com/clarkdave/connect-mincer/tree/master/examples/express) for an example precompile script). 18 | 19 | ## Let's go! 20 | 21 | npm install connect-mincer 22 | 23 | Now, in your connect app: 24 | 25 | ``` javascript 26 | var ConnectMincer = require('connect-mincer'); 27 | 28 | var connectMincer = new ConnectMincer({ 29 | root: __dirname, 30 | production: process.env.NODE_ENV === 'production', 31 | mountPoint: '/assets', 32 | manifestFile: __dirname + '/public/assets/manifest.json', 33 | paths: [ 34 | 'assets/css', 35 | 'assets/js', 36 | 'vendor/js' 37 | ] 38 | }); 39 | 40 | // access the internal Mincer object if you want to do anything extra to it, e.g. 41 | connectMincer.Mincer.CoffeeEngine.setOptions({ bare: false }); 42 | 43 | app.use(connectMincer.assets()); 44 | 45 | if (process.env.NODE_ENV !== 'production') 46 | app.use('/assets', connectMincer.createServer()); 47 | ``` 48 | 49 | The connectMincer.assets() middleware will: 50 | 51 | * Provide js(), css() and asset_path() helpers for your views 52 | * In development, ensure that assets are recompiled on every request 53 | 54 | Now, in your views, you can do this: 55 | 56 | ``` html 57 |
58 | <%- css('main.css') %> 59 | <%- js('application.js') %> 60 | 61 | ``` 62 | 63 | These helpers will output something like: ``. 64 | 65 | The second piece of middleware, `connectMincer.createServer()`, sets up a Mincer server which will send the compiled version of the asset. This is great for development, though in production you'll probably want to have these files served by nginx or from a cloud host (see more about 'in production' below). 66 | 67 | ## In more detail 68 | 69 | Mincer and this middleware are unopinionated about where your keep your assets. When you initialise connect-mincer you pass in several options: 70 | 71 | - **root** 72 | - This is usually the root of your app. Asset paths are relative to this. 73 | - **mincer** 74 | - (Optional) Use this to pass in your own Mincer object. 75 | - If not provided, ConnectMincer will use its own bundled version of Mincer, which may be out of date. The Mincer version provided MUST be >= 0.5.0, as older versions have an unsupported API 76 | - **production** 77 | - Set to true if the app is running in production mode. 78 | - **paths** 79 | - A list of directories where your assets are located. 80 | - **mountPoint** *(optional)* 81 | - This is what the js, css and asset_path helpers use to create the URL for each asset. Defaults to `/assets`. 82 | - **assetHost** *(optional)* 83 | - If specified, the view helpers will generate urls of the form `assetHost + mountPoint + asset`. E.g. `//j2938fj.cloudfront.net/assets/layout.css` 84 | - You should specify the protocol, i.e. `http://`, `https://` or `//` 85 | - This can be used to serve assets from a CDN like Cloudfront 86 | 87 | A typical app folder structure might be this: 88 | 89 | app/ 90 | assets/ 91 | js/ 92 | application.js 93 | css/ 94 | main.less 95 | blog/ 96 | more.css 97 | images/ 98 | logo.png 99 | lib/ 100 | public/ 101 | vendor/ 102 | js/ 103 | jquery.js 104 | app.js 105 | 106 | With this, a suitable path list would be: 107 | 108 | ['assets/js', 'assets/css', 'assets/images', 'vendor/js'] 109 | 110 | Now anything within these paths can be referenced in your views with the helpers like so: 111 | 112 | css('main.css') 113 | css('print.css', { media: 'print' }) 114 | js('jquery.js') 115 | 116 | Which would become: 117 | 118 | 119 | 120 | 121 | 122 | ### View helpers 123 | 124 | connect-mincer provides several helpers which are available in all views. All of them take an asset filename as their first argument, which is used to search for a matching asset across all asset directories (i.e. the path option provided to connect-mincer). If the asset is actually a bundle (it includes or requires other assets), all of these 125 | will be returned in development mode. In production, only the bundle itself will be returned (which will include all its required dependencies concatenated within). 126 | 127 | In all cases, the urls returned here will contain their MD5 digest if the app is running in production. 128 | 129 | #### js(path, attributes) -> One or more script tags 130 | 131 | * filename (String) The filename of the asset relative to its asset directory 132 | * attributes (Object) An object containing attributes for the ` 160 | 161 | which will correspond to the file `/public/assets/application-4b02e3a0746a47886505c9acf5f8c655.js`. Now you can set nginx up to intercept requests to `/assets` and serve the static file in `/public/assets` instead. Thanks to the MD5 digest, you can set the cache headers to maximum. The next time you deploy and precompile the digests will change, and your app will adjust its ` 17 | <%- js('application.js') %> 18 |