Tilde in url with css modules does not work - css

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
},
},
]
}

Related

Webpack - React unable to load videojs css file via webpack

I'm implementing video.js in a React web-app.
Using
import video.js/dist/video-js.min.css
it doesn't load all the css classes. Whilst if I use the following form it does.
require('!style-loader!css-loader!video.js/dist/video-js.min.css');
The latter form though triggers a import/no-webpack-loader-syntax eslint error.
How can I configure webpack in order for it to load the video-js.min.css file?
My webpack css loader config looks like this right now:
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
importLoaders: 1,
localIdentName: '[name]__[local]___[hash:base64:5]',
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
autoprefixer()
],
sourceMap: true
}
}
]
}

Configure fonts in webpack

I have a slight problem with webpack here; I'm somewhat unable to load fonts.
This is my webpack.config.js
const nodeExternals = require('webpack-node-externals');
const path = require('path');
const devMode = true;
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry:
[
'./src/main.js',
'./scss/main.scss'
],
output: {
filename: "main.min.js",
chunkFilename: '[name].bundle.min.js?bust=[chunkhash]',
path: path.resolve(__dirname, 'static_root'),
publicPath: "/assets/"
},
target: "node",
externals: [nodeExternals()],
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css',
ignoreOrder: false, // Enable to remove warnings about conflicting order
}),
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.scss$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].css',
outputPath: 'css/'
}
},
{
loader: 'extract-loader'
},
{
loader: 'css-loader'
},
{
loader: 'postcss-loader'
},
{
loader: 'sass-loader'
}
]
},
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../',
hmr: process.env.NODE_ENV == 'development',
}
},
],
},
{
test: /\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: '[name].[ext]'
}
}
]
}
};
This builds my css although then my local fonts aren't included / aren't rendered.. This also copies my Font to /static_root (which is where the css gets built to).
so I end up with this directory structure:
public/static_root/css/main.css
public/static_root/BebasNeue-Regular.ttf
public/static_root/main.min.js
I thought about just adjusting the path to the font in my scss file unfortunately though this lets the build process fail, since my working dir and the output root aren't the same.
My scss/font-directory is structured like so:
/public/scss/fonts/_fonts.scss
/public/scss/fonts/BebasNeueRegular.ttf
/public/scss/main.scss
So how can I achieve the inclusion of the font or how is this usually done since I found lots of different approaches online, that sadly didn't work out for me.
Any help would be greatly appreciated.
Greetings,
derelektrischemoench
So I found out what was causing the problems. It had to do something with the loader for the fonts (I was using an older one). I tried the whole thing with the url-loader like so:
{
test: /\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: '[name].[ext]'
}
}
... which got it going. It was just kinda confusing, since I found a bazillion of tutorials on the web on how to achieve this, of which the most part was deprecated.
Thanks for the responses.
hey #derelektrischemoench, I think the example in Webpack official website is pretty good, you could follow the webpack config and its file structure:
https://webpack.js.org/guides/asset-management/#loading-fonts

Css of node-modules

I am using css modules in my react application. After setting modules:true inwebpack.config.js, I am able to get css from files which I created in my src folder. I am importing some components from node-modules. But the css of components present in node-modules is not getting applied.
I also tried importing css of node-modules using import 'path'; but it didnt work.
If I set modules:false, css of node-modules is getting applied and css of files in src folder is not getting applied.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: "style-loader"
},
{
loader: "css-loader",
options: {
modules: true,
},
}
],
},
],
},
};
This might be due to the node module you are using may not be following module syntax. I mean they might be setting classes directly with a string instead of using like style.someClassName. So, you need 2 entries in your rules 1 for your stuff and 1 for node modules.
for ex:
module.exports = {
module: {
rules: [{
test: /\.css$/,
exclude: /node_modules/,
use: [{
loader: "style-loader"
},
{
loader: "css-loader",
options: {
modules: true,
},
}
],
}, {
test: /\.css$/,
include: /node_modules/,
use: [{
loader: "style-loader"
},
{
loader: "css-loader",
options: {
modules: false,
},
}
],
}],
},
};

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
}
}
]
},
]
}

Resources