Shorthand verbs don't work with webpack 5/jsbundling
rcackerman opened this issue · 2 comments
I'm upgrade a Rails 6 application from using webpacker to jsbundling with webpack 5. I'm running into a very strange error where get, patch, post, etc result in a TypeError, while the FetchRequest class does not. The exact error is that <webpack module>.post is not a constructor.
I managed to reproduce the error in a simple test application using Rails 6 and then following the migration instructions from jsbundling. There's a simple form:
<%= form_for @item, method: :patch, html: {data: {controller: "ajax-button"}} do |form| %>
<div class="form-check form-switch form-control-lg ms-3">
<%= form.check_box :active, class: "form-check-input", role: "switch", data: {action: "change->ajax-button#submit"} %>
</div> Active
<% end %>
This doesn't work:
import { Controller } from "@hotwired/stimulus"
import { get, post, put, patch, destroy } from '@rails/request.js'
// Connects to data-controller="ajax-button"
export default class extends Controller {
async submit(event) {
event.preventDefault()
event.stopPropagation()
let payload = new FormData(this.element)
const request = new post(this.element.action, { body: payload, responseKind: "json" })
const response = await request.perform();
if(response.ok) {
return response
}
}
}
but this does:
import { Controller } from "@hotwired/stimulus"
import { FetchRequest } from "@rails/request.js"
// Connects to data-controller="ajax-button"
export default class extends Controller {
async submit(event) {
event.preventDefault()
event.stopPropagation()
let payload = new FormData(this.element)
const request = new FetchRequest('patch', this.element.action, { body: payload, responseKind: "json" })
const response = await request.perform();
if(response.ok) {
return response
}
}
}
My package.json looks like this:
{
"name": "test-jsbundling",
"private": true,
"dependencies": {
"@hotwired/stimulus": "^3.1.0",
"@hotwired/turbo-rails": "^7.1.3",
"@rails/actioncable": "^6.0.0",
"@rails/activestorage": "^6.0.0",
"@rails/request.js": "^0.0.6",
"@rails/ujs": "^6.0.0",
"@rails/webpacker": "5.4.3",
"turbolinks": "^5.2.0",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0"
},
"version": "0.1.0",
"devDependencies": {
"webpack-dev-server": "^3"
},
"scripts": {
"build": "webpack --config webpack.config.js"
}
}
And my webpack config looks like:
const path = require("path")
const webpack = require("webpack")
module.exports = {
mode: "development",
optimization: {
moduleIds: 'hashed',
},
devtool: "source-map",
entry: {
application: "./app/javascript/application.js"
},
output: {
filename: "[name].js",
sourceMapFilename: "[file].map",
path: path.resolve(__dirname, "app/assets/builds"),
},
plugins: [
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1
})
]
}
@rcackerman Take another close look at Shorthand methods. Now compare that to your “This doesn’t work” code snippet, specifically the following bit:
const request = new post(this.element.action, { body: payload, responseKind: "json" })
const response = await request.perform();The correct invocation looks as follows:
const response = await post(this.element.action, { body: payload, responseKind: "json" });In the short version form you skip constructing a Request object, so you don’t need new …/request.perform() as the short versions do that for you.
@rcackerman Did you solve your problem based on @ur5us answer? I'll close the issue, but if you still are facing the problem we can reopen it, thank you!