Webpack - React unable to load videojs css file via webpack - css

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

Related

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

Webpack: How to use CSS-modules and imported CSS from outside libraries?

I am using css-modules in my react application, however when I try to import outside files in .js files, I cannot import them globally because I cannot wrap them in a :global block, and webpack interprets them as styles meant to be used as objects.
How do I import CSS files as global CSS from external libraries? This is CSS that is supposed to match imported plugins.
e.g.in src/index.js
import 'draft-js/dist/Draft.css';
//cannot wrap in a :global block since it is imported
import 'react-responsive-carousel/lib/styles/carousel.min.css';
// is wrapped in a :global {...} block, so it works
import './styles/app.css';
Webpack configuration, from Create-React-App
test: /\.css$/,
loader: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
modules: true,
minimize: true,
},
},
'postcss-loader'
]
One option is to have two separate rules for src styles and node_modules styles and only set modules to true in your src config. It should look similar to below (I didn't test this) - the important options are include and exclude and to remove modules from the rule that applies to node_modules.
{
test: /\.css$/,
exclude: /node_modules/,
loader: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
modules: true,
minimize: true,
},
},
'postcss-loader'
]
},
{
test: /\.css$/,
include: /node_modules/,
loader: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
minimize: true,
},
},
'postcss-loader'
]
}

Add sass/css modules to typescript react app

In a new project, I need to add scss/css modules to a typescript/react app.
I added "typings-for-css-modules-loader" to the project and webpack.config.dev.js
like so : (here is the entire webpack.config.dev.js)
{
test: /\.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('typings-for-css-modules-loader'),
options: {
importLoaders: 1,
modules: true
},
},
{
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
],
},{
test: /\.scss$/,
use: [
require.resolve('style-loader'),
require.resolve('sass-loader'),
{
loader: require.resolve('typings-for-css-modules-loader'),
options: {
namedexport: true,
camelcase: true,
modules: true
}
}
]
},
When i add a test.scss file to my project, the compilation successfully creates a test.scss.d.ts which contains :
export interface ITestScss {
'toto': string;
}
export const locals: ITestScss;
When i try to import this css in my project like so :
import styles from './scss/test.scss';
I get this error :
Module '"/home/cyprien/projets/test/typescript-sass-modules-boilerplate/src/scss/test.scss"' has no default export.
Finally, In the browser, i get this error :
Failed to compile
./src/scss/test.scss
Module build failed:
.toto{
^
Invalid CSS after "e": expected 1 selector or at-rule, was "exports = module.ex"
in /home/cyprien/projets/test/typescript-sass-modules-boilerplate/src/scss/test.scss (line 1, column 1)
You need to use the plugin mini-css-extract-plugin. Here is an example of configuration with TypeScript and SASS SCSS (but without CSS modules neither PostCSS):
// webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
module.exports = {
mode: "development",
devtool: "source-map",
resolve: {
extensions: [".ts", ".js"]
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: {
loader: "ts-loader"
}
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"sass-loader"
]
}
]
},
plugins: [
new MiniCssExtractPlugin()
]
}
I hope you'll be able to adapt it.
Found this solution:
webpack config (dev), this is for less :
{
test: /\.modules\.less$/,
use: [{
loader: 'style-loader' // creates style nodes from JS strings
},{
loader: 'typings-for-css-modules-loader',
options:{
modules:true,
namedExport: true,
camelCase: true,
localIdentName:'[path][name]---[local]---[hash:base64:5]'
}
},{
loader: 'less-loader',
options: { javascriptEnabled: true }// compiles Less to CSS
}]
}
then name your less file something.modules.less
import it in the js as so:
import * as styles from './something.modules.less';
and use it like this:
<div className={styles.yourClassName}></div>

Resources