Sass not load correct background SVG image using webpack - css

I have a following rules defined in the webpack.config.js
rules: [
{
test: /\.svg$/,
use: ['svgr/webpack', 'url-loader']
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'resolve-url-loader',
'sass-loader'
]
},
{
test: /.js?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
plugins: ['transform-class-properties', 'transform-object-rest-spread'],
presets: ['es2015', 'react']
}
}
]
As you can see I use a svgr plugin to translate SVG images into a React components, and it works fine.
Troubles come when I want to use a SVG image as a background CSS property in .scss file.
.scss file with selector looks:
.some-name-class {
background-image: url('../images/example.svg');
}
And following output is generated when I examine element by the Chrome Dev Tool:

The issue here is that svgr/webpack tries to return a React Object, when ever it encounters a .svg file. And the same is the output you found. which has an object in the output css file. To fix this, you can use the issuer differently. Eg:
{
test: /\.svg$/,
issuer: /\.(js)x?$/,
use: ['svgr/webpack']
},
{
test: /\.svg$/,
issuer: /\.css$/,
use: ['svg-url-loader']
}

Related

Normal CSS with CSS Modules

I was previously using bootstrap css import fine previously.
However I'm trying to use CSS module so I added a few lines.
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: true, //<- Added to enable css module
localIdentName: '[name]__[local]___[hash:base64:5]' //<-Added to enable css module
}
},
'postcss-loader'
]
},
Now I'm able to use the following sample codes
import styles from 'styles.css'
and use it in the code like this
<div className={styles.container}></div>
and it becomes like this in browser
<div class="styles__container___3dfEE"></div>
I have the following in my index.js
import 'bootstrap/dist/css/bootstrap.min.css';
Now, all my classes from bootstrap.min.css are no longer working.
How can i enable both css modules as well as continue to use bootstrap css normally?
I'm currently using a "dirty" way to do it, by saving my custom styles as styles.sss instead and added the following codes in webpack config. Not sure whether it will have any issues.
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1
}
},
'postcss-loader'
]
},
{
test: /\.sss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: true,
localIdentName: '[name]__[local]___[hash:base64:5]'
}
},
'postcss-loader'
]
}
you need to import bootstrap's css without going through your original webpack config:
import "!style-loader!css-loader!bootstrap/dist/css/bootstrap.min.css";
this will activate the style-loader and css loader but without the modules: true option
I have learnt few methods before for this Github pull-request issue.
First, change the file name. Easiest way but ugly.
Change your styles.css to styles.m.css and separate module and plain css like
//Module
test: /\.m.css$/
//Plain
test: /\^((?!\.m).)*css$/
Second, separate the folders for module and plain css, while exclude each other.
//Module
exclude: /css/plain/
//Plain
exclude: /css/module/
Third, use resourceQuery
test: /\.css$/,
oneOf: [{
resourceQuery: /^\?raw$/,
use: [...]
}
And import as
import './bootstrap.min.css?raw'
Try to separate the loaders into different rules. Like this:
{
test: /\.css$/,
use: [
'style-loader',
]
},
{
test: /\.css$/,
use: [
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: true,
localIdentName: '[name]__[local]___[hash:base64:5]'
}
},
'postcss-loader'
]
}

Webpack 4 - Style-loader/url not working

