rollup-plugin-styles
rollup-plugin-styles copied to clipboard
code splitting example and docs
Hi @Anidetrix and thanks for starting this plugin. You told in ReadMe file that one of the reasons for this plugin is supporting code-splitting:
Complete code splitting support, with respect for multiple entries, preserveModules and manualChunks
Is it supporting now or it's in your roadmap? If yes I think some examples and docs about this can be useful.
I want to test the code splitting and multi entry with your package. After switching to your library rollup didn't create any output file at all without any error message but when I mix your plugin with rollup-plugin-sass like bellow it's working:
import sass from "rollup-plugin-sass";
import nodeSass from 'node-sass'
import postcssSmartAsset from "postcss-smart-asset"
import styles from "rollup-plugin-styles"
const postcssSmartAssetOpts = {
url: 'inline'
}
plugins: [
sass({
runtime: nodeSass,
insert: true
}),
styles({
plugins: [postcssSmartAsset(postcssSmartAssetOpts)]
}),
]
...
Any idea about this?
Hi @mnlbox,
Is it supporting now or it's in your roadmap?
Yes, it is fully supported. And works just like Rollup's code splitting does, based on dynamic imports and preserveModules/manualChunks options. Also, you need to use extract mode, otherwise CSS is stored inside JS and code splitting occurs on JS side:
styles({
mode: "extract",
// other stuff...
})
If yes I think some examples and docs about this can be useful.
Yes, probably should do that.
As for your example:
- in this case
rollup-plugin-sassjust takes all the work and this plugin is not even used. - asset handling functionality is built-in inside the plugin, so
postcss-smart-assetplugin is not used in this case, or even might hurt the result, but if you really want to use it, disable the internal asset handler usingurl: false:
styles({
mode: "extract",
url: false,
plugins: [postcssSmartAsset(postcssSmartAssetOpts)]
})
As for the code splitting itself, just tested it to be sure nothing broke over time, and it works just fine, the simplest test is:
index.js:
import("./style1.scss");
import("./style2.scss");
style1.scss:
.style1 {
color: red;
}
style2.scss:
.style2 {
color: blue;
}
If you think something is broken after reading/trying the above, please make a minimal reproduction repo using rollup's REPL, REPL.it, or just a simple GitHub repo.
@Anidetrix
Oh, thanks, everything is working fine. I also completely remove postcss-smart-asset and using your plugin for asset handling. Just one question. Now I'm using bellow setting and I'm imported scss files in my component but when my component build my CSS import was removed.
I also don't want to use inject mode. I won't to use extract but keep my @import url.
styles({
minimize: true,
mode: 'extract',
url: {
inline: true
}
}),
I have this line in my js source file:
import './index.scss'
and want to convert this to something like this after build:
t=require("./index-09905e20.css")
but now it's removed and because of this my component redreded without any styles. Is it normal to remove scss import from js file?
Is it normal to remove scss import from js file?
In extract mode - this is intentional, since there's no require in the browser. I'd imagine you would use it with something like @rollup/plugin-html, or just include the resulting CSS file yourself in your own HTML file. If you need to use CSS as a string inside JS, you can use named css export, as it is described in the docs:
// Using named export of CSS string
import { css } from "./style.css";
If there's a real use case for keeping the require statement in the final bundle, please tell me and we'll go from there.
@Anidetrix I don't understand your guide :thinking: I didn't use plugin-html now and I think it's not helpful for my project.
Look this is my source structure:
├── FirstComponent
│  ├── index.scss
│ └── index.tsx
├── SecondComponent
│  ├── index.scss
│ └── index.tsx
So each component has its own style and imported like as I told for example in /FirstComponent/index.tsx I have this line:
import './index.scss'
and this is the style related to this specific component But now because your plugin will remove this import, then my component styles gone and component breaks. :thinking: In code splitting output I need this structure:
├── FirstComponent
│ ├── index.css
│ └── index.js
├── SecondComponent
│ ├── index.css
│ └── index.js
Now the structure is OK but relation between css and js files removed.
@Anidetrix I think it's not documentation :thinking: Maybe we need a fix to prevent remove import.
@mnlbox imports are not kept since they are not JS, thus rollup cannot understand and process them properly. I guess this is not that clear, so this needs documentation and separate feature addition to add require without breaking rollup. So this is labeled as both documentation and enhancement accordingly.
@Anidetrix But I didn't have a similar issue before when I used rollup-plugin-postcss and my CSS import line not removed from my js files before. So I think it's not related to rollup :thinking:
@Anidetrix I still think it's a bug. Maybe related to these two issues: https://github.com/Anidetrix/rollup-plugin-styles/issues/120 https://github.com/Anidetrix/rollup-plugin-styles/issues/117
I also tried to change import './index.scss' to require("./index.scss") in my index.tsx file. Now this line not removed from final files but the issue is that rollup-plugin-styles plugin didn't create any .css files at all and it seems broken.
I don't know it's a bug or something missed in documentation especially in preserveModules: true and extract mode.
I also don't want to use
injectmode. I won't to useextractbut keep my @import url.
I'm also running into this issue.
In
extractmode - this is intentional, since there's norequirein the browser.
@Anidetrix There is a use-case here, when using downstream bundlers. I'm using Rollup as an intermediate step for an UI library (which I think @mnlbox is also doing, judging from his filenames). While the browser can't recognize import statements, downstream bundlers can. It would be very useful if the import can stay in the bundle, so the end user of my library won't have to import the CSS separately.
You can view my project here, if you want to view for yourself. Run yarn && yarn build in the main directory, and yarn && yarn serve in the example directory. Then go to http://127.0.0.1:1234/ to view the components without styling.
I understand this is not always useful to have. So I propose to add an setting like preserveImports which, when true, keeps the imports in the bundle.
I took a shot at fixing it myself, but got stuck when actually writing the import statement. @Anidetrix can you help out here? I did find the output JS files, but the CSS files (and more importantly, their paths) were nowhere to be found.
@dsluijk Returning to work after a long break, will look into it.
That's great to hear! If you need any help let me know!
@dsluijk Returning to work after a long break, will look into it.
It's been a long time since you look into it.
Any updates on this?
Great to see that I'm not alone.
I left a comment here, and then found this page. It seems like the same topic, and since here are more people, so I just copied the comment here.
I'm in the same situation. I have source files in this structure
- src
- components
- button
- index.js
- index.scss
- index.js
- index.scss
I expected the dist files structure
- dist
- components
- button
- index.js
- index.css
- index.js
- index.css
And in dist/components/button/index.js, the CSS file import statement should be kept.
import './index.css';
And the name should be rather than import './index.scss.js';
I drafted a plugin to explain my idea, here is the codesandbox.
The file name is index.css rather than index.scss.js.
The content is plain CSS rather than JS.
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.