Unable to load css files for cookieconsent with webpacker - ruby-on-rails

I am trying to use the cookieconsent package with webpacker in ruby on rails 5.1.4.
My package.json is
{
"dependencies": {
"#rails/webpacker": "3.5",
"bootstrap": "^4.1.1",
"cookieconsent": "^3.0.6"
},
"devDependencies": {
"webpack-dev-server": "2.11.2"
I have added a cookieconsent.scss in app/javascript with the following content
#import 'cookieconsent/build/cookieconsent.min.css'
I am running webpack-dev-server which compiles successfully, including processing the cookieconsent.scss file viz
Child extract-text-webpack-plugin node_modules/extract-text-webpack-plugin/dist node_modules/css-loader/index.js??ref--2-2!node_modules/postcss-loader/lib/index.js??ref--2-3!node_modules/sass-loader/lib/loader.js??ref--2-4!app/javascript/cookieconsent.scss:
[0] ./node_modules/css-loader??ref--2-2!./node_modules/postcss-loader/lib??ref--2-3!./node_modules/sass-loader/lib/loader.js??ref--2-4!./app/javascript/cookieconsent.scss 10.7 kB {0} [built]
[1] ./node_modules/css-loader/lib/css-base.js 2.26 kB {0} [built]
In the head of the html page being loaded I have
<%= stylesheet_pack_tag 'cookieconsent' %>
When I load the page, I get the following error message at this stylesheet_pack_tag line
Webpacker::Manifest::MissingEntryError - Webpacker can't find cookieconsent.css in /Users/Chris/Sites/golf_mentor/public/packs/manifest.json. Possible causes:
1. You want to set webpacker.yml value of compile to true for your environment
unless you are using the `webpack -w` or the webpack-dev-server.
2. webpack has not yet re-run to reflect updates.
3. You have misconfigured Webpacker's config/webpacker.yml file.
4. Your webpack configuration is not creating a manifest.
Your manifest contains:
{
"application.css": "/packs/application-4aa426d9718df1187dbf816f0f19f567.css",
"application.css.map": "/packs/application-4aa426d9718df1187dbf816f0f19f567.css.map",
"application.js": "/packs/application-157f642ed5e88a31abbb.js",
"application.js.map": "/packs/application-157f642ed5e88a31abbb.js.map",
"counter.js": "/packs/counter-9d94c8ee2c39e62e654d.js",
"counter.js.map": "/packs/counter-9d94c8ee2c39e62e654d.js.map"
}
:
app/views/pages/temp.html.erb:3:in `block in _app_views_pages_temp_html_erb__4517159242875817520_70136616900600'
app/views/pages/temp.html.erb:1:in `_app_views_pages_temp_html_erb__4517159242875817520_70136616900600'
How do I fix this?

I ended up solving this by installing cookieconsent using sprockets.
However this post, https://rubyyagi.com/how-to-use-bootstrap-and-jquery-in-rails-6-with-webpacker/, although it does not deal specifically with cookieconsent does provide more information on how to install third party css files using webpacker.

Related

Custom CSS not working with CSS Bundling for Rails 7

Playing around with Rails 7 and I don't understand why my custom CSS is not working.
I built new rails app with flag for Bootstrap, which is working fine (CSS and JS, tested with bootstrap modal). These are my default config files:
application.js
// Entry point for the build script in your package.json
import "#hotwired/turbo-rails"
import "./controllers"
import * as bootstrap from "bootstrap"
application.bootstrap.scss
#import 'bootstrap/scss/bootstrap';
package.json
{
"name": "app",
"private": "true",
"dependencies": {
"#hotwired/stimulus": "^3.0.1",
"#hotwired/turbo-rails": "^7.1.0",
"#popperjs/core": "^2.11.2",
"bootstrap": "^5.1.3",
"esbuild": "^0.14.23",
"jquery": "^3.6.0",
"popper.js": "^1.16.1",
"sass": "^1.49.9",
"stimulus": "^3.0.1"
},
"scripts": {
"build": "esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds",
"build:css": "sass ./app/assets/stylesheets/application.bootstrap.scss ./app/assets/builds/application.css --no-source-map --load-path=node_modules"
}
}
And I can built CSS in /builds/application.css
Now I want to add custom CSS. This is my process:
Added new file stylesheets/custom.css, with css:
.my-class {
color: #fff;
background-color: #00eb00;
}
Add import to application.bootstrap.scss
#import "custom";
yarn run build:css
And now I can see .my-class in builds/application.css
But when I try to use id in HTML, no CSS is added. Why? Should I place it somewhere else?
EDIT: I got it running, but only when I run manually rails assets:precompile and then bin/dev.
Why do I need to precompile every time I change something?
In a fresh rails 7 app (with css=bootstrap), here's what I did to get custom css styles:
Uncomment gem 'sass-rails in Gemfile, then bundle install (more info on that here)
Create a new css file in app/assets/stylesheets and name it example.css.scss
Add this line to app/assets/config/manifest.js:
//= link example.css
Wherever you need access to those styles, include this tag
<%= stylesheet_link_tag "example", "data-turbo-track": "reload" %>
Start your server with bin/dev instead of rails server
Everything should work (a nice test is to include this in your example.css.scss file and H1s should turn green)
h1 {
color: green;
}
Resource
Very helpful video here
I just encountered this problem and noticed both JavaScript and CSS are not recompiled after changes.
If you have gem jsbundling-rails included in your gemfile, check out https://github.com/rails/jsbundling-rails for more details and how-tos.
Run yarn run build:css to recompile the CSS assets.
I prefer using ./bin/dev to start my local server and monitor both JavaScript and CSS updates.
It worked for me if I added
//= link custom.css
to app/assets/config/manifest.js
And I didn't add #import "custom"; to application.bootstrap.scss

Q: How to ensure vendor chunk hash doesn't change with webpacker?

I have a Rails 6 project with webpacker 4.2.2 configured to split vendor chunks into individual files:
# config/webpack/environment.js
const { environment } = require('#rails/webpacker')
const webpack = require('webpack')
environment.config.merge({
plugins: [
new webpack.HashedModuleIdsPlugin(),
],
optimization: {
minimize: true,
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
maxInitialRequests: Infinity,
minSize: 0,
cacheGroups: {
// #see https://hackernoon.com/the-100-correct-way-to-split-your-chunks-with-webpack-f8a9df5b7758
vendor: {
test: /[\\/]node_modules[\\/]/,
name(module) {
const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
return `npm.${packageName.replace('#', '')}`;
},
priority: 10,
},
}
}
}
})
module.exports = environment
When we precompile our assets, this produces fingerprinted files for each NPM dependency, which we upload for long-term caching and CDN-based distribution.
However, we're noticing that when we add a new library to the pack, this unexpectedly causes a rehash of many chunk files for dependencies that have not changed at all.
For example, this change in my app/javascript/packs/application.js:
require("#rails/ujs").start()
require("turbolinks").start()
require("#rails/activestorage").start()
require("channels")
import 'msr'
import copy from 'clipboard-copy'
+import axios from 'axios'
will produce the following change in my output chunks (produced from running bin/rails webpacker:compile):
--- a 2020-07-06 18:39:52.202440803 +0000
+++ b 2020-07-06 18:39:52.210440748 +0000
## -1,6 +1,8 ##
-application-1e8721172ae65f57286b.chunk.js
-npm.clipboard-copy-10b42ffbc97b4e927071.chunk.js
-npm.msr-01ea266e2c932167f10b.chunk.js
-npm.rails-a4564cfc542024efeb95.chunk.js
-npm.turbolinks-eeef46ff44962af9ac87.chunk.js
-npm.webpack-7226f5cf46a8c4e61c26.chunk.js
+application-bad0ed20808541f88894.chunk.js
+npm.axios-40b4b54ebace2b9e3907.chunk.js
+npm.clipboard-copy-79d2051f48603e0267e0.chunk.js
+npm.msr-f5a4252b7a7e0a94157f.chunk.js
+npm.process-cfe824ecbab5abe0eecc.chunk.js
+npm.rails-aa1c430d6ceee3ca6bd6.chunk.js
+npm.turbolinks-e28554dbfd4b75aa12e5.chunk.js
+npm.webpack-35f718d9a20b8bca2927.chunk.js
This is a double whammy because of unnecessary cache invalidation and additional CDN transfer costs.
My question is, is there a way to ensure the vendor chunk doesn't get rehashed because of dependency changes?
I don't know if this is a limitation with the way that webpack's SplitChunksPlugin works, but any advice is appreciated.
By the way, I've prepared a minimal Rails project that reproduces the situation I've described above: https://github.com/alextsui05/webpacker-vendor-chunks
A detailed summary is included in the README on the repository, and I invite any answerers to discuss based on that code.
Try setting the option moduleIds: 'hashed'
https://v4.webpack.js.org/configuration/optimization/#optimizationmoduleids

What is the best way to use webpacker in a Rails engine?

I realise there is some debate about using webpacker in Rails engines but I have a simple usecase and currently have a workaround. Would like to know of a better (the best?) solution.
In this rails engine I have webpacker setup in the "spec/dummy" directory and everything works well in dev:
https://github.com/RealEstateWebTools/property_web_scraper/tree/master/spec/dummy/config/webpack
When the engine is used by a rails app however it will not find the compiled webpack files so each time I have a release ready I compile the webpack files and manually copy them to the vendor directory:
https://github.com/RealEstateWebTools/property_web_scraper/tree/master/vendor/assets/javascripts
I then require that file here:
https://github.com/RealEstateWebTools/property_web_scraper/blob/master/app/assets/javascripts/property_web_scraper/spp_vuetify.js
In my layout I use the above file using the good old sprockets "javascript_include_tag": https://github.com/RealEstateWebTools/property_web_scraper/blob/master/app/views/layouts/property_web_scraper/spp_vuetify.html.erb
In the layout there is a check to see if I'm running the "spec/dummy" app in which case I will user webpacker as it would normally be used in dev.
There must be a better way than this.
Webpacker has been retired
https://github.com/rails/webpacker
Going forward, it's better to switch to jsbundling-rails with webpack.
(I would rather suggest esbuild as it's "10×-100× faster")
But let's do it with webpack:
rails new webpack-in-engine --javascript webpack --css tailwind --database postgresql
In app/javascript/application.js I do:
console.log("hello from application.js")
And it works.
Now with an engine:
rails plugin new admin --mountable
Then depends:
Separate JS
Add an entry to your webpack.config.js:
const path = require("path")
const webpack = require("webpack")
module.exports = {
mode: "production",
devtool: "source-map",
entry: {
application: "./app/javascript/application.js",
admin: "./admin/app/javascript/admin.js"
},
output: {
filename: "[name].js",
sourceMapFilename: "[name].js.map",
path: path.resolve(__dirname, "app/assets/builds"),
},
plugins: [
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1
})
]
}
<%= javascript_include_tag "admin", "data-turbo-track": "reload", defer: true %>
Shared JS
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
And in your app/javascript/application.js:
import "./../../admin/app/javascript/admin"
See full repo https://github.com/dorianmariefr/webpack-in-engine
Aside: Also I would rather namespace in the main app than have engines. I think engines are for very specific use cases not namespacing.

