Best practices for real world ember deployment

Our front end developers LOVE Ember and would like to use it moving fwd. Our server side team is skeptical and pushing back.

Can anyone provide some documentation or links that illustrate how Ember can be successfully deployed in a real world dev->staging->production environment?

While i realize a good portion of the Ember community is working with rails / node or other similar back ends, our servers are currently setup using traditional LAMP stacks, so ideally we would love to see an example deployment of Ember that ties into a PHP/SQL back end, delivers the Ember JS payload via CDN, how to best separate business logic from UI logic and a real world approach for implementing a config for deployment across our environments.

I realize this is a lot to ask. ANY suggestions ever so GREATLY appreciated.

2 Likes

For me i just build locally, and send files to the server using rsync -avz -e ssh dist/* username@0.0.0.0:/home/username/awesome_app. Then you can setup NGINX or Apache for handling incoming requests

This topic is not well explored in Ember community at the moment. The short answer is that its not very different than other frontend frameworks in that respect.

Ember App Kit project foundation will give you a project layout that covers automated testing and building of distribution files. From there, you will just need to integrate it into whatever process you follow currently to deploy javascript.

I’m not sure of the PHP equivalent but for our django web apps we deploy with Capistrano. And when we started writing ember.js front-ends we just added a grunt task for “staging” or “production” that runs as part of the deploy -this simply combines / uglifies / hashes the js so your client gets 1 file that has a different hash each time you deploy (assuming the JS code changes -else the hash remains the same). This helps us avoid the “caching” problem and Grunt helps automate it so we don’t have to think about it.

If you need a full blown grunt file => here is an example that should get you started

https://gist.github.com/toranb/7355103

Great responses, thank you all, i really appreciate the input so far …

could you put that Gruntfile in a gist or something?

ask and you shall receive :slight_smile:

I was annoyed by not having a complete solution for this. Basically you want to concatenate and minify all your stuff. Replace the ember dev with the production build and so on. I have created a small template for my projects, you can find it on github: https://github.com/NilsLattek/ember-grunt-template

It is currently using ember 1.0, but the Readme describes how to upgrade ember and handlebars. It should work fine with the latest version. It is just a grunt setup, nothing fancy like my own built tool. So it should be easy to customize and maintain in the future. I am not using a real module system, because it is not needed with ember, but I also do not want to list all files in the gruntfile, so I used grunt-neuter. A tool which was originally written in Ruby by the ember folks.

You will get a nice setup during development (live reload, etc) and the build process provides you with the js, css and index.html files which you can copy over to your server/CDN. (using grunt, git or whatever).

When working with your backend during development you may run into the CORS problems with your browser. I am using a small grunt proxy plugin which redirects my requests to the backend.

I don’t have a script that deploys yet but here’s my build script, note that gives me a minified and non minified version

module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    
    // Define our source and build folders    module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    
    // Define our source and build folders
    js_src_path: 'src/js',
    js_build_path: "build/js",
    css_src_path: "src/css",
    css_build_path: "build/css",
    hbs_src_path: "src/hbs",

    // Grunt Tasks
    concat: {
      options:{
        separator: ''
      },
      js: {
        src: [
          '<%= js_src_path %>/libs/jquery.js',
          '<%= js_src_path %>/libs/handlebars.js',
          '<%= js_src_path %>/libs/ember.js',
          '<%= js_src_path %>/libs/ember-data.js',
          '<%= js_src_path %>/libs/bootstrap.js',
          '<%= js_src_path %>/app.js',
          '<%= js_src_path %>/hbs.js',
          '<%= js_src_path %>/router.js',
          '<%= js_src_path %>/models/**/*.js',
          '<%= js_src_path %>/views/**/*.js',
          '<%= js_src_path %>/controllers/**/*.js',
          '<%= js_src_path %>/routes/**/*.js'
        ],
        dest: '<%= js_build_path %>/bundle.js'
      },
      css:{
        src: [
          '<%= css_src_path %>/libs/bootstrap.min.css',
          '<%= css_src_path %>/libs/bootstrap-responsive.min.css',
          '<%= css_src_path %>/default.css'
        ],
        dest: '<%= css_build_path %>/bundle.css'   
      }
    },
    uglify: {
      options:{
        mangle: true,
        banner: ''
      },
      js: {
        src: '<%= concat.js.dest %>',
        dest:'<%= js_build_path %>/bundle.min.js'
      }
    },
    cssmin: {
      css: {
        src: '<%= concat.css.dest %>',
        dest:'<%= css_build_path %>/bundle.min.css'
      }
    },
    ember_handlebars: {
      options: {
        processName: function(filename) {
          return filename.replace('src/hbs/', '').split('.hbs')[0];
        }
      },
      hbs: {
        src: '<%= hbs_src_path %>/**/*.hbs',
        dest:'<%= js_src_path %>/hbs.js'
      }
    }
  });
   
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-ember-handlebars');
 
  // Default task.
  grunt.registerTask('default', ['ember_handlebars', 'concat', 'uglify', 'cssmin']);
};
    js_src_path: 'src/js',
    js_build_path: "build/js",
    css_src_path: "src/css",
    css_build_path: "build/css",
    hbs_src_path: "src/hbs",

    // Grunt Tasks
    concat: {
      options:{
        separator: ''
      },
      js: {
        src: [
          '<%= js_src_path %>/libs/jquery.js',
          '<%= js_src_path %>/libs/handlebars.js',
          '<%= js_src_path %>/libs/ember.js',
          '<%= js_src_path %>/libs/ember-data.js',
          '<%= js_src_path %>/libs/bootstrap.js',
          '<%= js_src_path %>/app.js',
          '<%= js_src_path %>/hbs.js',
          '<%= js_src_path %>/router.js',
          '<%= js_src_path %>/models/**/*.js',
          '<%= js_src_path %>/views/**/*.js',
          '<%= js_src_path %>/controllers/**/*.js',
          '<%= js_src_path %>/routes/**/*.js'
        ],
        dest: '<%= js_build_path %>/bundle.js'
      },
      css:{
        src: [
          '<%= css_src_path %>/libs/bootstrap.min.css',
          '<%= css_src_path %>/libs/bootstrap-responsive.min.css',
          '<%= css_src_path %>/default.css'
        ],
        dest: '<%= css_build_path %>/bundle.css'   
      }
    },
    uglify: {
      options:{
        mangle: true,
        banner: ''
      },
      js: {
        src: '<%= concat.js.dest %>',
        dest:'<%= js_build_path %>/bundle.min.js'
      }
    },
    cssmin: {
      css: {
        src: '<%= concat.css.dest %>',
        dest:'<%= css_build_path %>/bundle.min.css'
      }
    },
    ember_handlebars: {
      options: {
        processName: function(filename) {
          return filename.replace('src/hbs/', '').split('.hbs')[0];
        }
      },
      hbs: {
        src: '<%= hbs_src_path %>/**/*.hbs',
        dest:'<%= js_src_path %>/hbs.js'
      }
    }
  });
   
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-ember-handlebars');
 
  // Default task.
  grunt.registerTask('default', ['ember_handlebars', 'concat', 'uglify', 'cssmin']);
};

Use Ansible. Done. Using environment templates to fit my needs, works perfectly and very good for scaling. I manage and deploy all of our applications with Ansible.

Here’s a Grunt script I use to deploy Ember-CLI apps via SFTP:

I hope someone will find it useful.

Whoa! This thread is from 2 years ago. Here’s an update on the ecosystem.

Checkout GitHub - ember-cli-deploy/ember-cli-deploy: A deployment pipeline for Ember CLI apps

I can really recommend Ember CLI Deploy 0.5.x.

(Besides the small annoying fact that we need to turn --verbose on every command else there’s NO output whatsoever.)

The docs are great, but I also wrote a step-by-step guide on how to deploy to S3 and/or Linux via SSH/rsync. For those who are interested: How to Deploy an Ember CLI app to Amazon S3 or a Linux box - Ember Igniter