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

Actioncable Webpacker compilation issues with Rails 6 in production #35501

Closed
terracatta opened this issue Mar 6, 2019 · 25 comments · Fixed by rails/webpacker#2624
Closed

Actioncable Webpacker compilation issues with Rails 6 in production #35501

terracatta opened this issue Mar 6, 2019 · 25 comments · Fixed by rails/webpacker#2624
Labels

Comments

@terracatta
Copy link
Contributor

terracatta commented Mar 6, 2019

Steps to reproduce

  1. Generate a new rails 6 app (rails new myapp) with all the defaults
  2. Generate a new channel bin/rails g channel test
  3. Boot the app in development to confirm the websocket is connecting as expected
  4. Deploy the app to Heroku

Expected behavior

The websocket connection is successful and there are no console errors

Actual behavior

Console error Uncaught TypeError: r is not a function in action_cable.js.
In my source map the error points to the following line https://github.com/rails/rails/blob/master/actioncable/app/assets/javascripts/action_cable.js#L21

My Theories

It seems that webpacker compiles this file incorrectly (only in production) and doesn't seem to like that the variable is named _typeof. I can see there are distinct differences in how the file is compiled in production vs dev (these differences cause dev to work and prod to throw the aforementioned error)

If I revert back to the yarn package actioncable vs @rails/actioncable and I revert my consumer.js file to use the old import syntax, everything works fine.

Things I already tried to fix this:

  1. Ensure the node version between dev and production were identical (I am currently running node 11.x)
  2. Ensuring my actioncable (and other rails packages) were correctly set to their beta2 versions.
  3. Upgraded my webpacker version to the latest release in the Gemfile and the latest yarn package in package.json

If my bug is accurate, it stands to reason that perhaps it is not possible to deploy Rails 6 with actioncable in a production environment with the default generated files. I am curious if anyone has shipped a working actioncable feature on a brand new Rails 6 beta2 project with the default files and generators.

System configuration

Rails version: 6.0.0.beta2
Ruby version: 2.6.1

@terracatta terracatta changed the title Actioncable Webpacker compilation issues with Rails 6 Actioncable Webpacker compilation issues with Rails 6 in production Mar 6, 2019
@nextchessmove
Copy link

I think I ran in to the same issue. I have a new rails 6.0.0.beta3 project, and when I deployed it to my staging environment, I got the same error.

I was able to resolve it by copying action_cable.js from node_modules into my project's app/javascripts and importing it directly from there.

I'm not sure why it works and it's obviously not a good solution, but hopefully it will provide a clue to somebody who understands this better than me! I am using TypeScript if that makes a difference.

@simchikoops
Copy link

Also seeing this problem with rails 6.0.0.rc1. @nextchessmove workaround worked for me too.

@jonknapp
Copy link

I followed @nextchessmove's workaround to fix my issue, but had to do a bit more alteration. I run the same code through Storybook in React components and the following line would fail when Storybook tried to run it through Webpack.

import { createConsumer } from "../../../vendor/action_cable";

the error was:

WARNING in ./app/javascript/components/App/hooks/useActionCable.js 19:23-37
"export 'createConsumer' was not found in '../../../vendor/action_cable'
 @ ./app/javascript/components/App/index.jsx
 @ ./app/javascript/components/App/stories.jsx
 @ ./app/javascript/components sync stories\.jsx?$
 @ ./.storybook/config.js
 @ multi ./node_modules/@storybook/core/dist/server/common/polyfills.js ./node_modules/@storybook/core/dist/server/preview/globals.js ./.storybook/config.js (webpack)-hot-middleware/client.js?reload=true

Maybe the UMD build of the action_cable.js file is off? 🤷‍♂

I fixed my issue by doing a require when I needed it instead of a top of the file import.

@matthutchinson
Copy link

Seeing this problem with Rails 6.0.0.rc1 too, on a fresh Rails depot app (from the Agile Web Development with Rails book) - deployed to Heroku.

Locally everything with ActionCable works fine.

With Rails 6 RC1 my package.json looks like this;

{
  "name": "depot",
  "private": true,
  "dependencies": {
    "@babel/preset-react": "^7.0.0",
    "@rails/actioncable": "^6.0.0-alpha",
    "@rails/activestorage": "^6.0.0-alpha",
    "@rails/ujs": "^6.0.0-alpha",
    "@rails/webpacker": "^4.0.7",
    "babel-plugin-transform-react-remove-prop-types": "^0.4.24",
    "prop-types": "^15.7.2",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "turbolinks": "^5.2.0"
  },
  "version": "0.1.0",
  "devDependencies": {
    "webpack-dev-server": "^3.7.1"
  }
}