Webpacker with Rails compiles scss partials

I have created a sample app at https://github.com/joostvanrijn/webpacker to be complete, but here's my issue:
# app/javascript/packs/stylesheets.scss
#import 'variables';
#import 'foo';
# app/javascript/packs/_variables.scss
$bar: #fff;
# app/javascript/packs/_foo.scss
body {
color: $bar;
}
Now when I run /bin/webpack-dev-server I get
Undefined variable: "$bar".
And more importantly
[84] ./app/javascript/packs/_foo.scss 988 bytes {2} [built] [failed] [1 error]
It seems as if Rails/webpacker compiles all files instead of just stylesheets.scss
I've been able to find the answer eventually.
From the Webpacker readme:
The configuration for what Webpack is supposed to compile by default
rests on the convention that every file in app/javascript/packs/*
(default) or whatever path you set for source_entry_path in the
webpacker.yml configuration is turned into their own output files (or
entry points, as Webpack calls it).
So by moving the sass partials to another folder now only the stylesheets.scss gets compiled.

Proper Semantic-UI / Bower / Rails 4 configuration

I'm struggling to properly install and configure Semantic-UI using bower in my Rails 4 app.
Until now, here's what I've done:
Gemfile:
gem "less-rails"
gem "therubyracer"
.bowerrc file:
{
"directory": "vendor/assets/components"
}
bower.json:
{
"name": "app",
"version": "0.0.0",
"homepage": "myapp.com",
"private": true,
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"vendor/assets/components",
"test",
"tests"
],
"dependencies": {
"semantic-ui": "~1.12.2"
}
}
After bower install, semantic UI gets properly pulled into my /vendor/assets/components folder
Now, I'd like to take advantage of semantic's theming properties, without of course editing what's currently loaded by bower.
I've added the following in semantic.css.less, itself being required in application.css
#import "semantic-ui/src/semantic";
The issue now: semantic lib seems to be properly fetched in the proper folder, as I get the following error:
'site//globals/site.variables' wasn't found
Ok I understand that.
But how do I use custom configuration files with the default assets installed by bower without touching these ?
How can I properly create the required configuration files (theme.config / site.variables / site.overrides), out of my /vendor/assets/components folder, and still properly assigning the SASS variables required for the lib to compile ?
I would take a gander at less-rails-semantic-ui, this is what I ended up going for my new rails project. It properly adds all the override files in vendor/assets!
If you are using less source files without npm (which includes an installer), you will need to manually create theme.config from theme.config.example and site/ from _site/ this is to avoid upstream changes affecting your local ui.
https://github.com/Semantic-Org/Semantic-UI/tree/master/src#config-files
PS: from the owner answer, source:
https://github.com/Semantic-Org/Semantic-UI/issues/2239

Resources