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 make it works with webpacker? #237

Closed
dbelyaeff opened this issue Mar 28, 2018 · 28 comments
Closed

How to make it works with webpacker? #237

dbelyaeff opened this issue Mar 28, 2018 · 28 comments

Comments

@dbelyaeff
Copy link

Rails 5.2 introduce Webpacker gem which can help you to avoid using Sprockets.

Is there any way to make JS-Routes usable with Webpacker?

@le0pard
Copy link
Member

le0pard commented Mar 28, 2018

Generate separate file from js-routes and use it in webpack. For any routes change you need regenerate this file.

@dbelyaeff
Copy link
Author

Is there any way to automate this?

@le0pard
Copy link
Member

le0pard commented Mar 29, 2018

@codEmotion rake task?

@dbelyaeff
Copy link
Author

Thanks.

This is the recipe:

window.Routes = require('./routes.js')

@le0pard
Copy link
Member

le0pard commented Mar 29, 2018

I think require('./routes.js') can work with ES6 module system - no need to apply it on window.

@bogdan
Copy link
Collaborator

bogdan commented Mar 30, 2018

I think we should add a doc on that to readme.

@gtarsia
Copy link

gtarsia commented Jun 13, 2018

I created my own webpack loader for the routes, so it would rebuild when I changed routes.rb. It worked but it would take 6 seconds to build, because it had to reload the whole rails app. I didn't like it.

I would instead recommend writing your own generator instead of a rake task because of the meaning of what this is doing.

# lib/generators/routes_generator.rb
# run it with: rails generate routes
class RoutesGenerator < Rails::Generators::Base
  def create_initializer_file
    create_file "app/javascript/routes.js", JsRoutes.generate
  end
end

And use your own path/options. This way you don't need to remember options to pass to rake js:routes.

@hadees
Copy link

hadees commented Jun 16, 2018

@gtarsia but you still have to use Sprockets correct? There seems like you shouldn't need it though.

@gtarsia
Copy link

gtarsia commented Jun 16, 2018

@hadees this is to use webpacker instead of sprockets.

I used app/javascript in my generator as the path for the routes.js file. You import this file from a webpacker pack.

Also, remember that if you replace sprockets with webpacker, you should install and import jquery-ujs

@ProGM
Copy link

ProGM commented Jul 31, 2018

Another option to use js-routes with webpacker is this:

Add rails-erb-loader

yarn add rails-erb-loader

Setup the erb loader

Create a file in config/webpack/loaders/erb.js:

module.exports = {
  test: /\.js\.erb$/,
  enforce: 'pre',
  exclude: /node_modules/,
  use: [{
    loader: 'rails-erb-loader',
    options: {
      runner: (/^win/.test(process.platform) ? 'ruby ' : '') + 'bin/rails runner'
    }
  }]
}

Then load it in environment.js:

...
const erb =  require('./loaders/erb')
...
environment.loaders.append('erb', erb)

Create a js-routes file:

Go into app/javascripts and create a js-routes.js.erb file, then paste:

<%= JsRoutes.generate() %>

Then you can simply import it as an es6 module, like this:

app/javascripts/packs/application.js

import Routes from '../js-routes.js.erb';

console.log(Routes.your_custom_path)

// If you want you can make it public:
window.Routes = Routes;

Hoping you can find it useful ;)

@paulodeon
Copy link

paulodeon commented Aug 22, 2018

@ProGM your solution works, a couple of points to note:

  • You can install the erb loader using bundle exec rails webpacker:install:erb
  • You'll need to uncomment the require "sprockets/railtie" line in your application.rb
  • You can avoid the .js.erb in the import if you add - .js.erb to extensions in webpacker.yml

@PikachuEXE
Copy link
Contributor

PikachuEXE commented Sep 12, 2018

@ProGM
It throws error with message

"export 'default' (imported as 'Routes') was not found in './../../../../assets/javascripts/plugins/js-routes/index.js.erb'

if babel-plugin-transform-runtime is used

I think this is due to generated code not having module.exports

Let me fork and test if adding module.exports would solve this issue

Update 1: My solution

// app/assets/javascripts/plugins/js-routes/index.js.erb
<%# encoding: UTF-8 %>

// Tell webpack to watch these files
// https://github.com/usabilityhub/rails-erb-loader#dependencies
/* rails-erb-loader-dependencies ./../config/routes.rb */

<%= JsRoutes.assert_usable_configuration! && JsRoutes.generate %>

// Exporting as default is required when using `babel-plugin-transform-runtime`
export default this.Routes

@le0pard
Copy link
Member

le0pard commented Sep 12, 2018

@PikachuEXE code have module.exports, it just do not have default scope, because default is separate key in export/import, not root in module.exports

image

@ElMassimo
Copy link

ElMassimo commented Jun 22, 2020

If you are looking for a solution that plays nicely with Webpacker, you might want to check out js_from_routes.

Although it doesn't come with a default implementation for url interpolation, it's very flexible and you can generate code that uses your own API helpers.

Comparison

For a comparison with this library, check this pull request, which illustrates how it can be customized to provide a nicer API.

@marvinthepa
Copy link

@paulodeon

* You'll need to uncomment the `require "sprockets/railtie"` line in your `application.rb`

Sounds like this might not be necessary anymore with #257 fixed (released in v1.4.10).

@stoplion
Copy link

