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

Changes related to RoR 5.1 optionable Webpacker #452

Open
foton opened this issue Sep 7, 2017 · 15 comments
Open

Changes related to RoR 5.1 optionable Webpacker #452

foton opened this issue Sep 7, 2017 · 15 comments

Comments

@foton
Copy link

foton commented Sep 7, 2017

HI,
Rails 5.1 give ability to use webpacker gem to manage javascript libraries. But this management is completely out of Rails so it cannot see gem cocoon.

Can You, please, add package.json file and build an NPM package of cocoon?

Related Issues in other project
ifad/data-confirm-modal#53 and
rails/webpacker#57 (comment)

@nathanvda
Copy link
Owner

We can still use regular gems with assets together with the webpacker option in rails 5.1? Let me check. I am not sure it makes no sense to package cocoon.js in npm? (imho cocoon is not a javascript library, it makes no sense without the rails/ruby interaction).

@foton
Copy link
Author

foton commented Sep 7, 2017

Yes, assets pipeline can be run together with webpacker.
I found outdated NPM package https://www.npmjs.com/package/cocoon-rails. But just by name, not sure if it does what is expected.

@KurtPreston
Copy link

Asset pipeline can be run together with webpacker, but many people (myself included) are trying to migrate entirely to webpack from sprockets.

It'd be great provide a way to use cocoon without relying on the asset pipeline.

@iainbeeston
Copy link

@nathanvda I've just tried to get cocoon working with webpacker but in the end I had to give up.

  1. First I tried loading cocoon using a sprockets//= require cocoon from my webpacker pack file. That didn't work. I think that's because sprockets doesn't get run on webpacker files.
  2. Then I tried import 'cocoon' from my pack file. I suspect if I could find the right path to add to resolved_paths in config/webpacker.yml this might work (or maybe not... see below)
  3. Next I copied cocoon.js directly into my project, and loaded it using import 'cocoon' from my pack file. That worked, but unfortunately cocoon.js cannot access the jQuery object which it needs, because it doesn't explicitly import it (nothing can be used without being required with webpacker).
  4. I tried a few ways to make jQuery a global, in order to access it from cocoon.js but had no luck (it still couldn't find the jQuery object).

I could go through and rewrite cocoon.js to use import statements, but it feels like that would outweigh the advantages of using cocoon rather than rolling my own. I also suspect I could add a sprockets application.js file, and //=require cocoon from there, and load both that and my webpacker application.js but that feels rather messy, not least because I could end up having to load jQuery twice (once in sprockets and once in webpacker)

Hopefully this is helpful to someone!

@mikavilpas
Copy link

Thanks @iainbeeston , I managed to import cocoon by just copying it to my project at work, and having a global jquery object present. Seems to work well.

I have this hack to have a global jquery object, which seems to be a requirement of many libraries by the way:

window.$ = window.jQuery = require("jquery")

There are other ways to do this too, but I found this the simplest to understand.

@vill
Copy link

vill commented Apr 27, 2018

Rails 5.2.0
Webpacker 3.4.3
rails webpacker:install:erb
// config/webpack/environment.js
const { environment } = require('@rails/webpacker')
const erb             = require('./loaders/erb')
const webpack         = require('webpack')

environment.loaders.append('erb', erb)

environment.plugins.prepend(
  'Provide',
  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery'
  })
)

module.exports = environment
# config/webpacker.yml
default: &default
  # Search jQuery in node_modules of the application and not in the cocoon directory
  resolved_paths: ['node_modules/jquery/dist']
// app/javascript/packs/application.js.erb
import "<%= File.join(Gem.loaded_specs['cocoon'].full_gem_path, 'app', 'assets', 'javascripts', 'cocoon') %>"

@diman0o1999
Copy link

@vill Looks like right solution, but I still have unresolved jquery.
2019-02-28 14 37 14

I had everything by your instruction

@xrnm
Copy link

xrnm commented Mar 4, 2019

This was clean and worked well for us: https://github.com/joerodrig/cocoon-js (https://www.npmjs.com/package/cocoon-js)
It would probably be good to publish an officially supported version and add doc to that.

@nathanvda
Copy link
Owner

