import scss file from css file with webpack - css

In my project, I need to combine stylesheets that were written in 2 different preprocessor languages (SASS and Stylus) into one css file.
My naïve approach was to just add stylus-loader with a test for the .styl extension into my webpack config, and #import a stylus file from my app.scss file (which is the entrypoint).
It seems that sass-loader doesn't resolve modules like it happens in JavaScript. I also tried making an entrypoint CSS file with my app.scss and the Stylus file as imports, which also doesn't work.
Is this just a configuration I'm missing or do css-loader and sass-loader just not support this kind of module resolve?
Entry CSS
#import "sass-loader!./app.scss";
#import "stylus-loader!../node_modules/vuetify/src/stylus/main.styl
This will just result in this error:
ERROR in ./node_modules/css-loader??ref--6-1!./css/app.css
Module not found: Error: Can't resolve './sass' in '/Users/tux/projects/zenner/platform-base/platform/assets/css'
# ./node_modules/css-loader??ref--6-1!./css/app.css 3:10-95
ERROR in ./node_modules/css-loader??ref--6-1!./css/app.css
Module not found: Error: Can't resolve './stylus' in '/Users/tux/projects/zenner/platform-base/platform/assets/css'
# ./node_modules/css-loader??ref--6-1!./css/app.css 4:10-131

Because none of css-loader, sass-loader or style-loader can load files in other languages (which I think should be possible with a loader chain string like sass-loader!my-file.scss), I instead imported the styles in my index javascript file and used extract-text plugin. This works fine.
webpack.config.js
var ExtractTextPlugin = require("extract-text-webpack-plugin")
const extractCSS = new ExtractTextPlugin('css/styles.css')
{
test: /\.scss$/,
use: extractCSS.extract({use: ["css-loader", "sass-loader"]})
}, {
test: /\.styl$/,
use: extractCSS.extract({use: ["css-loader", 'stylus-loader']})
}
app.js
import "../css/app.scss"
import "vuetify/src/stylus/main.styl"

Related

NextJS "Can't resolve" error attempting to import PostCSS file

In a NextJS project that uses TailwindCSS, I have a global css file, index.css and I'm trying to import another file.pcss into the global css file. But, NextJS can't seem to find file.pcss, produces the error below:
Error: Can't resolve 'file.pcss' in '/home/chris/repo/styles'
index.css has:
#import 'file.pcss';
Not sure why this is happening because Next + Tailwind should support PostCSS without issue.
Figured it out!
When I converted both files to .scss files. Everything started working again.
Result:
global css file renamed to: index.scss
#import 'file.scss';
pcss file renamed to: file.scss
Solution came from: https://github.com/vercel/next-plugins/issues/565#issuecomment-561086895

How to handle css modules with ?module suffix in Jest

I'm building a react app that mixes global css with css modules using Symfony's webpack encore. To avoid global CSS issues I've settled on using import 'app.css' for global styles and import styles from 'component.css?module' in my components. This is working as expected, however Jest is not pruning the ?module from the css module import and cannot find the file, giving me errors like Cannot find module './login.module.css?module' from 'assets/pages/Login/index.jsx'.
Does anyone know how to workaround this?
I managed to fix this myself. If anyone is interested, I enabled css modules in webpack.config.js by adding
.configureCssLoader((options) => {
options.modules = true;
})
However this then applies css module loading to all .css files and breaks global css rules.
So I modified the webpack config manually using the following at the end of webpack.config.js
const config = Encore.getWebpackConfig();
// only include files ending in module.css in the module css loader
config.module.rules[1].include = /\.module\.css$/;
// add another css loader without modules enabled to parse global css files
config.module.rules.push({
test: /\.css$/,
use: ["style-loader", "css-loader"],
exclude: /\.module\.css$/,
});
module.exports = config;
Not sure if this is the best way, but seems to be working ok at the moment!
I had some similar issue and fixed it with something like that (with Webpack Encore) :
.configureCssLoader(options => {
options.modules = {
auto: /\.module\.\w+$/i
}})
And now you can create a file with '.module.scss' suffix, and you can import it in a ts file. (working with jest, unlike ?module)

How to compile multiple themes using a common SCSS file? [duplicate]

