Rails upgrade to angular 2 - javascript

I would like to upgrade my existing Rails and Angular 1.x application. I'm following the ng-upgrade documentation and seeing that there are many dependencies including systemjs, typescript, tsd and a few other javascript libraries. Ideally there would be a angular-2 gem that would have all the dependencies but I'm not able to find that. Next I looked for gem's for each dependency but there isn't one for tsd.
Does it make sense to switch over to a custom build strategy so I can use npm for javascript package management? I read this article that recommends gulp but I do like the convenience of the asset pipeline.
Can anyone point me to examples of successfully using ng-upgrade with a rails project? Does it use a custom build solution like gulp or does it use the asset pipeline?

My main suggestion is not upgrading yet to Angular2, is still heavily in development and you'll face a lot of this issues like not finding a gem for rails.
Anyway, currently, angular2 can't be compiled with sprockets (the default rails pipeline), so you really want a custom solution.
My main suggestion is go with webpack, other options are browserify or gulp (and others), that's mainly a matter of taste. Overall, configuring a pipeline for angular2 is complicated, you have to take care of .d.ts files through typings (which is the updated version of tsd which now is deprecated), you have to transpile your typescript through tsc and possibly through babel too if you want to use async/await (which are really cool). You'll lose the ability to reference to your files in rails like image_path and such, using a custom pipeline, so you want to take that into account too.
Typescript is much more complex to compile than simple coffeescript files, you depend on every other file it reference, since it needs to compile check against it, don't expect something straightforward.
That being said, if you really want to work with Rails and Angular (2 or not), the right way to handle it is to have two separate projects, one with only the Rails app and one with the AngularJS path. In this way you separate concern, you can have a custom pipeline for Angular2 without impacting Rails and you'll be forced to correctly code your Angular2 app by using Rails as a JSON API, as you should.

My solution was to keep it as simple as possible without using webpack or the asset pipeline. I put the ts files in public and configured rails to serve the npm assets through the pipeline.
I put up a starter project with this structure as an example: https://github.com/jonnysamps/rails-ng2-starter
In many ways it has the benefits of having separate backend/frontend projects but keeps all the code together.

use angularjs gem
gem 'angularjs-rails', '~> 1.4', '>= 1.4.8'
insert into application.js
//= require angular

You can use http://bower.io/#install-bower and you can add two files to your the rails app .bowerrc and bower.json which is like GemFile

Related

Compile an opalized Ruby gem to Node package

It's not clear to me from the docs and guides whether the following is feasible with Opal:
I've written a builder gem which implements an API to build an object tree which is then written to XML (or AIXM to be exact, an aeronautical format). There are currently runtime dependencies, but I could get rid of those.
There's a guide on configuring gems for Opal, however, is it possible to use an opalized gem in a JavaScript project? Or convert it to a Node package?
We are currently in a process of designing a good NPM integration. But as of now, yes. You can build an Opal project to a .js (or .mjs) file and require it in the Node environment.
One issue though: Opal does not behave well in the JS environment, as it defines globals, modifies prototypes, etc. - it may cause a mess, though most incompatibilities have been sorted out over the years (in any case, you may consider running Opal code in a WebWorker). The main issue here is that such a package will inadvertently include opal corelib - and you should take care to include it just once. So, your Opal part of the application should be compiled together, not split together into multiple packages. We will work on correcting that issue in the following months.
As for interfacing Opal from JS, you should take a look at this: https://github.com/opal/opal/blob/master/docs/compiled_ruby.md#ruby-from-javascript

Rails 5.2+: why still use assets pipeline with webpacker?

I was reading the Rails webpacker gem documentation where it says:
Webpacker makes it easy to use the JavaScript pre-processor and bundler webpack 4.x.x+ to manage application-like JavaScript in Rails. It coexists with the asset pipeline, as the primary purpose for webpack is app-like JavaScript, not images, CSS, or even JavaScript Sprinkles (that all continues to live in app/assets).
However, it is possible to use Webpacker for CSS, images and fonts assets as well, in which case you may not even need the asset pipeline. This is mostly relevant when exclusively using component-based JavaScript frameworks.
I'm trying to understand the rationale behind using both the older assets pipeline for CSS/images/JS-sprinkles if webpacker is capable of handling all of this?
I've read some other articles that walk me through using webpacker for all of this, but I don't understand the reasoning behind this decision.
Is this just to support legacy applications and eventually the older assets pipeline will go away and webpacker will be used for everything in Rails apps?
As a maintainer of an app that existed before Webpacker, I can give you one reason:
It's hard to migrate an existing frontend from Sprockets to Webpack.
Sprockets builds all JS into one big file with shared scope. Webpack isolates the scope of every JS module. To migrate to Webpack, you need to make sure your code still works with the scope isolation.
Which is often problematic, because in the Sprockets times you didn't have proper JS requires, either, and had to rely on globals or top-scope variables to share code and data between your JS source files.
Rails doesn't offer a painless transition path from Sprockets compilation to Webpack. So, it must support both.
But to answer your other question - going forward, you should use Webpacker if you have enough JS to make it worthwhile.
If your frontend is simple, you will skip some JS nuisances if you use Sprockets. Like if you want to add 10 lines of JS to your app, you might not want to setup a whole JS environment with dependency management and node_modules etc - which is the price of using Webpack/Webpacker. It would be even more senseless to manage a JS environment if all you want is to compile CSS and add digests to your image filenames - which Sprockets is perfectly capable of, without a package.json and anything else JS related.
Therefore, there's a second reason:
Webpacker is good for apps that have a significant frontend codebase. Sprockets is good for adding a bit of JavaScript to a traditional server-rendered app, and for apps with no JavaScript at all.

