If you’re like me and you like to develop Ember apps, you probably enjoy using Ember-CLI. It’s one of the best build tools out there and it gives me what I need to create ambitious single page apps. But sometimes you don’t want to create another single page app. Maybe you want to just present some static content ASAP and you don’t have a big need for any dynamic behavior. At that point, you could start creating a simple project using Gulp, Grunt, Jekyll etc.

But wouldn’t it be nice if you could use Ember-CLI for that? It already provides great solutions for:

Templating with handlebars with the help of components, outlets and helpers

CSS minification

Development server with liveReload and styles hot reload

After a few quick ember install commands, you can have addons for:

CSS preprocessing — SASS, LESS, Autoprefixer

Image compression

UI elements (those could cause issues, but more on that later)

Besides that, creating a static website using Ember-CLI gives you another great advantage. If you later decide to transform the site into a single page app, there’s literally zero work to do that… Unless you have a lot of content in templates which would cause a monstrously huge JS file, then you might need to restructure a bit to load the content from API :). If you just want to add a little dynamic behavior here and there, you can take use of Ember Islands.

Generating & Saving HTML with Ember-CLI

Ok, this sounds nice but doesn’t Ember CLI generate JS files instead of HTML? Yes, but that’s where Fastboot comes to save the day.

Fastboot runs your Ember app on the server and sends already parsed HTML to the browser. Running Fastboot is as easy as:

ember install ember-cli-fastboot

ember fastboot --environment=production --serve-assets

Now you have a running Fastboot server. At that point there are multiple ways to generate the static HTML. You could do it already on the server in a custom express app, where you would include Fastboot as an express middleware. You could create custom Node script to scrape the HTML. But in my case I could easily scrape the site with just a simple shell script:

rm -rf ./scrape-dist

mkdir scrape-dist

cd scrape-dist cp -ar ../fastboot-dist/assets ./assets

cp -ar ../fastboot-dist/images ./images

app_name=”app” base_url=” http://localhost:3000/ app_name=”app” scrape(){

if test -n “$1”; then

mkdir $1

fi

url=$base_url$1

wget $url -O ./$1/index.html grep -v “assets/vendor” ./$1/index.html > ./$1/temp_index.html

mv ./$1/temp_index.html ./$1/index.html echo ./$1/index.html grep -v “assets/$app_name” ./$1/index.html > ./$1/temp_index.html

mv ./$1/temp_index.html ./$1/index.html

} scrape “”

scrape “cars”

scrape “buildings”

scrape “people”

Saving this into scrape.sh and running

sh scrape.sh

will create ./scrape-dist folder and copy assets and images into it. It will fire requests on http://localhost:3000/ , /cars, /buildings, /people and put the content in ./index.html ./cars/index.html, . /buildings/index.html and ./people/index.html. It will also remove app.js and vendor.js files from the output. The scrape-dist folder is ready to be deployed on the server.

There are cons of course. Fastboot is still an experimental feature. A lot of addons still aren’t Fastboot compatible. And since we are removing the ember .js files, there’s no build tooling for javascripts (transpiling, concatination, minification), so you’d have to roll your own. At this point, you need ember-cli-head to support custom meta tags.

It could also be possible to avoid Fastboot and scrape the client side generated HTML using PhantomJS which could allow you to use many more addons that take use of didInsertElement() and JQuery. But in my case, using Fastboot was sufficient and easy to use.

UPDATE: there is also an addon ember-cli-staticboot which does the scraping for you

— — — — —

I am a Freelancer Developer currently looking for work for upcoming months. I specialise in building single page applications with Ember.js and performance optimisations. Feel free to contact me at malindacz@gmail.com or twitter.com/@martinmalinda.cz