stoplion commented Aug 10, 2020

I'm also using Webpacker

in application.js added a..
require('js-routes');

getting a..
Module not found: Error: Can't resolve 'js-routes' in

@marvinthepa
Copy link

@stoplion there is not file that is generated that is called "js-routes.js". The default path is still app/assets/javascripts/routes.js, see

file: -> { Rails.root.join('app','assets','javascripts','routes.js') },
.

You can change that:

+++ b/config/initializers/js_routes.rb
@@ -0,0 +1,3 @@
+JsRoutes.setup do |config|
+  config.file = "app/javascript/js-routes.js"
+end

but even then, you need require('../js-routes') instead of require('js-routes'). Or you can useimport Routes from '../js-routes' in the files that use the Routes object.

@bogdan
Copy link
Collaborator

bogdan commented Aug 10, 2020

I made a few patches to make it more compatible with webpacker:

  • Default generation file is now at app/javascript/routes.js if app/assets/javascripts doesn't exist
  • Added default export key for better es6 experience.

I would be grateful if someone can try to use the gem from master and report of these features are working correctly.

@marvinthepa
Copy link

I have not had any issues using

import Routes from '../app/javascript/js-routes'

using 1.4.9, so I do not know why 7c654aa is necessary. But then again, I am far from being an expert on that topic.

@itsNikolay
Copy link

itsNikolay commented Oct 8, 2020

Just leave my notes how I migrated from Sprockets to Webpacker, perhaps somebody helps

  1. remove/rename assets directory
$ mv app/assets app/deprecated_assets
  1. Generate js-routes file with (every time when you update routes.rb file)
$ rails js:routes
  1. Make sure it created app/javascript/routes.js

  2. Add trinspiler to import routes.js file

$ yarn add @babel/plugin-transform-modules-umd
  1. ./babel.config.js
    plugins: [
      require('@babel/plugin-transform-modules-umd'), // to import `JsRoutes.generate!` file
    ]
  }
}
  1. ./app/javascript/packs/application.js
import Routes from 'routes'
// backward compatibility
window.Routes = document.Routes = Routes
  1. Enjoy! 👍

@bogdan
Copy link
Collaborator

bogdan commented Nov 23, 2020

@itsNikolay can you explain why you would need @babel/plugin-transform-modules-umd to make it work? Can you try version 1.4.12 (currently latest) and see if it works without it?

@sec0ndhand
Copy link

@bogdan I know I'm not @itsNikolay, but I was having the same problem. I upgraded my package from 1.4.9 to 1.4.13 and it broke my app. I was using the asset pipeline, but decided to make the jump and start using Webpacker for js-routes since we already have react in our project, and are using Webpacker already.

I followed the set up in the readme that explains using app/javascript/routes.js.erb and I was getting this error in the browser:

Uncaught TypeError: Cannot assign to read only property 'exports' of object '#<Object>'

Once I added @babel/plugin-transform-modules-umd the error went away. A UMD bundle, though making your shipped JS larger, allows it to be imported across browsers, nodejs, commonjs among others. Anyway, maybe a consideration would be to ship jsroutes with an option to create a UMD bundle instead, which would eliminate the need for the babel plugin. Thanks for all your hard work, it really helps those of us that know rails, but need to code in JS!

bogdan added a commit that referenced this issue Jan 4, 2021
@bogdan
Copy link
Collaborator

bogdan commented Jan 4, 2021

@sec0ndhand I did what I could in v1.4.14. It is hard to make it work for all environments- js is such a mess. Can you try that and see if it works without @babel/plugin-transform-modules-umd?

bmwiedemann pushed a commit to bmwiedemann/openSUSE that referenced this issue Jan 22, 2021
https://build.opensuse.org/request/show/865199
by user coolo + dimstar_suse
updated to version 1.4.14
 see installed CHANGELOG.md
  ## v1.4.14

  * Fix compatibility with UMD modules #237 [Comment](railsware/js-routes#237 (comment))

  ## v1.4.13

  * Improve compatibility with node environment #269.
  * Change default file location configuration to Webpacker if both Webpacker and Sprockets are loaded

  ## v1.4.11

  * Use app/javascript/routes.js as a default file location if app/javascript directory exists
  * Add `default` export for better experience when used as es6 module

  ## v1.4.10

  * Require engine only when sprockets is loaded #257.
@sec0ndhand
Copy link

Sorry it took so long @bogdan. I have tried this, and this did not work once I removed @babel/plugin-transform-modules-umd.

@bogdan
Copy link
Collaborator

bogdan commented May 17, 2021

I've released v2.0 with complete support of ESM modules and webpacker. Webpacker setup is now in the readme. Please upgrade and open another issue if there are still problems.

@bogdan bogdan closed this as completed May 17, 2021
@bogdan
Copy link
Collaborator

bogdan commented May 18, 2021

@le0pard it would be helpful if you could try upgrade guide https://github.com/railsware/js-routes/blob/master/VERSION_2_UPGRADE.md for any of your projects.

@le0pard
Copy link
Member

le0pard commented May 18, 2021

@bogdan thanks. Will try later and will provide feedback (in PR or just as comment)

@le0pard
Copy link
Member

le0pard commented Jul 6, 2021

@bogdan I did test on small project - all works. Currently I did not found project, which using js-routes in our company - all migrated to hardcoded values in JS :)

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