How to use absolute paths within a css-module to compose other classes instead of relative paths - css

I want to be able to have a folder in the root of my app "src" that contains reusable css which I can compose from in the css modules wi
In my css no my class has composes: table from './../../../css-vars/index.css'; but i am trying to just be able to use composes: table from 'css-vars/index.css'; and have it resolve to the root of my project. Currently when I try this i get this error:
Module not found: 'css-vars/index.css' in /Users/jfarina/Desktop/schedule-react/src/components/layout
Here is what my css loader looks like:
{
test: /\.css$/,
loaders: [
'style?sourceMap',
'css-loader?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]',
'postcss-loader'
]
},
Any idea?
I solved a similar problem with with postcss smart-import by adding a path with my source. Is there a similar solution with the css-loader? I noticed there is a root query param ter but adding that didn't help
smartImport({
addDependencyTo: webpack,
path: [ path.resolve(__dirname, 'src') ]
})

You can try postcss-modules-resolve-imports

Related

Angular custom webpack config enable CSS modules

I'm trying to apply CSS modules concept agains my angular app, to order embed it into existing frontend with CSS which unfortunately overlaps. My project uses scss, I want webpack "modulize" my CSS after CSS if formed from scss on last build step I think.
I want to use CSS loader of webpack to achieve this.
But I couldn't make it work.
https://www.npmjs.com/package/#angular-builders/custom-webpack
to order customize my webpack config.
I've tried to apply the next configuration
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: true,
},
},
],
},
};
and got this error
ERROR in Module build failed (from ./node_modules/postcss-loader/src/index.js):
SyntaxError
(1:1) Unknown word
> 1 | exports = module.exports = require("../../../../css-loader/dist/runtime/api.js")(false);
I've tried to find and add css loader into existing
module.exports = (config, options) => {
const rules = config.module.rules || [];
rules.forEach(rule => {
if (String(rule.test) === String(/\.css$/)) {
rule.use.push({ loader: 'css-loader', options: { modules: true }})
}
});
return config;
};
Getting the same error. How to make it work?
Update 1:
I found that angular uses postcss which also provides this functionality as a plugin, postcss-modules. Also still can't make it work.
I was able to implement CSS Modules in Angular with the help of #angular-builders/custom-webpack as you suggested.
However, my solution use postcss-modules and posthtml-css-modules instead of the css-loader to hash the styles.
postcss-modules hash all the styles, then posthtml-css-modules replaces the class names on the html files by the hashed class names.
I documented my solution here:
Live Demo: https://angular-css-modules.herokuapp.com/
Github Repo: https://github.com/gquinteros93/angular-css-modules
Article with the step by step: https://indepth.dev/angular-css-modules/
I hope it will be useful for you.

ExtractTextWebpackPlugin always outputs file, even if there are no changes

I have a project that bundles the client-side files using Webpack. We are bundling the CSS using the ExtractTextWebpackPlugin. The problem is when I edit a javascript file the CSS bundle always gets re-built despite there being absolutely no changes to the CSS state.
How can I bundle CSS but only when there are changes to the CSS files?
Extracted from my webpack config:
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: 'css-loader'
})
},
...
plugins: [
new ExtractTextPlugin(isDebug ? '[name].css' : '[name].[chunkhash].css')
],
whenever ExtractTextPlugin sees a import statement with css extension it will automatically extract the text contant of that css file whethere it changes or not
if you are using it to debug then use style-loader and HMR(Hot Module Replacement) for better experence something like this
isDebug
? {
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
: {
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: "css-loader"
})
}
if you want to use current configration and don't want ExtractTextPlugin to build css file and you are importing them in your javascript file using import then somehow you have to remove import statement for css files when there is no change in that css file
and if you are adding css file in your webpack config entry section then it would be easy because webpack allow custom command argument and you can do this by exporting a function in your webpack config file insted of object
//webpack.config.js
module.exports = function(env) {
return {
entry: {
main: env.includeCss
?
["./src/index.js", "./src/main.css"] //build with css
: ["./src/index.js"] //build without css
},
.
.
.
.
}
}
you can pass env.includeCss by command argument like this
webpack --config ./webpack.config.prod.js --env.includeCss
//notice --env.includeCss witch will set env.includeCss as true
run with --env.includeCss normally and without --env.includeCss when you dont want to compile css file
Not directly related to your question but I noticed you use [chunkhash] for extracted CSS. This will make your css name change even if you haven't change content in you CSS files.
Use [contenthash] instead.
https://survivejs.com/webpack/optimizing/adding-hashes-to-filenames/#setting-up-hashing
If you are using ExtractTextPlugin, you should use [contenthash]. This way the generated assets get invalidated only if their content changes.

