The Static Web is blisteringly fast. The Static Web is ultra efficient. The Static Web is cutting edge. And now it has a hero.
rack = require 'asset-rack'
The Static Web is an incredibly modern, high-performance platform for delivering apps and services. But before you dive-in, you need to start with the basics. You need to understand the fundamental building block of the static web, the asset.
An asset is a resource on the web that has the following three features:
This simple definition is the theoretical bedrock of this entire framework.
Let's look at a simple example.
asset = new rack.Asset({
url: '/hello.txt',
contents: 'hello world'
})
Need to serve that asset with a blisteringly fast in memory cache using express?
app.use(asset)
What's cool is that this new asset is available both here:
/hello.txt
And here
/hello-5eb63bbbe01eeed093cb22bb8f5acdc3.txt
That long string of letters and numbers is the md5 hash of the contents. If you hit the hash url, then we automatically set the HTTP cache to never expire.
Now proxies, browsers, cloud storage, content delivery networks only need to download your asset one single time. You have versioning, conflict resolution all in one simple mechanism. You can update your entire entire app instantaneously. Fast, efficient, static.
Assets need to be managed. Enter the Rack. A Rack serializes your assets, allows you to deploy to the cloud, and reference urls and tags in your templates.
Say you have a directory structure like this:
/static # all your images, fonts, etc.
/style.less # a less files with your styles
You can create a Rack to put all your assets in.
assets = new rack.Rack([
new rack.StaticAssets({
urlPrefix: '/static',
dirname: __dirname + '/static'
}),
new rack.LessAsset({
url: '/style.css',
filename: __dirname + '/style.less'
})
])
After you hook into express, you can reference your assets in your server side templates.
assets.tag('/style.css')
Which gives you the html tag.
<link href="https://github.com/techpines/asset-rack/blob/master/style-0f2j9fj039fuw0e9f23.css" rel="stylesheet">
Or you can grab just the url.
assets.url('/logo.png')
Which gives the hashed url.
/logo-34t90j0re9g034o4f3o4f3.png
We have some professional grade assets included.
Asset Rack is extremely flexible. Extend the Asset class and override the create method to roll your own awesomeness, and watch them get automatically ka-pow'ed by your rack.
SuperCoolAsset = rack.Asset.extend({
create: function(options) {
this.contents = 'easy, easy',
this.emit 'created',
}
})
Or, for those with more refined taste:
class SuperCoolAsset extends rack.Asset
create: (options) ->
@contents = 'even easier with coffee'
@emit 'created'
Checkout the tutorial.
Your assets need to be deployed! Here are the current providers that are supported.
assets.deploy({
provider: 'amazon',
container: 'some-bucket',
accessKey: 'aws-access-key',
secretKey: 'aws-secret-key',
}, function(error) {})
assets.deploy(
provider: 'rackspace',
container: 'some-container',
username: 'rackspace-username',
apiKey: 'rackspace-api-key',
}, function(error) {})
assets.deploy(
provider: 'azure',
container: 'some-container',
storageAccount: 'test-storage-account',
storageAccessKey: 'test-storage-access-key'
}, function(error) {})
If you provide the options configFile
in your deploy options then a config file will be written:
assets.deploy(
configFile: __dirname + '/rack.json',
provider: 'amazon',
container: ...
)
Then you can create your assets from the file like this:
assets = rack.fromConfigFile({
configFile: __dirname + '/rack.json',
hostname: 'cdn.example.com'
});
app.use(assets);
And now all of your server side templates will reference your CDN. Also, if you do happen to hit one of your static urls on the server, then you will be redirected to the CDN.
That's easy!
With all that said, much thanks to Trevor for writing connect-assets.
Grunt is a great build tool. Asset Rack is not a build a tool. It never writes files to disk, there is no "build step". Everything happens "just in time".
If you have "genuine" build issues, then by all means use Grunt. You can even use Grunt with Asset Rack.
However, if you are only using Grunt to manage your static assets, then you should consider upgrading to Asset Rack.
Asset Rack is a static web framework, and at it's core there are only two abstractions, the Asset
and Rack
classes. Wintersmith is a high level framework that solves a more specific problem.
Wintersmith could consume Asset Rack as a dependency, and if something more high-level fits your specific use case, then by all means that is probably a good fit. If you need more flexibilty and power, then go with Asset Rack.
new StylusAsset({
watch: true,
...
});
new BrowserifyAsset({
gzip: true,
...
});
addAsset
.this.addAsset(asset);
this.emit('created');
Thanks @moellenbeck, @d1plo1d, @undashes, and @noc7c9 for contributing!
LessAsset
.rack.util.walk
function, need to document the function.DynamicAssets
class.new StylusAsset
url: '/style.css'
filename: __dirname + '/style/fun.styl'
config: ->
@use bootstrap()
@define 'setting', 90
And for javascript:
new StylusAsset({
url: '/style.css',
filename: __dirname + '/style/fun.styl',
config: function (stylus) {
stylus // using "this" here seems a little unnatural
.use(bootstrap())
.define('setting', 90);
}
});
Testing is easy and fun!
cd asset-rack
npm install
npm test
©2012 Brad Carleton, Tech Pines and available under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.