Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to include JS from gems? #57

Closed
cgarvis opened this issue Jan 13, 2017 · 25 comments
Closed

How to include JS from gems? #57

cgarvis opened this issue Jan 13, 2017 · 25 comments

Comments

@cgarvis
Copy link
Contributor

cgarvis commented Jan 13, 2017

Specifically I would like to require the action_cable javascript into my packs. Anyone try this yet?

@guilleiguaran
Copy link
Member

In your case you can require action_cable from npm: https://www.npmjs.com/package/actioncable

@merqlove
Copy link
Contributor

yep, now always sit at npmjs.com.
Just remember, don't do ./bin/yarn clean. It will make ignore file for all packages, which is fighting with actioncable.js.

@dhh dhh closed this as completed Jan 17, 2017
@foton
Copy link

foton commented Sep 6, 2017

And in other cases? Like cocoon gem (https://github.com/nathanvda/cocoon) ?

@guilleiguaran
Copy link
Member

@foton You can send a PR to Cocoon to include a package.json, you can use this as example: ifad/data-confirm-modal#53

@nathanvda
Copy link

Hi, I maintain the cocoon gem. I am a bit confused, so maybe a silly question, but since webpacker coexists with the normal asset pipeline, why should a gem containing javascript "sprinkles" move those to npm where they make no sense?

@gauravtiwari
Copy link
Member

Yes, that's another way so you could require cocoon gem JS into your sprockets application.js but I guess it might not make sense for people who don't want to use asset pipeline at all since that's totally possible with Webpacker.

@nathanvda Webpacker co-exists with asset pipeline but can also be used alone, since Rails also supports yarn for installing npm packages it would make sense to publish the JS counterpart to npm for future, since that's where everything is moving. I understand it's a bit more work though :) i.e. publishing two packages.

@foton
Copy link

foton commented Sep 19, 2017