@timgentry
Copy link

timgentry commented Jun 24, 2019

Try updating your babel.config.js as per the Webpacker 4.0.7 CHANGELOG which fixed it for me. ActionCable is not compatible with es2015 which was enabled as part of @babel/preset-env

@matthutchinson
Copy link

No luck, same error - my babel.config.js matches Webpacker's CHANGELOG for 4.0.7:

module.exports = function(api) {
  var validEnv = ['development', 'test', 'production']
  var currentEnv = api.env()
  var isDevelopmentEnv = api.env('development')
  var isProductionEnv = api.env('production')
  var isTestEnv = api.env('test')

  if (!validEnv.includes(currentEnv)) {
    throw new Error(
      'Please specify a valid `NODE_ENV` or ' +
        '`BABEL_ENV` environment variables. Valid values are "development", ' +
        '"test", and "production". Instead, received: ' +
        JSON.stringify(currentEnv) +
        '.'
    )
  }

  return {
    presets: [
      isTestEnv && [
        require('@babel/preset-env').default,
        {
          targets: {
            node: 'current'
          }
        }
      ],
      (isProductionEnv || isDevelopmentEnv) && [
        require('@babel/preset-env').default,
        {
          forceAllTransforms: true,
          useBuiltIns: 'entry',
          corejs: 3,
          modules: false,
          exclude: ['transform-typeof-symbol']
        }
      ],
      [
        require('@babel/preset-react').default,
        {
          development: isDevelopmentEnv || isTestEnv,
          useBuiltIns: true
        }
      ]
    ].filter(Boolean),
    plugins: [
      require('babel-plugin-macros'),
      require('@babel/plugin-syntax-dynamic-import').default,
      isTestEnv && require('babel-plugin-dynamic-import-node'),
      require('@babel/plugin-transform-destructuring').default,
      [
        require('@babel/plugin-proposal-class-properties').default,
        {
          loose: true
        }
      ],
      [
        require('@babel/plugin-proposal-object-rest-spread').default,
        {
          useBuiltIns: true
        }
      ],
      [
        require('@babel/plugin-transform-runtime').default,
        {
          helpers: false,
          regenerator: true,
          corejs: false
        }
      ],
      [
        require('@babel/plugin-transform-regenerator').default,
        {
          async: false
        }
      ],
      isProductionEnv && [
        require('babel-plugin-transform-react-remove-prop-types').default,
        {
          removeImport: true
        }
      ]
    ].filter(Boolean)
  }
}

@dapi
Copy link

dapi commented Jun 24, 2019

tired to fix and just added to package.json section:

  "scripts": {
    "postinstall": "cp node_modules/@rails/actioncable/app/assets/javascripts/action_cable.js app/javascript"
  },

@6temes
Copy link
Contributor

6temes commented Aug 22, 2019

I am having the same issue after updating to rails 6 and bumping the npm package to "@rails/actioncable": "^6.0.0"

jellybob added a commit to jellybob/stage-screen that referenced this issue Aug 23, 2019
@xaviablaza
Copy link

I'm facing this same issue when deploying in production, and am looking for a fix.

@jhlms
Copy link

jhlms commented Sep 12, 2019

What solved it for me is removing this from the bottom of babel.config.js

isProductionEnv && [ require('babel-plugin-transform-react-remove-prop-types').default, { removeImport: true } ]

@jessehanley
Copy link

@MelfQuin that fixed it for me, thanks mate.

ughstudios added a commit to ughstudios/FindAFriend that referenced this issue Sep 21, 2019
ughstudios added a commit to ughstudios/FindAFriend that referenced this issue Sep 21, 2019
@ughstudios
Copy link

@jessehanley @MelfQuin this also worked for me, Thanks guys.

@lf2foce
Copy link

lf2foce commented Nov 3, 2019

@MelfQuin also worked for me too, thank you guys, dont know why not so many people mention about this error.

@tmikoss
Copy link
Contributor

tmikoss commented Nov 14, 2019

I'm also having this same issue in test environment. We are precompiling in CI before running tests, and while that completes successfully, any test hitting JS assets dies with the same "r is not a function" error. Updating babel.config.js as per previous comments had no effect.

Edit: Excluding actioncable from transpilation, as per https://github.com/rails/webpacker/blob/master/docs/v4-upgrade.md#excluding-node_modules-from-being-transpiled-by-babel-loader, solved my issue.

@krtschmr
Copy link

