I am using the Shakapacker https://github.com/reactjs/react-rails and I have come across this error despite following all the steps in the Get started with shakapacker section I am not sure why this is happening any help is appreciated
config/importmap.rb
# Pin npm packages by running ./bin/importmap
pin "application", preload: true
pin "#hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "#hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "#hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers"
app/javascript/application.js
import "#hotwired/turbo-rails"
import "controllers"
picture of error
You're mixing concepts. Shakapacker and Import Maps are 2 different ways of building your front-end.
Shakapacker: it's based on webpack, so you are running a Node.js bundler with a compilation/transpilation step. Dependencies are defined in the package.json.
Import Maps: based on ESM so it runs directly in the browser with no bundling step. It's the new Rails 7+ default.
So first of all, you'll need to choose one of the options to build your front-end code (you can probably mix both, but it will be messy if you don't have a clear understanding of how they work). If you just need "Hotwire" and don't want any kind of complex stuff (three-shaking, hot-reloading, ...), the importmap-rails solution is simpler and the recommended way to go.
There is also a 3rd option (my 🙋♂️ preferred one): jsbundling-rails. It's a small layer/glue-code to use a js bundler (esbuild, webpack or rollup) and rely on the Rails assets pipeline (Sprockets) to plug-in into the app. I you want to see an example of this, some time ago I published a ready-to-go template: https://github.com/ralixjs/rails-ralix-tailwind.
Related
I am using the latest Rails 7 and when ever i import a custom js file in to my project the action text disappears. what am i doing wrong?
Go to config/importmap.rb and add the following:
pin_all_from "app/javascript/custom", under: "custom"
Go to app/javascript/application.js file and add the following:
import "custom/main"
In app/javascript/custom directory add your custom js file main.js. Run In your terminal:
rails assets:precompile
Start your rails server.
I used the above way to add a js file to my project.
There is no changed I made to my code but as soon as I perform the above task to add a custom javascript file the actiontext/trix in my form disappear, It stops working.
I figured it out there was a problem with the custom JS file. Everything works after fixing the JavaScript file i was trying to import.
How can I output the javascript file from Parcel, include this javascript file in Rails app/assets/javascripts/application.js, and ideally get it working with hot module reloading?
Alternatively, is this a bad approach, and do you recommend something more streamlined, that lets me use mostly traditional .html.erb Rails templates but sprinkle in ReactJS UI components here and there?
I was able to do this perfectly in Parcel 1 but I am finding that the setup is quite different in Parcel 2.
I am using the traditional Rails 5 application.html.erb templating.
My attempt so far with Parcel 2 has been to use the library tutorial in the Parcel documentation. I can mount the simplest React component to my Rails app but then if I try to import anything I get errors like require is not defined, and HMR is not working.
I'm not sure how much context to provide for this question. But if it helps, my previous setup with Parcel 1 was to have a separate npm app at the root folder (next to the Rails /app folder) which output a dist/index.js file using the npm script parcel start app/index.jsx --out-dir dist --public-url /assets/dist. This was added to the Rails assets via config.assets.paths << Rails.root.join('frontend') and included in app/assets/javascripts/application.js .
Now for Parcel 2 I removed the include in application.js and added <script type="module" src="/assets/dist/index.js"></script> in application.html.erb
There are two errors you're seeing that I might be able to help with:
Runtime errors like require is not defined. This would be expected if you set up parcel to output your javascript as a library target (as you indicated). Libraries are typically npm packages that are consumed by other projects. In this context, parcel will output a commonjs bundle (including require-based imports) that's intended to be processed by another bunder (maybe parcel again, or webpack) before it's ready to be executed in a browser. You probably want to build your javascript with a browser target instead, so that all dependencies are included without require statements to other packages.
Assuming your package.json for the parcel project currently looks similar to the the library tutorial, the way you'd do that would be to remove the "main": "path-to/my-root-javascript.js" field, and change the build script to parcel build path-to/my-root-javascript.js. There's also a bunch of ways to customize this - see the targets documentation.
HMR not working. If parcel is only in charge of bundling your javascript (and rails is building your html from templates), then the "normal" way that parcel does HMR won't work. This "normal" way would involve parcel injecting an HMR script in the html file that's its responsible for building and serving. But if Rails is taking care of the HTML, parcel can't do this automatically. Perhaps there is a way to configure rails to watch when parcel rebuilds the js bundle, and refresh the page?
This might be a bit of an onion-peeling exercise - it's hard to say if the above suggestions will solve it all end-to-end. If you can post a minimal reproduction of the issue (maybe a simplified version of your ruby + parcel project?) on github that shows the problem, I'm happy to troubleshoot it further.
In migrating an app to Rails 5.1 for the first time, I'm experimenting with yarn instead of bower to manage frontend dependencies.
Everything is working great, and I'm able to include js and css files via the relevant application.js/css manifest files.
But, if these files depend on other resources (e.g., a directory of images, fonts, etc.), then Rails knows nothing about them.
Given a yarn package that includes:
/css
|-styles.css
/images
|-background.jpg
where
#styles.css
.background {
background-image: url(../images/background.jpg);
}
Logs are (obviously) showing
No route matches [GET] "/images/background.jpg"
How do I ensure that Rails is aware of these images in Yarn packages and properly compiles them?
Is this possible? Or am I overlooking something obvious?
I had the same problem. Following are some good references
https://edgeguides.rubyonrails.org/webpacker.html#using-webpacker-for-css
https://github.com/rails/webpacker/issues/349
Basically you need to do following things
Require the css file like a js file but with css extension included in /app/javascript/packs/application.js (Yes, require css in javascript)
Add <%= stylesheet_pack_tag "application" %> in layout file if already not there
If you don't already have it, create file (even if empty) /app/javascript/packs/application.scss
So, using Rails 5.2beta (gem install rails --pre), if you create a new app via rails new myapp --webpack=react... how would I go about incorporating Lodash into my flow from there?
I've mucked around with babel-plugin-lodash and lodash-webpack-plugin to no avail.
The compile doesn't fail if I do something like import { _pick, _map } from 'lodash/array'; ... but those variables are undefined when trying to use them.
I'm a bit lost as I'm both new to webpacker & webpack, and a lot of existing examples seem to target an older version of webpack?
Anyway, thank you for any help...
UPDATE:
Ok, looks like you can just do import map from "lodash/map"
So where are you trying to use lodash from? By this I mean are you sure the files are getting compiled / processed by Webpacker, or are they getting processed via the Asset Pipeline?
On my webpacker project I realized that there's a problem: that yes, regular old Javascript compiled with the Asset Pipeline won't know about the NPM Modules included via Webpack. (or at least the require statements wouldn't work).
Because of this I made a hard rule: all javascript goes where webpacker expect it (app/javascript) and no Javascript goes in app/assets. We only use the asset pipeline for CSS (which works great in our case, as I still don't think React - our frontend framework of choice - has a good story around site wide CSS).
I'm trying to fully replace the rails asset pipeline with a webpack based pipeline. I've got the dev setup with the webpack-dev-server and hot reloading etc all working beautifully. Now what I'm trying to achieve is a compilation step for production that would mimic how rails compiles assets (digesting / generating a compatible manifest.json file) such that I can still use helpers like javascript_include_tag etc. This is where I'm stuck.
I've read lots of tutorials on using webpack with rails, but they all end up writing their own view helpers to load the assets. I'm trying to avoid this because I don't want extra overhead or for devs to need to understand a different pipeline. I also want config like asset_host= to work out of the box for using a CDN etc.
Ultimately, what I want is something similar to gulp-rev-rails-manifest that generates a rails-asset-pipeline compatible manifest file on compilation, but I haven't found a plugin (yet) that exists for Webpack. So...
is it possible to run a webpack build through a gulp stream using webpack only (ie not using gulp-webpack) so I can use the above gulp plugin. The reason I don't want to use gulp-webpack is that it takes over your entries / output etc and I find that whole setup confusing since this all already exists in webpack.config
Or
Does anyone have any decent resources on writing plugins for Webpack. It seems a bit of a black box to me and the official site has a menu section for "How to write a plugin" but it's not actually a link to anything.
Or
Is there actually a plugin that will do exactly this and I don't know how to search properly on the interwebs.
Any help is greatly appreciated :)
Running webpack in a gulp task is very simple:
var webpack = require('webpack');
var webpackConfig = require('./webpack.config');
gulp.task('webpack', function(done) {
webpack(webpackConfig, function(err, stats) {
done(err);
});
});
Note that the stats object provided to the webpack callback contains information about all assets emitted by webpack, so you could potentially use it to generate your own manifest.
Here are a few webpack plugins you might find useful:
https://github.com/sporto/assets-webpack-plugin
https://github.com/danethurber/webpack-manifest-plugin
https://github.com/diurnalist/chunk-manifest-webpack-plugin
While there is no official tutorial on how to create a plugin, there's still a Plugin API doc that describes the different interfaces your plugins can hook into. The webpack source and github contain a lot of webpack plugin examples.
Here's a very simple plugin that just logs assets:
module.exports = function() {
this.plugin('done', function(stats) {
console.log(stats.toJson().assets);
});
};