I'm having my webpack set up and it's running all fine, but in development it is serving my compiled scss stylesheets inline instead of using an URL.
module: {
rules: [
{
test: /\.scss$/,
use: [
{ loader: "style-loader"},
{ loader: "css-loader" },
{ loader: 'postcss-loader',
options: {
plugins: () => [require('autoprefixer')]
}
},
{ loader: "sass-loader" }
]
}
]
}
So I grabbed the docs and read up on how to use a single CSS file instead. I updated my webpack config to the following and since all loaders are running in reverse order this should be working;
module: {
rules: [
{
test: /\.scss$/,
use: [
{ loader: "style-loader/url"},
{ loader: "file-loader" },
{ loader: "css-loader" },
{ loader: 'postcss-loader',
options: {
plugins: () => [require('autoprefixer')]
}
},
{ loader: "sass-loader" }
]
}
]
}
It results in no errors, and inserts the following stylesheet into my header;
<link rel="stylesheet" type="text/css" href="6bbafb3b6c677b38556511efc7391506.scss">
As you can see it's creating an scss file, whereas I was expecting a .css file. I tried moving the file-loader around but that didn't work either and resulted in several crashes. Any idea how to turn this into a working css file?
I can't use mini-css-extract in my dev env since I'm using HMR. I already got this working on my prod env.
Update: When removing css-loader it compiles and shows my css applied to the page. But when I inspect the elements everything is on line 1 and the file it refers to can not be found
I'm importing my css like this in index.js by the way;
import '../css/styles.scss';
You can install extract-text-webpack-plugin for webpack 4 using:
npm i -D extract-text-webpack-plugin#next
The you can define the following constants:
// Configuring PostCSS loader
const postcssLoader = {
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: [
// Write future-proof CSS and forget old preprocessor specific syntax.
// It transforms CSS specs into more compatible CSS so you don’t need to wait for browser support.
require('postcss-preset-env')()
]
}
};
// Configuring CSS loader
const cssloader = {
loader: 'css-loader',
options: {
importLoaders: 1
}
};
Then in your SASS loader section, you can use the following:
ExtractTextPlugin.extract({
use: [cssloader, postcssLoader, 'sass-loader']
})
Then in you plugins section, you need to use the following:
new ExtractTextPlugin({
filename: 'css/[name].css'
)
Now suppose that your entry section is like below:
entry: {
app: 'index.js'
}
The generated CSS will be named as app.css and placed inside the css folder.
Another useful plugins for handling these type of post creating operations are:
HtmlWebpackPlugin and HtmlWebpackIncludeAssetsPlugin
Working with these plugins along with extract-text-webpack-plugin gives you a lot of flexibility.
I had a similar issue with webpack, after searching for a long time i found the soluton of combining a few plugins:
This is my result config: (as a bonus it preserves your sass sourcemaps;))
watch: true,
mode: 'development',
devtool: 'source-map',
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css", //make sure you use this format to prevent .scss extention in the hot reload file
chunkFilename: "[id].css"
})
],
module: {
rules: [
{
test: /\.scss$/,
use: [
'css-hot-loader', //5. this will hot load all the extracted css.
MiniCssExtractPlugin.loader, //4 this will extract all css
{
loader: "css-loader", //3. this is where the fun starts
options: {
sourceMap: true
}
},
{
loader: "postcss-loader", //2. add post css
options: {
sourceMap: true
}
},
{
loader: "sass-loader", //1 . you can ingore the globImporter
options: {
importer: globImporter(),
includePaths: ["node_modules"],
sourceMap: true
}
}
]
},
]
}

loading .jpn images in reactJs

I have just configured my project with style-loader and css-loader -
module: {
loaders: [
{
test: /\.jsx?$/,
loaders: ['babel'],
include: path.join(__dirname, 'scripts')
},{
test: /\.css$/,
loaders: [ 'style-loader', 'css-loader' ]
}
]
}
Which works perfectly but then i encountered a problem with my .jpn image.
ERROR in ./scripts/radio.jpg Module parse failed:
C:\Users\barak\WebstormProjects\FinalProjectRadioStream\scripts\radioo.jpg
Unexpected character '�' (1:0) You may need an appropriate loader to
handle this file type.
Any recommendations about images loaders? some simple way for using images in css files with react and webpack?
Thanks.
I think you are using webpack.
You need to config for image loader files like this (use 'file-loader'):
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {}
}
]
}
]
}
}
Learn more: https://webpack.js.org/loaders/file-loader/

Webpack.config not running Sass-Loader before PostCSS-Loader

