Anidetrix / rollup-plugin-styles

🎨 Universal Rollup plugin for styles: PostCSS, Sass, Less, Stylus and more.
https://anidetrix.github.io/rollup-plugin-styles
MIT License
243 stars 43 forks source link

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

Open Kelt-prog opened 8 months ago

Kelt-prog commented 8 months ago

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 commented 7 months ago

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 commented 7 months ago

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.