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

[v11] missing style package export for webpack based asset pipelines #1184

Closed
tagliala opened this issue Aug 30, 2024 · 7 comments · Fixed by #1193
Closed

[v11] missing style package export for webpack based asset pipelines #1184

tagliala opened this issue Aug 30, 2024 · 7 comments · Fixed by #1193
Labels

Comments

@tagliala
Copy link
Contributor

tagliala commented Aug 30, 2024

Describe the bug

Hello, I'm trying to upgrade a working app using shakapacker (a pre-processor based on webpack) to Choices v11 but I'm getting an error related to scss import

When updating from Choices.js 10 to Choices.js 11, shakapacker is not able
to resolve

  • @import "choices.js/src/styles/choices"; in Scss
  • import "choices.js/public/assets/styles/choices.css"; in JS

This is due to the new exports entry in package.json, which require
specific entries for webpack, such as style

To Reproduce

Tools and versions required to replicate

  • npm 10.8.0
  • Shakapacker 7/8
  • Node 20.15.0
  • Ruby 3.3.4 (should not be relevant)
  • Rails 7.2.1 (anything >= 6.1.0 should not be relevant)

Initial app

rails _7.2.1_ new test-choices-package-exports --skip-active-record --skip-javascript --skip-git --skip-test
cd test-choices-package-exports
echo "{ \"private\": true, \"packageManager\": \"npm@10.8.2\" }" > package.json
echo "gem 'shakapacker', '8.0.2'" >> Gemfile
bundle
rails shakapacker:install
npm add css-loader style-loader mini-css-extract-plugin css-minimizer-webpack-plugin
npm add choices.js@10.2.0
echo "module.exports = { plugins: [require('postcss-import')] }" > postcss.config.js
git add .
git commit -am "First commit"
git branch tests/scss main
git branch tests/css main

CSS import from JavaScript

git checkout tests/css
echo "import \"choices.js/public/assets/styles/choices.css\";" >> app/javascript/packs/application.js
git commit -am "CSS test"
bin/shakapacker # WORKS, CSS OUTPUT PRESENT
npm add choices.js@^11.0.0
bin/shakapacker # DOES NOT WORK

Error:

ERROR in ./app/javascript/packs/application.js 16:0-53
Module not found: Error: Package path ./public/assets/styles/choices.css is not exported from package ./node_modules/choices.js (see exports field in ./node_modules/choices.js/package.json)

Sass

git checkout tests/scss
npm add sass-loader sass
echo "@import \"choices.js/src/styles/choices.scss\";" >> app/javascript/packs/application.scss
git add .
git commit -am "Scss test"
bin/shakapacker # WORKS, CSS OUTPUT PRESENT
npm add choices.js@^11.0.0
bin/shakapacker # DOES NOT WORK

Error:

Error: Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
Can't find stylesheet to import.
  ╷
1 │ @import "choices.js/src/styles/choices.scss";
  │         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  ╵
  app/javascript/packs/application.scss 1:9  root stylesheet

Suggested solution

https://github.com/ifad/Choices/tree/bugfix/style-export

  1. npm add choices.js@ifad/choices#bugfix/style-export
  2. Retry bin/shakapacker

Details are in the commit message

Ref: https://webpack.js.org/guides/package-exports/#reference-syntax

@tagliala tagliala added the bug label Aug 30, 2024
@tagliala tagliala changed the title Upgrading to v11: missing styles package export Upgrading to v11: missing style package export Aug 30, 2024
@tagliala tagliala changed the title Upgrading to v11: missing style package export [v11]: missing style package export for webpack based asset pipelines Aug 30, 2024
@tagliala tagliala changed the title [v11]: missing style package export for webpack based asset pipelines [v11] missing style package export for webpack based asset pipelines Aug 30, 2024
@Xon Xon linked a pull request Aug 31, 2024 that will close this issue
@Xon
Copy link
Collaborator

Xon commented Aug 31, 2024

@tagliala Can you try the webpack-css branch from this #1188 PR?

It appears to be the "sideEffects": false being an overly big hammer for webpack ref

tagliala added a commit to ifad/Choices that referenced this issue Aug 31, 2024
Mimic FontAwesome's package.json

Close Choices-js#1184
tagliala added a commit to ifad/Choices that referenced this issue Aug 31, 2024
Mimic FontAwesome's package.json

Close Choices-js#1184
tagliala added a commit to ifad/Choices that referenced this issue Aug 31, 2024
Mimic FontAwesome's `package.json`.

- Add `style` package export
- Add `styles.scss` and `styles` exports
- Add `styles.scss` to "side effects" to prevent issues with tree-shaking

With this commit, it is possible to import the style with the following
approaches:

```scss
@import "choices.js";
@import "choices.js/styles";
@import "choices.js/styles.scss";
```

Refs:
- https://webpack.js.org/guides/package-exports/
- FortAwesome/Font-Awesome#18654

Close Choices-js#1184
@tagliala
Copy link
Contributor Author

tagliala commented Aug 31, 2024