Dynamically pull in dependencies for angular project

So I am working with a couple of different Angular starter kits, but I have yet to find one that automatically puts in the script src, for the vendor resources such as angular formly, bootstrap, etc., in the index.html. I am trying to make it so my dependencies in my module can work.
Anyone know of any good grunt or gulp build that would take care of this?
I believe grunt-wiredep is what you are looking for. It will inject your bower dependencies into your 'index.html'.
however if you are trying to include JS dependencies into a stand-alone angular module meant to be used with different HTML applications, you will need to concatenate those dependencies into a single deployable JS file. This can be easily done with grunt-contrib-uglify.

rake-pipeline or requirejs

I am about to start a new emberjs project and I cannot decide whether to use requirejs or rake-pipeline.
The ember advice seems to be to use the rake-pipeline.
Anybody any thoughts on either side of the argument?
If you want to load the dependencies dynamically after page load on an as-and-when-required basis then requirejs is the preferred option.
However if loading all the script when the page loads is not an issue for you (amount of javascript is small, or lot of javascript is required just for the rendering of content) then rails asset pipeline reduces a lot of boilerplate for you because even if you use require js you will eventually have to use r.js compiler to bundle all the dependencies into a single script. Rails does all of this concatanation and minification transparently behind the scenes without you having to do anything at all. Using the rails asset pipeline eases rolling deployment for you because in development scripts are all served as individual files without minification and in production scripts are served as minified and concatenated. This does not require you to run any build script or optimizer upon every change and you don't even have to modify anything in your HTML files. As long as you follow the sprockets specifications and specify the dependencies (which you have to do in case of requirejs too) everything works out of the box.
Also, Rails asset pipeline does not tie your client application to rails platform as sprockets (the dependency manager used behind in the rails pipeline) can be used independently without rails.
If however AMD compatibility is important for you (for example you are planning on using the same code on a NodeJS server as well as client, or are creating a distributable library) then requirejs is a great option.
You can also take a look at https://github.com/jwhitley/requirejs-rails/ which attempts to integrate requirejs into the rails pipeline. Please make sure that you have a reasonable level of familiarity with both requirejs and rails before you adopt this approach.

Bundler for javascript, or how to source control external javascript files

I am in the process of converting an existing Rails 3.1 app I made for a client into a Backbone.js app with the Rails app only as a backend server extension. This is only a personal project of mine, to learn more about Backbone.js.
While setting up Backbone.js (using Backbone-on-Rails), I noticed I have some dependencies (like backbone-forms) that come from external sources and are frequently updated.
I've grown accustomed to using Bundler to manage my Ruby gems, but I haven't found anything similar for JavaScript files. I'm wondering if there is any way to do the same for Javascript (and possibly css) files.
Basically I can see three possibilities to solve this issue:
Simply write down all the sources for each JS file and check these sources from time to time to see what has changed.
Use some kind of existing "Bundler for Javascript" type of tool, I've been looking for something like this but have yet to find anything (good).
Since most of these JS files will be coming from Git anyway, use Git to get the files directly and use checkout to get the latest version from time to time.
I prefer the last option, but was hoping on some more input from other people who have gone this route or preferred some other way to tackle this issue (or is this even an issue?).
I figure the Git way seems easy, but I am not quite sure yet how I could make this work nicely with Rails 3.1 and Sprockets. I guess I'd try to checkout a single file using Git and have it be cloned in a directory that is accessible to Sprockets, but I haven't tried this yet.
Any thoughts?
You don't mention it in your alternatives, but ideally you should use something like Maven to manage your dependencies. Unfortunately, there are no public repositories for javascript files. This discussion lists some other options which might be of help to you: JQuery Availability on Maven Repositories
For now I've settled on using the Git solution combined with some guard-shell magic.
The steps I follow:
Create a dependencies directory somewhere on your local drive
Clone the repositories with javascript (or css) files you want to use in the app
Set up a custom guard-shell command to do the following:
group 'dependencies' do
guard 'shell' do
dependencies = '~/path/to/dependencies/'
watch(%r{backbone-forms/src/(backbone\-forms\.js)}) {|m| `cp #{dependencies + m[0]} vendor/assets/javascripts/#{m[1]}` }
end
end
Place the Guardfile at the root of the app directory
It takes some time to set things up, but after that, when you have the Guard running, and you pull changes into your dependencies, the required files are automatically copied to your application directory, which are then part of your repository.
It seems to work great, you need to do some work for each new file you want to include in the asset pipeline, but all that is required is cloning the repository in your dependencies directory and adding a single line to your Guardfile, for example for the backbone-form css:
watch(%r{backbone-forms/src/(backbone\-forms\.css)}) {|m| `cp #{dependencies + m[0]} vendor/assets/stylesheets/#{m[1]}` }
Also, the reason I added this Guard to a group is because I keep my dependencies outside the main application directory, which means guard normally doesn't check my dependencies directory. To make this work, I start up my main Guard processes using bundle exec guard -g main and use bundle exec guard -w ~/path/to/dependencies -g dependencies in a new terminal window/tab to specify the -w(atchdir).

Categories

Resources