If my application is using
test: /\.s+([ac])ss?/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[hash:base64:7]'
}
},
{
loader: 'sass-loader',
options: {
sourceMap: !isProductionEnvironment
}
},
{
loader: 'sass-resources-loader',
options: {
resources: 'src/styles/variables.scss'
}
}
]
webpack configuration to load css and sass, semantic-ui-sass package gets hashed upon import, is there a way to comfortably use semantic-ui-react package to decode those hashes?
Alternatively I am trying to use the
:global {
#import '~semantic-ui-sass/semantic-ui';
}
:global directive so that it could be used globally, but the webpack compiler then does not resolve icons and fonts from that package:
Module not found: Error: Can't resolve '../../icons/outline-icons.woff2'
Any ideas please?
I have solved the following issue by manually handling font icons and images by providing the semantic variables with their path:
<src/styles/global.scss>
$icons-font-path: '~semantic-ui-sass/icons';
$flags-image-path: '~semantic-ui-sass/images';
:global {
#import '~semantic-ui-sass/semantic-ui';
}
Related
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
}
}
]
},
]
}
I have been using webpack 4.6.0:
I have following issue when compiling:
Uncaught Error: Module parse failed: Unexpected token (1:4)
You may need an appropriate loader to handle this file type.
| div {
| background-color: yellow;
| color: red;
my webpck config is as following:
var path = require('path');
var webpack = require('webpack');
module.exports = {
mode:'development',
entry: './src/code/app.js',
output: { path: __dirname, filename: 'bundle.js'},
watch: true,
module: {
rules: [
{
test: /.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
plugins: "transform-class-properties",
presets: ['es2015', 'react']
}
},
{
// Do not transform vendor's CSS with CSS-modules
// The point is that they remain in global scope.
// Since we require these CSS files in our JS or CSS files,
// they will be a part of our compilation either way.
// So, no need for ExtractTextPlugin here.
test: /\.css$/,
include: /node_modules/,
loader: 'css-loader'
}
]
}
};
and I have :
"css-loader": "^0.28.11",
and my file struct is like:
root:
-src
|-code
|-XXXX.js
|-css
|-HomePage.css
I think it is something related to my css loader, I have tried many methods online, but none of them works. Is there something related to my file structure?
I believe you still need to add a rule for your own css files. Try adding this to your rules.
{
// Preprocess your css files
// you can add additional loaders here (e.g. sass/less etc.)
test: /\.css$/,
exclude: /node_modules/,
use: ['style-loader', 'css-loader'],
}
In my app, lets say I have two JS pages A and B, and each import a different stylesheet (import '../style/<A or B.css>').
Both stylesheets have identical classnames but but different properties.
I run yarn run dev ==> dev: webpack-dev-server --inline --hot ==> webpack -p
This is what my html <head> looks like
https://imgur.com/a/1JVb5
page A stylesheet is loaded first, then page B css style is loaded after
When I go to Page B, the css is correct
When I go to Page A, the css is mixed up and some class styles are overriden by page B.css.
My project structure is like
public/
bundle.js
index.html
src/
components/
pages/
style/
App.js
index.js
package.json
webpack.config.js
my webpack.config.js is
const path = require('path');
var config = {
entry: path.resolve(__dirname, 'src', 'index.js'),
output: {
path: path.resolve(__dirname, 'public'),
filename: 'bundle.js'
},
devServer: {
contentBase: path.resolve(__dirname, 'src'),
publicPath: path.resolve(__dirname, 'public')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: [
{ loader: 'babel-loader',
options: { presets: ['react','env'] } }
]
},
{
test: /\.css$/,
use: [
{ loader: "style-loader?singleton",
options:
{ singleton: true }
},
{ loader: "css-loader" }
]
}
]
}
};
module.exports = config;
I want Webpack to merge the multiple elements and fix the css override issue
In Webpack, I have tried style-loader?singleton and { singleton: true } but it didnt work.
EDIT 1: looking into extract-text-webpack-plugin
EDIT 2:
import movieStyle from '../style/MovieDetail.css'
...
return (
<div id="CellDetail_right" className={ movieStyle['cell-detail-right'] }>...</div>
)
Ok, I added options: { modules: true } and it didnt work. My classNames are hyphenated and after compiling the browser renders the components WITHOUT any style or classes.
Div on browser looks like <div id="CellDetail_right">...<div>
One solution is to enable local scoped css to avoid styles bleeding/overrides.
Update your css-loader options to include modules: true
{
test: /\.css$/,
use: [
{
loader: "style-loader",
options: { singleton: true }
},
{
loader: "css-loader",
options: {
modules: true,
camelCase: 'dashes',
localIdentName: '[path][name]__[local]'
}
}
]
}
Then, using in your components as:
import styles from '../style/MovieDetail.css';
function MyComponent() {
return (
<div className={styles.container}>
<div className={styles.cellDetailRight}>Some Content</div>
</div>
);
}
This ensures that despite you have more .container rules defined in other css files, this particular rule becomes to something like ._-path-to-component__container.
Using camelCase: 'dashes' in options transform your hyphenated rules.
dashes in class names will be camelized
You can also review my webpack-demo project which includes configs to handle your scenario.
Check the webpack configurations
Read more on css-loader options
Do you have some example config that works?
setting for webpack:
{
test: /\.scss$/,
use: ['style-loader', {
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[local]--[hash:base64:5]',
},
}, 'sass-loader'],
},
Usage:
background: url('~assets/arrow-white.svg') center no-repeat;
Output:
Module not found: Error: Can't resolve './assets/arrow-white.svg'
I can omit ~ or use ~/../assets and it works , but I would like to use it just ~.
Probably relevant bug: CSS modules break build if used with ~ https://github.com/webpack-contrib/css-loader/issues/589
I just copy your comment in order that you may close this question
the problem is that css-modules mode changes path resolution and
doesn't respect webpack module resolution
Use this package https://github.com/P0lip/url-tilde-loader
// In your webpack config
{
test: /\.s?css$/,
use: [
'style-loader',
{
loader: "css-loader",
options: {
modules: true,
},
},
{
loader: 'url-tilde-loader'
options: {
replacement: '~/../', // string to replace with
traverse: false, // use manual traversing
},
},
]
}
In my Vue component, I changed the language from the default CSS to the explicitly set SCSS, like this.
<style lang="scss">
div.bordy{ border: solid 3px red; }
</style>
I also changed the webpack.config.js according to this post by LinusBorg, so it looks like this.
module.exports = {
entry: ["babel-polyfill", "./index.js"],
output: { path: __dirname, filename: "bundle.js" },
module: {
loaders: [
{ test: /\.js$/, loader: "babel", exclude: /node_modules/ },
{ test: /\.vue$/, loader: "vue" },
// { test: /\.scss$/, loader: 'style!css!sass' },
{ test: /\.s[a|c]ss$/, loader: "style!css!sass" }
]
},
babel: {
presets: ["es2015", "stage-3"],
plugins: ["transform-runtime"]
},
vue: { loaders: [{ scss: "style!css!sass" }] },
resolve: { alias: { "vue$": "vue/dist/vue.common.js" } }
}
The guy explains that by doing so, we catch SCSS and map it to SASS. However, I'm getting an error saying the following.
Module not found: Error: Cannot resolve module 'scss-loader'
I've tried installing the packages as shown below but it gave no difference in the output error.
npm install scss-loader --save-dev
Here, I get uncertain and googlearching leads me to more confusion because I'm reading hints in all possible directions, not rarely commented with angry shouts of not resolving the issue.
Should I use style lang="sass" to being with?
When I try that, I have to install node-sass and I'm not sure if I'm resolving the problem or hiding it...
You have to install sass-loader and node-sass and it's resolving the problem not hiding it.
sass-loader documentation clearly says:
The sass-loader requires node-sass and webpack as peerDependency. Thus you are able to specify the required versions accurately.
and here are peerdependency from it's package.json:
"peerDependencies": {
"node-sass": "^3.4.2 || ^4.0.0",
.....
Which means sass-loader will work with these versions of node-sass.
It requires it in the very 4th line of it's code - sass-loader/index.js:
'use strict';
var utils = require('loader-utils');
var sass = require('node-sass');
Once you have it installed, you can do any of following:
<style lang="scss">
or
<style lang="sass">
as you are going to use same loader for both of these.