In Less I can do something like this
#basePath:"../../some_crazy_project_path_to_repeat/less/";
#import "#{basePath}less.less";
So I tried to do the same thing in Sass
$basePath:"../../some_crazy_project_path_to_repeat/less/";
#import "${basePath}less.scss";
// Syntax error: File to import not found or unreadable: ${basePath}less.scss.
and
#import "#{basePath}less.scss";
// Syntax error: File to import not found or unreadable: #{basePath}less.scss.
Is there a way to do this in Sass?
You can't use conditional stuff for imports in SASS.
Consider creating a Compass extension out of your project.
You cannot use variables in import paths as already mentioned. What you can do is use the -I or --load-path option to specify a directory to search from.
sass --watch sass/:css/ --load-path ../../path/to/library/
Let's say you have a directory structure like this:
themes
hotdog
_variables.scss
classic
_variables.scss
styles.scss
Your styles.scss should have import paths that are relative to the provided load-path(s):
// note the import here doesn't contain themes, hotdog, or classic
#import "variables";
#debug $foo;
Your commands would look something like this:
# hotdog
sass styles.scss hotdog.css --load-path ./themes/hotdog/
# classic
sass styles.scss classic.css --load-path ./themes/classic/
See the Sass options documentation for more information.

Webpack Sass and foundation how do I manipulate the variables

I'm working on a project with webpack to load all my assets.
I load my assets like that in app.js and concat them with ExtractTextPlugin:
import 'foundation-sites/scss/normalize.scss';
import 'foundation-sites/scss/foundation.scss';
import './../sass/app.scss';
I read somewhere that webpack will read each line and one by one compile to CSS and append them to my dist file.
My problem is that I want to access the variables and mixins in foundation from the app.scss, but since they are compile one after the other and appended, it doesn't seem possible to access those mixins and variables. Any one has a solution?
You need to load your dependent .scss files within app.scss.
To do this with webpack. I've configured my app.scss like so:
#import '~foundation-sites/scss/foundation';
#import 'settings';
#include foundation-everything($flex: true);
// the rest of my imports now have access to Foundation mixins
#import 'mycomponent.scss'
The ~ tells sass-loader to tell webpack to look in the modules directory for those files.

Compile css and sass files to single css file using gruntjs

I have a bootstrap.css file which I want to compile with my custom styles from style.sass into single output file, for example - style.css.
For sass compilation I use gruntjs with grunt-contrib-sass extension. My Gruntfile.js config for sass looks like this:
sass: {
dist: {
options: {
//style: 'compressed',
style: 'expanded',
lineNumbers: true
},
files: {
'build/styles/style.css': 'src/styles/style.sass'
}
}
}
I've tried to import bootstrap.css into sass file, but instead it only generates next code in output css (which is correct behavior http://sass-lang.com/documentation/file.SASS_REFERENCE.html#import):
#import url(bootstrap.css);
.....
/*my style.sass rules*/
I even tried to list multiple files in order of concatination and processing, like in uglifier settings:
files: {
'build/styles/style.css': ['src/styles/bootstrap.css', 'src/styles/style.sass']
}
But this only adds bootstrap.css into final style.css file ignoring style.sass existence.
As I'm new in gruntjs, I can't figure out how this should be done properly.
The Grunt configuration is correct. The reason your file is not being imported is because of the way SASS is designed to work.
The SASS documentation states:
By default, it looks for a Sass file to import directly, but there are a few circumstances under which it will compile to a CSS #import rule:
If the file’s extension is .css.
If the filename begins with http://.
If the filename is a url().
If the #import has any media queries.
Since the file you are importing has a .css extension it will therefore not be imported directly but remain a standard CSS #import.
You have three options to resolve this:
Rename the included file to _bootstrap.scss. (If you don't add the underscore a bootstrap.css will be created along with your main output file which is unnecessary.)
Include the Bootstrap SCSS source as a dependency of your project and build against that. Install the Bootstrap source using Bower by typing $ bower install bootstrap-sass-official in your project root folder. (For instructions on setting up Bower see the Bower website.) Then you can replace your import above with #import 'bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap';.
Use a concatenation library such as grunt-contrib-concat to combine Bootstrap.css and your main style sheet during your build process.
This first option is fine if you downloaded the bootstrap CSS file into your project manually, however, if you are including it as a dependency with npm/bower it is not ideal.
I would recommend the second option since building Bootstrap from source will not only solve your problem but allow for customization of Bootstrap variables to fit your theme rather than overwriting them with subsequent style rules as well. The only downside is that your build process might be slightly longer due to the rather large SASS build of the Bootstrap source.

Resources