My config file currently has the following possibly relevant code:
{
// do not exclude `node_modules`
test: /\.css$/,
loader: ExtractTextPlugin.extract(
'style-loader',
'css',
{ publicPath: '../' }
)
},
{
test: /\.scss$/,
exclude: /node_modules/,
loader: ExtractTextPlugin.extract(
'style-loader',
['css-loader', 'postcss-loader', 'sass-loader'],
{ publicPath: '../' }
)
},
It's important that I run sass-loader first because PostCSS-loader (Autoprefixer) is unable to reach code within a #mixin that I have.
So far I've been unable to apply the relevant vendor prefix to the #mixin code being imported in. Everything works as expected if I move the #mixin code to where I #include it.
For Webpack 1 the extract function is expecting two parameters.
The first parameter will be applied when you're not extracting css to a file (fallback).
The second parameter is a list of loaders separated by an exclamation mark (!) , these loaders are applied from right to left.
ExtractTextPlugin.extract(
'style-loader',
'css-loader!postcss-loader!sass-loader'
);
For Webpack 2:
The ExtractTextPlugin is expecting a loader or an object.
ExtractTextPlugin.extract(options: loader | object)
Example:
{
test: /\.scss$/,
exclude: /node_modules/,
loader: ExtractTextPlugin.extract({
fallbackLoader: "style-loader",
loader: [
"css-loader",
"postcss-loader",
"sass-loader"
]
})
}
I've discovered the issue in my code. My entry-point files, where the scss files were being imported, were importing as such:
import styles from '!style-loader!css!sass!postcss-loader!./styles/styles.scss'
This was overwriting the configurations in my webpack.config files, so I simply changed all my import lines to have the correct loader order.

How to specify multiple loaders in Webpack plugin?

My Webpack config contains the following loaders.
module: {
loaders: [
{ test: /\.js$/, loader: "babel", exclude: /node_modules/ },
{ test: /\.sass$/, loaders: ["style-loader", "css-loader", "sass-loader"], exclude: /node_modules/ }
]
},
Then, I wished to pull out the CSS to a separate file and I tried using the extract text webpack plugin, alternating my config like this.
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module: {
loaders: [
{ test: /\.js$/, loader: "babel", exclude: /node_modules/ },
// { test: /\.sass$/, loaders: ["style-loader", "css-loader", "sass-loader"], exclude: /node_modules/ }
{
test: /\.sass$/,
loader: ExtractTextPlugin.extract(
{
loaders: ["css-loader", "sass-loader"],
fallbackLoader: "style-loader"
}
),
exclude: /node_modules/
}
]
},
plugins: [new ExtractTextPlugin("global.css")],...
However, it fails with. Probably due me not specifying the loaders correctly. How can I specify multiple loaders (one for SASS and one for CSS)?
Module not found: Error: Cannot resolve module '[object Object]' in C:\Source\Poc\TestProj
# ./index.js 7:14-38
I've checked the file index.js but I can't see anything wrong there. It's literally empty export, as shown below. And the reference to 7:14-38 says nothing to me. There aren't that many lines in the file, even...
import CssGlobal from "./global.sass";
//document.write("Banana!");
export default {}
This syntax for ExtractTextPlugin.extract() only works in webpack2 and above, apparently (an object as argument). Check this issue.
In order to make it work with webpack1, the syntax is:
ExtractTextPlugin.extract([notExtractLoader], loader, [options])`
notExtractLoader (optional) the loader(s) that should be used when the css is not extracted (i.e. in an additional chunk when allChunks:
false)
loader the loader(s) that should be used for converting the resource to a css exporting module.
Source: https://github.com/webpack/extract-text-webpack-plugin/blob/webpack-1/README.md
So, a working config file would be:
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
/* ... */
module : {
loaders: [
{ test: /\.js$/, loader: "babel", exclude: /node_modules/ },
{
test: /\.sass$/,
exclude: /node_modules/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader!sass-loader")
/* using ExtractTextPlugin.extract(["css","sass"]) works too */
}
]
},
plugins: [
new ExtractTextPlugin("styles.css")
]
}
This will genereate a styles.css file.
Loaders are transformations that are applied on a resource file of your app. They are functions (running in node.js) that take the source of a resource file as the parameter and return the new source.
For example, you can use loaders to tell webpack to load CoffeeScript or JSX.
Nicely Explained here
http://ui-codeman.blogspot.in/2017/02/webpack.html?view=sidebar

Resources