rollup-plugin-vue
rollup-plugin-vue copied to clipboard
Use rollup to transform styles before applying scope to scoped styles
Version
5.0.0
Reproduction link
None (this is an issue in the build step).
Steps to reproduce
Compile an SFC that requires sass files from node modules.
What is expected?
To find the sass files correctly from node_modules.
What is actually happening?
Sass files are not found.
I use the plugin to compile an SFC that import a sass file from node_modules. Here is my rollup.config.js:
import vue from "rollup-plugin-vue";
import commonjs from "rollup-plugin-commonjs";
import nodeResolve from "rollup-plugin-node-resolve";
import babel from "rollup-plugin-babel";
import replace from "rollup-plugin-replace";
const { PRODUCTION } = process.env;
export default {
input: "src/js/index.js",
output: {
format: "iife",
file: "dist/js/index.js"
},
plugins: [
babel({
presets: ["@babel/preset-env"],
runtimeHelpers: true,
plugins: ["@babel/plugin-proposal-export-default-from"]
}),
commonjs(),
nodeResolve(),
vue(),
replace({
"process.env.NODE_ENV": JSON.stringify(PRODUCTION ? "production" : "development")
})
]
};
And here is my SFC (producing the error):
<template lang="pug">
mdc-button Test
</template>
<script>
import { MdcButton } from "material-components-web-vue";
export default {
components: {
MdcButton
}
};
</script>
<style lang="scss">
@import "@material/button/mdc-button";
</style>
And here is the error:
$ rollup -c
src/js/index.js → dist/js/index.js...
[!] (plugin VuePlugin) Error: Error: Can't find stylesheet to import.
src\js\page\Home.vue 14:9 root stylesheet
src\js\page\Home.vue
Error: Error: Can't find stylesheet to import.
src\js\page\Home.vue 14:9 root stylesheet
at Promise.all.descriptor.styles.map (C:\xampp\htdocs\test-bug\node_modules\rollup-plugin-vue\dist\rollup-plugin-vue.js:241:31)
Does vue template compiler tries to load using CSS3 @import
instead of finding from node_modules
?
I read those 2 issues:
- https://github.com/vuejs/rollup-plugin-vue/issues/203
- https://github.com/vuejs/rollup-plugin-vue/issues/146
But it seems not working either (as I do not have the exact code the others persons used I post my full config here and hope someone can answer this tricky question I am struggling with).
@znck can you shed some light on this issue, and any potential workarounds? I get the exact same Can't find stylesheet to import.
error on all of my Sass imports within .vue
files, as they all reference node_modules
.
I also don't fully understand why the title was changed to include "before applying scope to scoped styles", as OP does not used scoped
within his reproduction example (nor do I).
After a bit of digging I've learned that importing node_modules
is not actually something sass
supports out-of-the-box. I was using the ~@some/package
syntax, having assumed that ~
was particular to sass
. But it's actually particular to sass-loader
, not sass
. sass-loader
uses it to forward imports to the Webpack resolver. So it looks like there isn't actually a bug in rollup-plugin-vue
, here.
Have a read: https://github.com/webpack-contrib/sass-loader/blob/master/README.md#resolving-import-at-rules
For your example, @khalyomede, you should be able to pass sass
a load path option, setting it to your node_modules
. I think you would use the style.preprocessOptions
option: https://github.com/vuejs/rollup-plugin-vue/blob/master/docs/options.md#stylepreprocessoptions. The format of sass
options is documented here: https://sass-lang.com/documentation/js-api#includepaths. Unfortunately, this might not work if you're publishing a library, as setting a load path is not equivalent to using node's package resolution algorithm, so package hoisting could go throw a wrench in this. For a regular application, though, it should be fine.
For my case, since I have an existing application with a codebase full of the ~
syntax, and an existing Webpack configuration that I cannot remove, it looks like I'll need to write a custom importer and pass that to sass
.
@khalyomede a quicker fix would be to run SASS_PATH=node_modules rollup -c
, which I can confirm works.
I found a fix that worked great for me:
rollup.config.js
const PATH_SRC = path.resolve(PATH_ROOT, "src").replace(/\\/gi, "/");
const PATH_NODE_MODULES = path
.resolve(PATH_ROOT, "node_modules")
.replace(/\\/gi, "/"); // Errm.. I use windows 😬
export default {
plugins: [
vue({
css: true,
data: { // This helps to inject variables in each <style> tag of every Vue SFC
scss: () => `@import "@/styles/variables.scss";`,
sass: () => `@import "@/styles/variables.scss"`,
},
style: {
preprocessOptions: {
scss: {
importer: [
function (url, prev) {
return {
file: url
.replace(/^~/, `${PATH_NODE_MODULES}/`)
.replace(/^@/, PATH_SRC), // ain't pretty, it can be easily improved
};
},
],
},
},
},
}),
],
};
Hi,
i have to admit i just quickly browsed over this issue and i hope i understood the problem right - however just a quick note on how i was able to import files from node modules - namely by altering the config for rollup-plugin-vue the following way:
vue({
style: {
preprocessOptions: {
scss: {
includePaths: ['node_modules'],
}
},
}),
might this be what you are looking for?
I found a fix that worked great for me:
rollup.config.js
const PATH_SRC = path.resolve(PATH_ROOT, "src").replace(/\\/gi, "/"); const PATH_NODE_MODULES = path .resolve(PATH_ROOT, "node_modules") .replace(/\\/gi, "/"); // Errm.. I use windows 😬 export default { plugins: [ vue({ css: true, data: { // This helps to inject variables in each <style> tag of every Vue SFC scss: () => `@import "@/styles/variables.scss";`, sass: () => `@import "@/styles/variables.scss"`, }, style: { preprocessOptions: { scss: { importer: [ function (url, prev) { return { file: url .replace(/^~/, `${PATH_NODE_MODULES}/`) .replace(/^@/, PATH_SRC), // ain't pretty, it can be easily improved }; }, ], }, }, }, }), ], };
Just tried this, but found out this does not work for CSS imports. If the import ends on ".css", it will simply not pass the file through the importer
function as it contains a .css
extension: https://sass-lang.com/documentation/at-rules/import#plain-css-imports.
I have slightly improved your importer
function to take extensionless .css
imports into account to mimic Sass's CSS imports
url => {
let replacedUrl;
if (url.includes("~")) {
replacedUrl = url.replace(/^~/, NODE_MODULES_PATH);
// Extensionless import https://sass-lang.com/documentation/at-rules/import#importing-css
// This does imply that non CSS files (`.scss` files for example), need an explicit extension
if (!/\.\w+$/.test(replacedUrl)) {
replacedUrl = `${replacedUrl}.css`;
}
}
return {
file: replacedUrl || url
};
}
I am not sure if sass-loader
works with extensionless imports. I hope it does, so I can replace my rollup config with a webpack config without making too many changes in the sourcecode.
Note that I did not replace @
as I didn't really need that for my use case.
EDIT: It does seem to still be applying the scoped
[data-xxx]
attribute to the imported classes, which I presume @khalyomede was referring to in the title.
Posting in case it's helpful to other's in the future, but I used a combination of other responses above which provides a more simple approach then replacing aliases... only note is that documentation on this could probably be better. I did have to define data in 2 different places to get it to work. I also use node-sass-glob-importer
for globbing my mixins/functions inside my library.scss
file, so if using that make sure to add it and this above the config
const globImporter = require('node-sass-glob-importer');
data: {
scss: () => '@import "library";'
},
style: {
preprocessOptions: {
scss: {
importer: globImporter(),
includePaths: [
path.resolve(__dirname, '../node_modules/breakpoint-sass/stylesheets/'),
path.resolve(__dirname, '../en-style/src/scss'),
path.resolve(__dirname, '../en-style/src'),
],
data: '@import "library";'
}
}
}
Is there any documentation of what options are available in preprocessOptions
? I can not get the data
pattern to inject the variables import to work in any context.
@plummer-flex that's within the vue-rollup-plugin
here (which isn't very useful) https://rollup-plugin-vue.vuejs.org/options.html#style-preprocessoptions
but I think that just takes options similar to the Vue CLI CSS loaderOptions
https://cli.vuejs.org/guide/css.html#passing-options-to-pre-processor-loaders
Furthermore, I believe all the css loaders had to make slight changes to their options for webpack 5 so I think you want to be using the options pre-webpack 5. I think for sass-loader version 10 is still compatible with webpack 4.