In our previous post, we successfully configured our server-side and client-side applications in a decoupled way in a development environment, but what about deploying on a different environment (i.e. staging, production)?, how would we join our applications together and deploy them as one?.
Well, there are at least two ways to deploy our application and it basically depends on the following:
In any of the cases above we have two other sub-options:
a. Copy the generated client-side files (i.e. under frontend/dist
folder) to the Rails application public folder (or the corresponding assets folder for js, css, etc.) before pushing (the generated files are checked in version control for this to work).
b. Use lineman on the remote server to build the client application from its source files and copy the generated files to the Rails application to its final location, as in option a.
If we choose option a, then we can push the bundled-ready-to-operate application to our remote server, provided we have generated all needed files in our development machine and committed the changes.
On the other hand, if we choose option b we don't have to commit the generated files, thus reducing the size of the our version-controlled repository, but in contrast, running the generation on the server could take more time and be more complex to setup (since you need nodejs and lineman and all the other things to be able to generate the files).
Depending on what you need and if you do or do not want to commit generated files in version control, you can choose between these two, so we will leave that to you, but we will present both alternatives.
Note: As mentioned earlier these apply to the example app from our previous post.
Let's assume you have all changes ready, and you wish to push your app to Heroku, but could be other platform or your own server at this point. The steps you would need to perform are the following:
Generate the frontend app files.
$ lineman build
This will generate all the app into the frontend/dist
folder. Then, for example, manually (or via a single "cp" line script) copy this folder's contents into the Rails public
folder (which we recommend), or painstakingly copy the corresponding files into each of the assets
folders for the asset pipeline to work, which we do not recommend since all the minify, uglify and fingerprinting are already performed by lineman.
$ cp -R frontend/dist/* public/
lastly, commit these changes to the repo.
$ git commit -am ‘add client application version x.y.z’
In any case we could write a script to do this and later deploy. Note that we will be overriding the generated files each time we deploy, but that's pretty much it, you app would be deployed without any "special" steps.
As we mentioned before, this process is truly more complex compared to the previous one, but the good news is that there is already the rails-lineman gem to helps us deal with this. However we did some tweaks of our own to the gem to improve the possible scenarios for deployment that it could manage. With this option you do not have to commit any generated files, only the source ones.
Generally speaking, this gem adds the CSS and JS files built by Lineman and adds them to asset pipeline like any other asset in a Rails application. While this is good for some situations where the views are built by Rails and the CSS and JS by Lineman separately, we would like to just be able to copy our generated files without any Rails intervention or dependency on its views.
For the purpose of exploring the deployment solution we modified the rails-lineman gem adding it a new deployment method, which is just to copy our AngularJS client application to the rails public folder and not use rails assets precompile feature at all, however you can switch to the asset pipeline feature if you want. For now, we have our own fork of the gem here. The modified gem dynamically generates one of the two following rake tasks, depending on the deployment method you choose:
assets:precompile
, which adds the client application assets to the Rails asset pipeline flow (if you choose the :asset_pipeline method)
deploy:frontend
which runs Lineman and copy/pastes all files into dist
folder to the Rails public folder.
To choose one of the two deployment methods you have to setup your Rails application configuration config/application.rb
the deployment_method
option, as follows:
config.rails_lineman.deployment_method = :asset_pipeline
or
config.rails_lineman.deployment_method = :copy_files_to_public_folder
When you choose the :asset_pipeline then the rake task assets:precompile
will be overridden by the rails-lineman gem, so the deployment process will be like:
You invoke the command you use to deploy the application to the server (e.g. by using Capistrano or by pushing to Heroku or any platform of your choice) this process and setup is up to you.
The assets:precompile
rake task will be run, which will:
frontend/dist
folder.frontend/dist
to the Rails asset_path so that they are precompiled together.The Rails app will be started and ready to go!.
On the other hand, when you choose the :copy_files_to_public_folder option the process will be:
You invoke the command you use to deploy the application to the server (e.g. by using Capistrano or by pushing to Heroku or any platform of your choice) this process and setup is up to you.
The Rails app will be started, and afterwards this will happen:
frontend/dist
folder.Be sure to gitignore the frontend/node_modules
, frontend/generated
and the frontend/dist
folders and be careful to not gitignore all the frontend
folder. This way you only have the source files in your version control.
Ok, now that we have explained a little bit about that, let's continue deploying our example app. We will use the :copy_files_to_public_folder
deployment method and deploy to Heroku, where we do not have complete control over our filesystem, so that you can test this without acquiring a dedicated machine.
install our fork of rails-lineman(version 0.3.1).
To do so, add to your Gemfile:
gem 'rails-lineman', github: 'degzcs/rails-lineman'
setup/update the config/application.rb
, as per the README, like this:
# Integrate with lineman
config.rails_lineman.lineman_project_location = "frontend"
config.rails_lineman.deployment_method = :copy_files_to_public_folder
Commit all changes and push to Heroku!
$ git push heroku master
You can see this app running on heroku here and grab the code from here.
There are many ways in which you can organize, separate and deploy your project, this is proposed approach way of dealing with this specific technology pairing (AngularJS/Rails). This post plugs in with our previous post just in case you wonder why we are eperimenting with these deployment methods.
Other awesome related projects worth checking out are Meteor, Gyoman, Ember, Sails, MEAN, and a bunch of others.
We hope this information helps you to start with these awesome technologies. See you around!