Hello, unfortunately this does not work with my specific use case, but I can also see that fontawesome's package.json contains sideEffects entries for .css and .scss.

I've tried

  1. @import "choices.js/src/styles/choices";
  2. @import "choices.js/src/styles/choices.scss";
  3. @import "choices.js";

And the error is always the same

Error: Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
Can't find stylesheet to import.
   ╷
30 │ @import "choices.js/src/styles/choices.scss";
   │         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   ╵

Back in 2022, when Font Awesome 6 was released, we had to deal with a lot of use cases and asset pipelines. I can still provide a script to create a reproducible test case, but that would be specific to Rails, Ruby, webpack, shakapacker. Let me know if it is the case

However, according to our finding back at the times, the following commit should contain all the necessary parts to make webpack work and prevent tree-shaking issues:

ifad@6a532c0

Please also check the side effects

@Xon
Copy link
Collaborator

Xon commented Aug 31, 2024

Can you try using the following syntax against the proposed PR?

@import '~choices.js/src/styles/choices.scss'

The ~ is a bit of webpack syntax which I believe will made it pull the stylesheet from the node_modules path. You'll need sass-loader/sass configured in webpack.

@tagliala
Copy link
Contributor Author

tagliala commented Aug 31, 2024

Hi,

The ~ is a bit of webpack syntax which I believe will made it pull the stylesheet from the node_modules path. You'll need sass-loader/sass configured in webpack.

I do have those, but using ~ was an old deprecated way of referencing modules used until 2022

Ref: https://webpack.js.org/loaders/sass-loader/#resolving-import-at-rules

Using ~ is deprecated and should be removed from your code, but we still support it for historical reasons. Why can you remove it? The loader will first try to resolve @import as a relative path. If it cannot be resolved, then the loader will try to resolve @import inside node_modules.

Ref: diowa/ruby3-rails6-bootstrap-heroku@370f749

I've get rid of all ~s in my projects a couple of years ago.

Unfortunately we had a lot of struggles with exports entry and webpack. And I understand the resistance to including changes in package.json

Ref: fnando/i18n#91 (comment)


Said so, I will provide you the script that I've used in Font Awesome when we had to deal with this package.json entry and webpack(er) based asset pipelines. Please allow me some time (I will create a new comment)


EDIT: sorry, I've seen the .css files. I'm going to improve the issue description and the fix

tagliala added a commit to ifad/Choices that referenced this issue Aug 31, 2024
Mimic FontAwesome's `package.json`.

- Add `style` package export for webpack
- Add `sass` package export for webpack
- Add `styles.css` and `styles` exports for main CSS file
- Add `*.scss` and `*.css` to "side effects" to prevent issues with
  tree-shaking

With this commit, it is possible to import the style with the following
approaches:

```css
@import "choices.js";
@import "choices.js/styles";
@import "choices.js/styles.css";
```

```scss
@import "choices.js";
```

Refs:
- https://webpack.js.org/guides/package-exports/
- FortAwesome/Font-Awesome#18654

Close Choices-js#1184
@Xon
Copy link
Collaborator

Xon commented Aug 31, 2024

@tagliala Can you create a PR for your requested changes?

@tagliala
Copy link
Contributor Author

@Xon Yes I can, I'm now investigating also css support, dedicated sass support, and it requires a little bit of time. I will use this issue to post updates and eventually open a PR

@tagliala
Copy link
Contributor Author

tagliala commented Aug 31, 2024

WORK IN PROGRESS

Tools and versions required to replicate

  • npm 10.8.0
  • Shakapacker 7/8
  • Node 20.15.0
  • Ruby 3.3.4 (should not be relevant)
  • Rails 7.2.1 (anything >= 6.1.0 should not be relevant)

Actual behavior

When updating from Choices.js 10 to Choices.js 11, shakapacker is not able
to resolve

  • @import "choices.js/src/styles/choices"; in Scss
  • import "choices.js/public/assets/styles/choices.css"; in JS

This is due to the new exports entry in package.json, which require
specific entries for webpack, such as style

How to reproduce

Initial app

rails _7.2.1_ new test-choices-package-exports --skip-active-record --skip-javascript --skip-git --skip-test
cd test-choices-package-exports
echo "{ \"private\": true, \"packageManager\": \"npm@10.8.2\" }" > package.json
echo "gem 'shakapacker', '8.0.2'" >> Gemfile
bundle
rails shakapacker:install
npm add css-loader style-loader mini-css-extract-plugin css-minimizer-webpack-plugin
npm add choices.js@10.2.0
echo "module.exports = { plugins: [require('postcss-import')] }" > postcss.config.js
git add .
git commit -am "First commit"
git branch tests/scss main
git branch tests/css main

CSS import from javascript

git checkout tests/css
echo "import \"choices.js/public/assets/styles/choices.css\";" >> app/javascript/packs/application.js
git commit -am "CSS test"
bin/shakapacker # WORKS, CSS OUTPUT PRESENT
npm add choices.js@^11.0.0
bin/shakapacker # DOES NOT WORK

Error:

ERROR in ./app/javascript/packs/application.js 16:0-53
Module not found: Error: Package path ./public/assets/styles/choices.css is not exported from package ./node_modules/choices.js (see exports field in ./node_modules/choices.js/package.json)

Sass

git checkout tests/scss
npm add sass-loader sass
echo "@import \"choices.js/src/styles/choices.scss\";" >> app/javascript/packs/application.scss
git add .
git commit -am "Scss test"
bin/shakapacker # WORKS, CSS OUTPUT PRESENT
npm add choices.js@^11.0.0
bin/shakapacker # DOES NOT WORK

Error:

Error: Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
Can't find stylesheet to import.
  ╷
1 │ @import "choices.js/src/styles/choices.scss";
  │         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  ╵
  app/javascript/packs/application.scss 1:9  root stylesheet

Cause

The cause is the new exports field in package.json. Apparently it is tricking
webpack and it is not able to solve choices.js's stylesheet

Suggested solution

https://github.com/ifad/Choices/tree/bugfix/style-export

  1. npm add choices.js@ifad/choices#bugfix/style-export
  2. For CSS in js: change import to import "choices.js"; or import "choices.js/styles";
  3. For Scss: change @import to @import "choices.js/scss/choices";
  4. Retry bin/shakapacker

Details are in the commit message

Ref: https://webpack.js.org/guides/package-exports/#reference-syntax

tagliala added a commit to ifad/Choices that referenced this issue Aug 31, 2024
Mimic FontAwesome's `package.json`.

- Add `style` package export for webpack
- Add `sass` package export for webpack
- Add `styles.css` and `styles` exports for main CSS file
- Add `*.scss` and `*.css` to "side effects" to prevent issues with
  tree-shaking

With this commit, it is possible to import the style with the following
approaches:

```css
@import "choices.js";
@import "choices.js/styles";
@import "choices.js/styles.css";
```

```scss
@import "choices.js";
```

Refs:
- https://webpack.js.org/guides/package-exports/
- FortAwesome/Font-Awesome#18654

Close Choices-js#1184
tagliala added a commit to ifad/Choices that referenced this issue Aug 31, 2024
Mimic FontAwesome's `package.json` to improve compatibility with webpack

- Add `style` package export to allow main CSS import from JavaScript
- Add `sass` package export to allow
- Add `styles.css` and `styles` exports for main CSS file
- Add `*.scss` and `*.css` to "side effects" to prevent issues with
  tree-shaking

With this commit, it is possible to import the style with the following
approaches:

```js
import "choices.js";
import "choices.js/styles";
import "choices.js/styles.css";
```

```scss
@import "choices.js";
```

Refs:
- https://webpack.js.org/guides/package-exports/
- FortAwesome/Font-Awesome#18654

Close Choices-js#1184
tagliala added a commit to ifad/Choices that referenced this issue Aug 31, 2024
Add some entries to `package.json` to improve compatibility with webpack

- Add `style` package export to allow main CSS import from JavaScript
- Add `sass` package export to allow
- Add `styles.css` and `styles` exports for main CSS file
- Add `*.scss` and `*.css` to "side effects" to prevent issues with
  tree-shaking

With this commit, it is possible to import the style with the following
approaches:

```js
import "choices.js";
import "choices.js/styles";
```

```scss
@import "choices.js/scss/styles";
```

I was expecting that `@import "choices.js";` in scss would have imported
the Scss file, but it is not the case. It is taking the CSS.

Refs:
- https://webpack.js.org/guides/package-exports/

Close Choices-js#1184
tagliala added a commit to ifad/Choices that referenced this issue Aug 31, 2024
Add some entries to `package.json` to improve compatibility with webpack

- Add default `style` and `sass` exports as per webpack requirements
- Add `styles/*` exports for CSS files
- Add `scss/styles/*` exports for Scss files
- Add `*.scss` and `*.css` to "side effects" to prevent issues with
  tree-shaking

With this commit, it is possible to import the style with the following
approaches:

```js
import "choices.js/styles/choices.css"; // CSS
import "choices.js/scss/styles/choices.scss"; // Scss
```

```scss
@import "choices.js/scss/styles/choices";
```

Refs:
- https://webpack.js.org/guides/package-exports/

Close Choices-js#1184
tagliala added a commit to ifad/Choices that referenced this issue Sep 1, 2024
Add some entries to `package.json` to improve compatibility with webpack

- Add default `style` and `sass` exports as per webpack requirements
- Add `public/assets/styles/*` exports for CSS files
- Add `src/styles/*` exports for Scss files. Extension can be omitted
  to prevent linting issues with `stylelint`
- Add `*.scss` and `*.css` to "side effects" to prevent issues with
  tree-shaking

With this commit, it is possible to import styles with the same syntax
of v10 to prevent a breaking change in webpack based applications

Refs:
- https://webpack.js.org/guides/package-exports/
- 

Close Choices-js#1184
@Xon Xon closed this as completed in #1193 Sep 2, 2024
@Xon Xon closed this as completed in 5721e9a Sep 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants