So I have an application which is using Rails 3.1.3, and gets deployed under Jruby. We allow the users to import their own themes (so their own CSS content) and for that reason we do not pre-compile our assets in production (I am aware of performance reasons of pre-compiling, however we don't find the performance hit that bad, and this was the best decision for us).
Since we want to support multiple languages, we also have translation files. Rails translations being in config/locales/*.yml and then we have translations required for our Javascript files. Previously we were putting these translations in a assets/javascripts/config.js file - but this is highly unscalable for the future. We wanted a solution that would allow the Javascript files to pull from the config/locales/*.yml files. We came across the i18n-js Gem ( i18n-js ).
This gem works exactly as expected locally. However, in production, we are getting errors. The first problem was application.js could not locate the i18n.js file. To me, this made sense, since we were not pre-compiling the assets, and the i18n-js Gem would obviously not be installed on the production server, the application would not have access to the i18n.js file. So I added the file manually in the assets/javascripts/ path. That fixed that error.
Now we are getting this error:
2012-10-05[INFO] - Internal Server Error: Sprockets::FileNotFound couldn't find file 'file:/tmp/Jetty_0_0_0_0_application.war____.r5dru7/webapp/WEB-INF/lib/tmp-gems.jar!/gems/activesupport-3.1.3/lib/active_support/locale/en.yml'
(in /tmp/Jetty_0_0_0_0_application.war____.r5dru7/webapp/WEB-INF/app/assets/javascripts/i18n/translations.js)
I have checked the tmp-gems.jar and the gems.jar and the file is actually there... So that confuses me. My thoughts are that the i18n-js Gem simple assumes that you are pre-compiling your assets and was not designed to function without that in production where the gems are not actually installed on the server. However, I was wondering if anyone could provide some guidance on that thought? Am I right, or is there a way around this?
Note: If I do pre-compile the assets - there are no issues in production. And also note, this production issue has only shown up when we started using this Gem - so I know it is related to that gem's usage, and nothing else. Everything was working before this change.
Also, if anyone has better suggestions for getting around the language problem (we don't want translations maintained in a JS file, AND in a locales YAML file). I would appreciate suggestions to that end as well!
Thanks!
Related
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.
I'm using capistrano to deploy from localhost to the remote server.
Everytging works fine except one thing: js and css files do not update. Not even one. Not even application.js or application.css is updated on the server.
What should I do to make capistrano update js and css files? I think they are cached so I only need to clear this cache files. How do I do that? I think this is a common question but I could not find any information about.
Any help is appreciated. Thank you in advance.
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.
I may just be doing something wrong but all of my javascript files as well as my css files are each individually available. This would be perfect except asset pipeline also adds my applicaion.js which is making my javascript crash. Is there a way that I can tell rails not to load all the individual files, I want JUST the application.js/css files.
As you can see here, the search and sort bars are shown twice because the javascript is trying to run twice. Anyone else deal with this? I have seen a couple other people ask this question and have yet to see a good answer.
IIRC this is caused by you having pre-compiled assets in public/assets, but having config.assets.compile set to true in the config for your current environment.
Normally if you're compiling assets on each request application.css and .js will only contain code that you have specifically entered into those files in app/assets, whereas if the assets have been pre-compiled (and are in public/assets) you'll see all your css and javascript in those files.
To fix this issue rm -rf public/assets and you should be good to go.
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).