Minify and add hash to css files webpack

I am using webpack for my Angular 2 project.
Inside the src folder I have a global css folder and component and other folders.
My webpack.config.js is outside the src folder.
I am using CopyWebpackPlugin to copy the css folder to the dist folder :
new CopyWebpackPlugin([
{ from: 'src/css', to: 'css'}
]),
I am using the following loader also for css :
exports.css = {
test: /\.css$/,
loader: 'to-string!css?-minimize!postcss',
};
But the deal is that I want to add a hash to each css file name and also then change the css file name in the index.html since these are global files included in the index.html. What is the best way to achieve this?
EDIT : While changing the code i realised that the loader property only applies to the css inside the components folder and not to the outside folder. why is this?
Use https://github.com/webpack/extract-text-webpack-plugin.
example in webpack.config.js
config.plugins.push(
new ExtractTextPlugin({filename: 'css/[name].[hash].css'})
);
...
config.module = {
rules: [
{
test: /\.css$/,
exclude: root('src', 'app'),
loader: ExtractTextPlugin.extract({ fallbackLoader: 'style-loader', loader: ['css', 'postcss']})
}
]
}
Do not use CopyWebpackPlugin for application sources. This will bypass Webpack's loaders and lock you out of all of Webpack's features.
Simply use ES6 imports, require, require.ensure or System.import to require your stylesheets. Alterantively, as MichaƂ suggested, use ExtractTextPlugin in production when applicable.

How to bundle Angular 2 component css?

In my application for angular 1 I used to bundle all of the css in library.css and application.css. While this can be done with angular 2 the same way for ordinary css, there is a new feature that allows a "component css". As far as I can see Angular just downloads the css file and then processes it to add some id's to not interfere with each other.
Now if I just bundle all of these css'es Angular just won't be able to find them. Is it possible at all to do bundling of component css? Perhaps a similar way to bundling HTML exists, where HTML is really put into .js as string?
I managed to achieve this with webpack and a special angular2-template-loader plugin. This is the config from webpack 2:
module: {
rules: [
{
test: /\.ts$/,
use: ['awesome-typescript-loader', 'angular2-template-loader']
}
Basically what it does, it replaces templateUrl and styleUrls with inline template and styles and just stores them in a string as a separate "module".
How does it work
The angular2-template-loader searches for templateUrl and styleUrls
declarations inside of the Angular 2 Component metadata and replaces
the paths with the corresponding require statement. If keepUrl=true is
added to the loader's query string, templateUrl and styleUrls will not
be replaced by template and style respectively so you can use a loader
like file-loader.
The generated require statements will be handled by the given loader
for .html and .js files.
P.S. The whole set up can be found in Anagular tutorial.
These are the combination of the loaders that does the trick if you have
templateUrls and styleUrls
loaders: [{
test: /\.ts$/,
loaders: ['awesome-typescript-loader', 'angular2-template-loader']
},
{
test: /\.html$/,
loader: 'raw-loader',
exclude: [root('src/index.html')]
},
{
test: /\.css$/,
loader: 'to-string-loader!css-loader'
}
],
and in the code
#Component({
selector: 'my-app',
templateUrl: 'sub.component.html',
styleUrls: ['app.component.css']
})
export class AppComponent {
}

extract-text-webpack-plugin to output css from scss in new folder in output

I can't seem to make extract-text-webpack-plugin generate the css from scss in a special folder in output. I know that there is a publicPath option but it doesn't seem to do anything. The css is still generated along with the other css's in my output folder.
can anyone help?
in my config:
test: /(add-to-home\.scss)$/,
loader: ExtractTextPlugin.extract("style","css!postcss!sass", {publicPath: "output/a/b"})
thanks
To output the your style.css file in "output/a/b"
You need to use the ExtractTextPlugin
{
test: /(\.scss|\.css)$/,
loader: ExtractTextPlugin.extract('style', 'css?postcss!sass'),
}
In the plugin section use :
plugins: [
new ExtractTextPlugin('output/a/b/style.css', {allChunks: true})
],
This will output the extracted css in the output/a/b/ folder.

Resources