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

Is it possible to import css file to js with preserveModules option enabled? #247

Open
Kelt-prog opened this issue Jan 27, 2024 · 2 comments

Comments

@Kelt-prog
Copy link

Hi everyone.
Im wondering is it possible to import css files into js using import syntax with preserveModules:true in rollup config?
Bundling all css in one file is not an option, because Im making ui library. Also injecting css to works bad on Nextjs.

Bellow file structure of what Im trying to achieve.
index.js

import "styles.css"

Source files structure
-src
--components
---button
----index.ts
----index.module.css
---link
----index.ts
----index.module.css

Expected transpiled files structure
-lib
--components
---button
----index.js
----index.css
---link
----index.js
----index.css

@SunHuawei
Copy link

SunHuawei commented Feb 29, 2024

I have the same question about the SCSS format.
Source files structure

- src
    - components
        - button
            - index.js
            - index.scss
    - index.js
    - index.scss

Expected transpile files structure

- lib
    - components
        - button
            - index.js
            - index.css
    - index.js
    - index.css

And in lib/components/button/index.js

import './index.css';

rather than import './index.scss.js';

@SunHuawei
Copy link

SunHuawei commented Feb 29, 2024

I drafted a plugin to explain my idea, here is the codesandbox.

The file name is index.css rather than index.scss.js.
image

The content is plain CSS rather than JS.
image

Here is the main code

function scss() {
  return {
    name: "rollup-scss-to-css-plugin",
    transform(code, id) {
      if (id.endsWith(".scss")) {
        return new Promise((resolve, reject) => {
          const opts = {
            data: code,
            file: id,
            includePaths: [path.dirname(id)],
          };

          sass.render(opts, (error, obj) => {
            if (error) {
              reject(error);
              return;
            }

            this.getModuleInfo(id).meta.targetCSS = obj.css.toString();

            resolve({
              moduleSideEffects: "no-treeshake", // I have to use this to keep the chunk
              code: "export default {}", // fake code to keep chunk
              map: null,
            });
          });
        });
      } else {
        return Promise.resolve({ code, map: null });
      }
    },
    renderChunk(code, chunk, options, meta) {
      if (code.includes(".scss.js")) {
        return code.replace(".scss.js", ".css"); // dirty way to replace the code in consumer files
      } else if (chunk.fileName.endsWith(".scss.js")) {
        options.sourcemap = false; // the sourcemap is not able to be fixed, just sacrifice it
        chunk.fileName = chunk.fileName.replace(".scss.js", ".css"); // mutate this to fix the file name
        return this.getModuleInfo(chunk.facadeModuleId).meta.targetCSS; // replace the content with the plain css
      }
    },
  };
}

I'm not familiar with Rollup's mechanism, but I believe there must be a better way to achieve this. Anyone who has an idea, please let me know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants