How to import css from libraries via postCSS? - javascript

I am using this library for slideshows called Flickity that requires to use its css file flickity.min.css. In my project I use postCSS and when including this flickity.min.css into my components css like:
#import ./lib/flickity.min
its classes get prefixed in the following way: MyComponent__flickity-class_35aw issue with this is that flickity creates new dom elements and relies on its classes, so in inspector the class for it would be .flickity-class hence no styles are applied to it, I'm trying to figure out how to include it correctly.
Using react + webpack setup

It looks like you're importing the CSS as CSS Modules. If you didn't intend to use CSS Modules you just need to remove 'modules' from your webpack config, i.e.
loaders: [
{
test: /\.css$/,
loaders: 'style!css?modules'
}
]
Should just become:
loaders: [
{
test: /\.css$/,
loaders: 'style!css'
}
]
If however you want to use CSS modules for some files but not others I would recommend defining multiple CSS loader configs based on an appropriate heuristic, e.g. assuming your /lib/ directory will only ever contain 'global' CSS you could do this:
loaders: [
{
test: /\.css$/,
exclude: /lib/,
loaders: 'style!css?modules'
},
{
test: /\.css$/,
include: /lib/,
loaders: 'style!css'
}
]

Related

CSS into JS using webpack

I`m trying to paste a CSS Code into a JS File using webpack
My flux is the following
SASS file > CSS content > PostCSS > css file
{
test: /\.(sass|scss)$/,
exclude: /node_modules/,
use: [
MiniCSSExtractPlugin.loader,
'css-loader',
'postcss-loader',
{
loader: 'sass-loader',
options: {
sourceMap: true,
sassOptions: {
outputStyle: 'compressed'
}
}
}
]
}
But the MiniCSSExtractPlugin gets me the content into a css file.
I'm use Lit Element so the styles should be declare with css function part of lit-element on the following way
import {css} from 'lit-element';
export default css`
:host {
display: inline;
}
`;
Is there any way to generate css code as a string and paste it into js file?
To import a CSS file into JS (w/webpack) you need to configure webpack with the following loaders:
css-loader
style-loader
Both available with NPM:
$ npm i css-loader style-loader --save-dev
And add this entry to the module.rules array in your webpack configuration:
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}
The result
Both of this loaders correctly configured will allow you to do the following sentence in JavaScript:
import myStyles from './your-css-file.css';
And then, you can just paste them into literal templates as follows:
static get styles() {
return css`${myStyles}`;
}
Additionally:
With a deep knowledge into what you might be talking about, you might need to take a look around #cells/cells-cli files and add those loaders into webpack configuration. Otherwise, you may need to create a webpack.config.js file in every lit-element component, which might not be the best for the current architecture.
Nice to see you around here, ¡saludos!;)
#k3llydev, I tried your suggestion and couldn't get it to work. Do you have any suggestions, specifically when you say "both of these loaders correctly configured will allow you to do the following"? I'd like to be able to import the CSS and then use it directly in the styles getter like you show in your example, but I had to do this as a workaround:
import MyImportedStyle from './some.css';
static get styles () {
return [
css`${unsafeCSS(MyImportedStyle.toString())}`
];
}
While using the 'to-string-loader' in webpack:
{
test: /\.css$/i,
use: ['to-string-loader', 'css-loader'],
}
This worked out for me and did what I wanted, but if I could avoid using the to-string-loader and could use the imported object directly, that would be idea. Any suggestions?
This way should do what the original poster asked for, a way to get the CSS as a string and use it in your LitElement.

Enabling CSS Modules from css-loader disallows importing node_modules CSS

I have a CSS Modules rule on webpack
{
test: /\.css$/,
loader: 'style-loader!css-loader?modules=true&localIdentName=[name]__[local]___[hash:base64:5]'
}
Enabling modules modules=true gives me the following error:
ERROR in ./node_modules/css-loader?modules=true&localIdentName=[name]__[local]___[hash:base64:5]!./src/global.css
Module not found: Error: Can't resolve '~/antd/dist/antd.css' in '[REDACTED]'
# ./node_modules/css-loader?modules=true&localIdentName=[name]__[local]___[hash:base64:5]!./src/global.css 3:10-141
# ./src/global.css
# ./src/entry.jsx
This happens at the CSS line
#import '~/antd/dist/antd.css';
antd is a dependency that is in node_modules.
However, removing modules=true from the loader seems to generate no error from this import line.
I need CSS modules and I need to import this CSS. How can I fix this?
You can stop css-loader to interpret #import statements by setting your config as follows
{
test: /\.css$/,
use: [
{
loader:'style-loader'
},
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[name]__[local]___[hash:base64:5]',
import: false
}
}
]
}
Unfortunately, this is a known issue with CSS-loader. #imports don't work properly when modules are enabled.
There is an ugly solution for this, but a solution nonetheless.
What I did is I replaced the rule with this:
{
test: /^((?!\.module).)*css$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
}
]
},
{
test: /\.module.css$/,
loader: 'style-loader!css-loader?modules=true&localIdentName=[name]__[local]___[hash:base64:5]'
},
CSS files that require #import like in my case above, will now work, however these files cannot be imported in javascript as a CSS module.
CSS files that should be modular must be end with the file extension .module.css for CSS modules to work.

What is the purpose for the fallback option in ExtractTextPlugin.extract

Using the example from webpack-contrib/extract-text-webpack-plugin:
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
//resolve-url-loader may be chained before sass-loader if necessary
use: ['css-loader', 'sass-loader']
})
}
]
},
plugins: [
new ExtractTextPlugin('style.css')
//if you want to pass in options, you can do so:
//new ExtractTextPlugin({
// filename: 'style.css'
//})
]
}
What is the purpose of the fallback option?
How I see this snippet to work is:
I instruct webpack to use the ExtractTextPlugin on every .scss file it encounter. I am telling ExtractTextPlugin to use ['css-loader', 'sass-loader'] loaders to generate the css. Webpack will then emit extra style.css file containing the css.
I can then reference this file in my index.html or if I am using html-webpack-plugin it will be added automatically to it.
I can remove the fallback: 'style-loader', option and everything continues to work.
What does it mean to fallback to style-loader?
How/When the fallback gets triggered?
I understand what style-loader is doing and how it is modifying the DOM with style tag if I am not using the ExtractTextPlugin. I just can't understand the fallback option when I am using ExtractTextPlugin.
Let's suppose we have a webpack config with:
entry: {
'pageA': './src/pageA',
'pageB': './src/pageB',
},
...
module: {
rules: [
...
{
test: /\.css$/,
exclude: helpers.root('src', 'app'),
loader: ExtractTextPlugin.extract({ fallbackLoader: 'style-loader', loader: 'css-loader?sourceMap' })
},
...
],
plugins: [
...
new CommonsChunkPlugin({
name: "commons",
chunks: ["pageA", "pageB"]
}),
new ExtractTextPlugin('[name].css')
...
]
}
which let's suppose would get some css into commons.js generated by CommonsChunkPlugin above.
When allChunks option used by new ExtractTextPlugin() is false (default) the output [name].css won't contain the css from commons.js so some css would remained loaded as javascript with commons.js (uuh, ugly). Now the fallbackLoader option would say "use the style-loader" meaning "add that css into a <style/> when loading commons.js in browser".
But you could better use allChunks = true for this case, this meaning to force new ExtractTextPlugin() to also collect (into the separate css file it creates) the css which otherwise would go into commons.js. In this case fallbackLoader option would become useless.

Converting gatsby project from css to scss, having issues with lost grid preprocessing

I'm taking a gatsby starter project that uses Lost grid and converting from css to scss for some gains. This is the starter project: https://github.com/wpioneer/gatsby-starter-lumen
Essentially, I'm converting the project to scss because I much prefer it's structure and would like to move away from all the css files. For now, I simply:
Installed sass-loader, scss, and node-sass
Renamed all the css files to scss files
And modified gatsby-node.js to the following:
var rucksack = require('rucksack-css')
var lost = require("lost")
var cssnext = require("postcss-cssnext")
exports.modifyWebpackConfig = function(config, env) {
config.merge({
postcss: [
lost(),
rucksack(),
cssnext({
browsers: ['>1%', 'last 2 versions']
})
]
})
config.loader('svg', {
test: /\.(svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'file-loader',
})
config.loader('sass', {
test: /\.scss$/,
loader: 'style-loader!css-loader!sass-loader',
})
return config
};
Unfortunately, while this does allow me to build and run the project using scss, I've noticed that my sweet Lost grid has disappeared. After investigation, I notice that .sidebar is still reading as lost-column: 1/3 in the browser (for example), so I can see that the preprocessing which is crucial for Lost grid didn't happen.
Honestly, this is probably an issue outside of Lost grid, and rather an issue with how I've constructed the gatsby-node.js, but I would appreciate any insight into what I'm missing. I don't mind uploading a scss/lost starter project for gatsby once this issue is resolved.
Solved.
In node_modules/gatsby/dist/utils/webpack.config.js, I changed
// CSS modules
config.loader('cssModules', {
test: /\.module\.css$/,
loaders: ['style', cssModulesConfDev, 'postcss']
});
config.loader('lessModules', {
test: /\.module\.less/,
loaders: ['style', cssModulesConfDev, 'less']
});
config.loader('sassModules', {
test: /\.module\.(sass|scss)/,
loaders: ['style', cssModulesConfDev, 'sass']
});
to:
// CSS modules
config.loader('lessModules', {
test: /\.module\.less/,
loaders: ['style', cssModulesConfDev, 'less']
});
config.loader('sassModules', {
test: /\.module\.(sass|scss)/,
loaders: ['style', cssModulesConfDev, 'sass']
});
config.loader('cssModules', {
test: /\.module\.css$/,
loaders: ['style', cssModulesConfDev, 'postcss']
});
I'll probably see what the gatsby folks see about making this change permanent.

Include bootstrap using webpack

I'm developping a chrome extension. I use boostrap 3 for the UI.
doctype html
html
head
meta(charset='UTF-8')
title (Boilerplate Popup)
link(rel="stylesheet", href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css")
style.
body { width: 500px; }
body
#root
script(src=env == 'prod' ? '/js/ext.bundle.js' : 'http://localhost:3000/js/ext.bundle.js')
Here is how I was used to include boostrap.
localhost:3000 is a server created with webpack web server.
At this point everything works well and here is a screenshot :
But I don't want my chrome extension to be network dependant, so I decided to download boostrap using :
npm install boostrap which have downloaded boostrap 3.
I also decided to use webpack to load boostrap.min.css.
module: {
loaders: [{
test: /\.js$/,
loader: 'babel',
exclude: /node_modules/,
query: {
presets: ['react-hmre']
}
}, {
test: /\.css$/,
loaders: [
'style',
'css?modules&sourceMap&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',
'postcss'
]
},
{test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/font-woff'},
{test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream'},
{test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file'},
{test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml'}]
}
I didn't change the css loader (which comes from a boilerplate) but I added the loader for the web font and svg.
Finally, I've included boostrap.min.css in the javascript entry point :
import 'bootstrap/dist/css/bootstrap.min.css';
Now, it's how my extension look like :
I think a part of boostrap is loaded (because the link in the second version looks like the same as the links in the first version. But obviously, the other components are not loaded.
I also use react-boostrap.
Thanks
My idea in the comments is right, css?module locally load boostrap. I changed the import with :
import '!style!css!bootstrap/dist/css/bootstrap.min.css';
and it works
For WEBPACK 2, (i.e. after all the necessary dependency installs) you can include bootstrap as follows:-
Add css loaders in webpack.config.js
{
test: /\.css$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
importLoaders: 1
}
}
]
}
Then, import bootstrap in the entry point script (i.e index.js or app.js, index.js in my project)
import '!style-loader!css-loader!bootstrap/dist/css/bootstrap.css';
Need details!!! More details here
npm install bootstrap ;
And :
Adjust css loader as following :
{
test: /\.css$/,
loaders: ['style', 'css'],
}
And, import bootstrap :
import Bootstrap from 'bootstrap/dist/css/bootstrap.css';

Categories

Resources