Yes indeed probably a good idea. There are now already two packages on npm for cocoon cocoon-rails and cocoon-js. I will have to look into how I can deploy from one repository to both npm and rubygems.

@xrnm
Copy link

xrnm commented Mar 5, 2019 via email

@thedanbob
Copy link

This is how the rails-ujs package handles it:

// package.json
{
  "main": "lib/assets/compiled/rails-ujs.js",
  "files": [
    "lib/assets/compiled/*.js"
  ]
}

Looks like files specifies which files get published to npm, and main is what gets imported.

FWIW, here's how I solved loading javascript from gems that aren't available on npm (applicable to more than just cocoon):

// config/webpack/environment.js
environment.plugins.prepend('GemAssetsPlugin', require('./plugins/gem-assets'))
// config/webpack/plugins/gem-assets.js
const { exec } = require('child_process')

module.exports = {
  apply(compiler) {
    compiler.hooks.beforeRun.tap('GemAssetsPlugin', (compilation) => {
      exec('mkdir -p vendor/frontend/js')
      exec('cp $(env -u DEBUG bundle show cocoon)/app/assets/javascripts/cocoon.js vendor/js')
      return true
    })
  }
}
# config/webpacker.yml
resolved_paths: ['vendor/js']

@McRipper
Copy link

McRipper commented Feb 29, 2020

This is how the rails-ujs package handles it:

// package.json
{
  "main": "lib/assets/compiled/rails-ujs.js",
  "files": [
    "lib/assets/compiled/*.js"
  ]
}

Looks like files specifies which files get published to npm, and main is what gets imported.

FWIW, here's how I solved loading javascript from gems that aren't available on npm (applicable to more than just cocoon):

// config/webpack/environment.js
environment.plugins.prepend('GemAssetsPlugin', require('./plugins/gem-assets'))
// config/webpack/plugins/gem-assets.js
const { exec } = require('child_process')

module.exports = {
  apply(compiler) {
    compiler.hooks.beforeRun.tap('GemAssetsPlugin', (compilation) => {
      exec('mkdir -p vendor/frontend/js')
      exec('cp $(env -u DEBUG bundle show cocoon)/app/assets/javascripts/cocoon.js vendor/js')
      return true
    })
  }
}
# config/webpacker.yml
resolved_paths: ['vendor/js']

It works, but I want to point out:

exec('mkdir -p vendor/frontend/js')

must be:

exec('mkdir -p vendor/js')

Then you can:

// /javascripts/packs/application.js
import 'cocoon-js'

@datty258
Copy link

Yes indeed probably a good idea. There are now already two packages on npm for cocoon cocoon-rails and cocoon-js. I will have to look into how I can deploy from one repository to both npm and rubygems.

in /javascript/packs/application.js
import 'cocoon-js'

@Petercopter
Copy link

As the latest person to stumble through this, let me post what appears to be working for me, based on what everyone else is doing. I've got jQuery mixed in here, since obviously that's used by Cocoon.

Should I gitignore that vendor folder that gets created? I feel like that shouldn't be committed...

// config/webpack/environment.js

const { environment } = require('@rails/webpacker')
const webpack = require('webpack')

environment.plugins.prepend('GemAssetsPlugin', require('./plugins/gem-assets'))
environment.plugins.prepend(
  'Provide',
  new webpack.ProvidePlugin({
    $: 'jquery/src/jquery',
    jQuery: 'jquery/src/jquery'
  })
)

module.exports = environment
// config/webpack/environment.js

environment.plugins.prepend('GemAssetsPlugin', require('./plugins/gem-assets'))
// config/webpack/plugins/gem-assets.js

const { exec } = require('child_process')

module.exports = {
  apply(compiler) {
    compiler.hooks.beforeRun.tap('GemAssetsPlugin', compilation => {
      exec('mkdir -p vendor/js')
      exec(
        'cp $(env -u DEBUG bundle info cocoon --path)/app/assets/javascripts/cocoon.js vendor/js'
      )
      return true
    })
  }
}
# config/webpacker.yml

additional_paths: ['vendor/js']

@thedanbob
Copy link

In principle it should be, but I didn't bother to .gitignore it myself. The cocoon JS hasn't changed in over a year so it doesn't really matter one way the other.

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