@xaviablaza https://github.com/rails/webpacker/blob/master/docs/v4-upgrade.md#excluding-node_modules-from-being-transpiled-by-babel-loader this worked for me.

just add environment.loaders.delete('nodeModules') at the bottom of webpack/environment.js

@ziaulrehman40
Copy link

@MelfQuin Worked for me as well, though I am not sure if it has any side effects? This babel plugin was there for a reason i suppose.

So we still await some official solution, if we can pin point issue i would be happy to put up a PR, or help in that regard, to fix this issue.

@lhjd
Copy link

lhjd commented Feb 26, 2020

thanks @tmikoss @krtschmr
both methods worked for me.
https://github.com/rails/webpacker/blob/master/docs/v4-upgrade.md#excluding-node_modules-from-being-transpiled-by-babel-loader

decided to use the 2nd method, which is to exclude just the actioncable library, so i added this to config/webpack/environment.js:

const nodeModulesLoader = environment.loaders.get('nodeModules')
if (!Array.isArray(nodeModulesLoader.exclude)) {
  nodeModulesLoader.exclude = (nodeModulesLoader.exclude == null)
    ? []
    : [nodeModulesLoader.exclude]
}
nodeModulesLoader.exclude.push(/actioncable/)

@jakeNiemiec
Copy link
Member

jakeNiemiec commented Feb 26, 2020

This babel plugin was there for a reason i suppose.

There are 2 babel-loader`s in webpacker (source files and node_modules/* files).

Please see rails/webpacker#2131 (comment) for more discussion.

lxkuz added a commit to lxkuz/blogpost that referenced this issue Mar 13, 2020
@jonathan-s
Copy link

I was using rollup together with the javascript library "@rails/actioncable": "^6.0.2", and it failed with 'createConsumer' is not exported by node_modules/@rails/actioncable/app/assets/javascripts/action_cable.js

What made the error go away was to use commonjs with named exports.

plugins: [
    commonjs({
        namedExports: {
            "node_modules/@rails/actioncable/app/assets/javascripts/action_cable.js": ["createConsumer"]
        }
    }),
]

@morgoth
Copy link
Member

morgoth commented Apr 28, 2020

@jakeNiemiec can you think about some permanent solution to this issue, so it won't happen in newly generated app?

@jakeNiemiec
Copy link
Member

@morgoth Yes, see rails/webpacker#2131 (comment)

@terracatta
Copy link
Contributor Author

terracatta commented May 8, 2020

FYI I've submitted this issue as a post in the Rails Forum's May of WTFs because I think it stands to reason this bug will bite people using ActionCable for the first time and leave a pretty bad taste in their mouth.

Any feedback about how much of your time was lost to this bug or your general thoughts are welcome!

https://discuss.rubyonrails.org/t/actioncable-broken-by-default-in-rails-6-in-prod/74457

@dhh
Copy link
Member

dhh commented May 8, 2020

cc @javan

jakeNiemiec added a commit to jakeNiemiec/webpacker that referenced this issue Jun 8, 2020
gauravtiwari pushed a commit to rails/webpacker that referenced this issue Jun 17, 2020
@rails-bot
Copy link

rails-bot bot commented Aug 6, 2020

This issue has been automatically marked as stale because it has not been commented on for at least three months.
The resources of the Rails team are limited, and so we are asking for your help.
If you can still reproduce this error on the 6-0-stable branch or on master, please reply with all of the information you have about it in order to keep the issue open.
Thank you for all your contributions.

@rails-bot rails-bot bot added the stale label Aug 6, 2020
@rails-bot rails-bot bot closed this as completed Aug 13, 2020
@jackrr
Copy link

jackrr commented Dec 11, 2020

I ran into a similar looking issue that I suspect shares the same underlying cause. In my case, I get a runtime error in my development build: TypeError: this.createWebSocketURL is not a function at node_modules/actioncable/lib/assets/compiled/action_cable.js:26 (from actioncable@5.2.4-4).

The fixes proposed by others in this issue assume the use of rails webpacker for my builds or access to the build's webpack config. However I'm building my app with create-react-app so none of the above solutions work for me. I found that changing my import syntax from:

import { createConsumer } from "actioncable";
...
createConsumer("my url"); <-- errors

to:

import actioncable from "actioncable";
...
actioncable.createConsumer("my url"); <-- no error

got my app to run without issue.

Hopefully this helps others that run into this. Also if you think there's a more appropriate place for my comment, or maybe it merits its own issue, let me know.

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

Successfully merging a pull request may close this issue.