rails / cssbundling-rails

Bundle and process CSS in Rails with Tailwind, PostCSS, and Sass via Node.js.
MIT License
579 stars 83 forks source link

Importing 3rd party css files from the node_modules folder #92

Closed GregSmith92 closed 1 year ago

GregSmith92 commented 2 years ago

I am moving from webpack to esbuild with jsbundling-rails & cssbundling-rails. In a vendor directory I have a file which imports css files required by some JS packages like so:

@import "drift-zoom/dist/drift-basic.min.css";
@import "dropzone/dist/min/dropzone.min.css";
@import "select2/dist/css/select2.css";
@import "slick-slider/slick/slick.scss";
@import "slick-slider/slick/slick-theme.scss";

This file is then imported in my application.sass.scss.

In the logs I get a series of errors for each file like: ActionController::RoutingError (No route matches [GET] "/assets/select2/dist/css/select2.css"):

It seems the problem may be that it is looking in app/assets for these files, when they are at the root under node_modules instead.

In config/initializers/assets I have Rails.application.config.assets.paths << Rails.root.join('node_modules')

A similar issue was posted to the jsbundling-rails page (which I think should of been here), where OP added additional paths to config.assets, like so: Rails.application.config.assets.paths << Rails.root.join("node_modules/photoswipe/src/css/default-skin"), but this has not worked for me.

The scripts I have in my package.json are:

"scripts": {
    "build": "esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds",
    "build:css": "sass ./app/assets/stylesheets/application.sass.scss ./app/assets/builds/application.css --no-source-map --load-path=node_modules"

EDITS: I have noticed that only the css files fail to be found, the scss files work fine. Maybe coincidence, I am usnure

GregSmith92 commented 2 years ago

Turns out my sass implementation couldn't handle the 3rd party css files. I managed to find scss versions for most of these, so it now works.

Not sure what the reccomended route is if you need to import a 3rd party css file though

Petercopter commented 2 years ago

@GregSmith92 What version of Yarn are you using? I'm trying to move from Yarn 1 to Yarn 3. Everything is fine except when I push to Github. I'm using Github Actions, and I'm getting

Run bundle exec rails spec
➤ YN0000: ┌ Resolution step
Resolution step
➤ YN0000: └ Completed
➤ YN0000: ┌ Fetch step
Fetch step
➤ YN0000: └ Completed in 3s 690ms
➤ YN0000: ┌ Link step
Link step
➤ YN0000: └ Completed in 2s 59ms
➤ YN0000: Done with warnings in 5s 853ms
Error: Can't find stylesheet to import.
  ╷
3 │ @import 'bootstrap/scss/bootstrap.scss';
  │         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  ╵
  app/assets/stylesheets/application.scss 3:9  root stylesheet
rails aborted!
cssbundling-rails: Command css:build failed, ensure yarn is installed and `yarn build:css` runs without errors

This only happens in the CI, despite the fact that it's using the same setup locally for assets. I've got the node modules in my assets.rb as well.

Edit: It looks like the 'plug and play' setup for Yarn is the culprit. Adding

nodeLinker: node-modules

to the .yarnrc.yml "fixes" the problem. Still trying to understand why I'm only seeing this in the CI....

Gibson2 commented 2 years ago

I have the same problem, but with the solution that @Petercopter proposed, adding to the .yarnrc.yml file that is in the root (/home/user) helped me to solve the problem, however, I do not understand why the file has not configured that line of code.

nodeLinker: node-modules

So, as I see my problem, when executing the following $> rails new app_name -j esbuild -c bootstrap -d postgresql command generates the entire project structure, however, it does not generate the node_modules folder, which generates the > Error: Can't find stylesheet to import. │@import 'bootstrap/scss/bootstrap'; shown in the image.

image

OS: Ubuntu-20.04 (WSL) ruby: 3.1.2p20 rails: 7.0.3 node: v16.14.0 npm: 8.3.1 yarn: 3.2.0

mopx commented 2 years ago

@GregSmith92 removing the extension '.css' from the import path does the trick for me.

Example: @import "select2/dist/css/select2";

GregSmith92 commented 1 year ago

@mopx Nice tip! To my surprise this does work!!

dhh commented 1 year ago

Feel free to add a doc patch for this.

yudukikun5120 commented 1 year ago

I want to import a CSS module (in this case @algolia/autocomplete-theme-classic) in the style tag within the shadow root. The stimulus controller looks like this:

// import '@algolia/autocomplete-theme-classic'

export default class extends Controller {
  connect() {
    const shadowRoot = this.element.attachShadow({ mode: 'open' })

    const style = document.createElement('style');
    const autocompleteCss = 'https://cdn.jsdelivr.net/npm/@algolia/autocomplete-theme-classic@1.11.0/dist/theme.min.css';
    style.textContent = `@import url(${autocompleteCss});`;
    shadowRoot.appendChild(style);
  }
}

I want to give a CSS file in node_modules (@algolia/autocomplete-theme-classic/dist/theme.css) as an argument to @import url() instead of from jsdelivr. What do you think I should do?