I made it work by

  1. Unpacking gem cocoon-1.2.10 into vendor/gems/cocoon-1.2.10 (according to https://makandracards.com/makandra/538-freeze-vendor-unpack-a-single-ruby-gem-with-and-without-bundler). And modifiing Gemfile.

  2. Adding vendor path resolved_paths: ['vendor'] to config/webpacker.yml.

  3. Created file vendor/gems/index.js with import {} from './cocoon-1.2.10/app/assets/javascripts/cocoon.js';

  4. Import this file in app/javascript/application.js with import {} from 'gems/index.js'; //in /vendor/gems

Of course, no npm package is then needed.

@vitobotta
Copy link

Hi, how to import assets from a gem for example such as https://github.com/estum/growlyflash? This gem adds both assets and some Ruby code. What do I set in resolved_paths without unpacking the gem into the vendor directory? Thanks.

@dmitry
Copy link

dmitry commented Feb 4, 2018

Is there are an easier way to import javascript rather than unpacking a gem?

@dmitry
Copy link

dmitry commented Feb 4, 2018

Looks like the best would be convert gems to npm packages: #488

@valterbarros
Copy link

I agree with @dmitry, My problem is because I'm work in a old project with old front end gems, and the version from theses gems dont exist in npm because is so old like 2014. In the last opition I will up this gems in npm packages.

@Petercopter
Copy link

For anyone looking for context, the idea is to move all assets over to Webpacker, rather than having to maintain say, jQuery in both the asset pipeline and the package manager.

https://medium.com/@coorasse/goodbye-sprockets-welcome-webpacker-3-0-ff877fb8fa79

@qwertme
Copy link

qwertme commented Oct 23, 2018

I solved it by enabling erb like this comment describes: nathanvda/cocoon#452 (comment)

Once you have access to the JS via ERB you can make a shim, this is what I did for the best_in_place gem:

import jQuery from 'jquery'
import 'jquery-autosize'

<%= File.read(File.join(Gem.loaded_specs['best_in_place'].full_gem_path, 'lib', 'assets', 'javascripts', 'best_in_place.js')) %>

@valterbarros
Copy link

Seems be a good solution @qwertme

@guilleiguaran
Copy link
Member

I think we can add an helper to wrap that logic making easier to load assets from gems.

@cseelus
Copy link

cseelus commented Feb 19, 2019

@guilleiguaran Is there anything available yet for this use case?

@DrkCloudStrife
Copy link

I was also struggling with this and I got a solution that worked for me that I wanted to share. If you follow the instructions in link that @qwertme shared, you can write a ruby class helper in your lib folder and include it with rails-erb-loader-dependencies to make it more presentable in your webpack application.

This is how I'm currently using this:

Rails 5.1.6.1
Webpacker 4.0.2
bundle exec rails webpacker:install:erb
# lib/webpack_helper.rb
class WebpackHelper

  class << self
    def my_gem_js(path)
      File.join(Gem.loaded_specs['my_gem'].full_gem_path, 'app/assets/javascripts/my_gem/', path)
    end

    def my_gem_css(path)
      File.join(Gem.loaded_specs['my_gem'].full_gem_path, 'app/assets/stylesheets/my_gem/', path)
    end
  end

end
// app/javascript/packs/application.js.erb 
/* rails-erb-loader-dependencies ../lib/webpack_helper */

import "<%= WebpackHelper.my_gem_js('path-to-my-file.js') %>";
import "<%= WebpackHelper.my_gem_js('path-to-another-file.coffee') %>";

May not be much, but it helps me DRY things up and I can add more class methods for other gems I may need. Hope this helps!

@andrewhaines
Copy link

This setup worked for me. I made a few tweaks to get it doing what I needed:

https://github.com/projectblacklight/blacklight/wiki/Using-Webpacker-to-compile-javascript-assets

Feel free to hit me up if you're running into issues and want more details.

@isteel
Copy link

isteel commented Jun 15, 2020

I solved it using the idea of a separate pack file for gems.
In packs/gems.js.erb:

import {} from '<%= File.join(File.join(Gem.loaded_specs['best_in_place'].full_gem_path, 'lib', 'assets', 'javascripts', 'best_in_place.js')) %>'
import {} from '<%= File.join(File.join(Gem.loaded_specs['best_in_place'].full_gem_path, 'vendor', 'assets', 'javascripts', 'jquery.autosize.js')) %>'

The key one for me was the second import - without that I was getting autosize not found.

In packs/application.js:

import './gems.js.erb'

@jan-gerritsen
Copy link

jan-gerritsen commented Sep 23, 2020

I could not make any of these work, but (for Rails 6) the asset pipeline still works, so I did this

# config/initializers/assets.rb
Rails.application.config.assets.precompile += %w( best_in_place.js )

and in my erb file

<%= javascript_include_tag 'best_in_place' %>

@infogrind
Copy link

From what I understand, the pre-Rails 6 behavior (with JavaScript assets being handled by Sprockets) was such that the assets pipeline could access any JavaScript files in a Gem's app/assets/javascript directory (such as in this example).

Naively, it would seem that the Webpacker Gem could just solve this by making files under a Gem's app/javascript directory available through the path that's used to search JavaScript assets. From the above discussion, which focused mainly on workarounds, it is not clear to me what (if anything) would speak against implementing such a solution.

@mcmire
Copy link

mcmire commented Jun 15, 2021

I think others have shared this opinion here but just to extend this concept, Webpacker is designed to be a wrapper around Webpack, a tool widely used in the JavaScript community. The JavaScript community uses NPM to keep and distribute packages and has done so for several years now. In my opinion, people who've made Ruby gems which wrap JavaScript libraries should be encouraged to publish those libraries to NPM. Webpacker should embrace the future, and any behavior supporting Ruby wrappers should stay in Sprockets and not get ported over into Webpacker.

@infogrind
Copy link

Thank you for the explanation @mcmire. As I am new to all this, I am definitely still missing a lot of context and grateful for all the bits of information I get.

I think any solution that forces a package to be maintained in two separate places (say as a Gem and as an NPM module) is something to be avoided. I think in the example case of libraries such as Bootstrap or Semantic UI, which combine CSS and JS, the problem is that Rails 6 uses two quite different solutions to serve JS and CSS assets. I hope this will be cleaned up at some point.

@cseelus
Copy link

cseelus commented Jun 15, 2021

@infogrind You can (and probably should, if you depend on easy to install & modern/up-to-date packages) use Webpacker for both JS and CSS assets.

@infogrind
Copy link

Thanks @cseelus , I wasn't aware this was possible but now I am 😀
I found this article, which does a nice job of explaining how to get it done in Rails 6, in case anyone else is interested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests