This loader is a fork of the well-known loader typings-for-css-modules-loader
The purpose of creating yet another typescript generation loader for css-modules is the ability to use it in an isomorphic application in conjunction with style-loader/usable(is used in browser to use or unse component's stylesheets) and fake-style-loader(is used on server side to get source css from component's stylesheet).
style-loader/usable
adds 2 methods to the css-modules interface:
use: Function
unuse: Function
fake-style-loader
adds properties to the css-modules interface:
source: String
- all classnames into default exported object
Install via npm npm install --save-dev @budarin/ts-css-loader
All options are available only when the parameter modules
set to true
(see options for css-loader)
Name | Type | Default | Description |
---|---|---|---|
EOL |
{String} |
CRLF |
{'CRLF', 'LF'} |
onlyNamedExport |
{Boolean} |
false |
Export only named items of interface |
browser |
{Boolean} |
false |
Add use and unuse methods to interface and all classnames in flat view |
server |
{Boolean} |
false |
Add source property to interface |
tabWidth |
{Number} |
4 | Set tabWidth for indentation |
silent |
{Boolean} |
false |
To silence the loader |
banner |
{Boolean} |
false |
Adds a "banner" prefix to each generated *.d.ts |
the other parameters are the same as the css-loader
:
This loader should be used instead of` css-loader ' because inside it uses it.
An example of using webpack.config:
test: /\.css$/,
use: [
{
loader: 'style-loader',
},
{
loader: '@budarin/ts-css-loader',
options: {
modules: true,
},
}
]
for style file app.css
:
.foo {
color: red;
}
the loader will generate a type definition:
declare interface IAppCss {
readonly foo: string;
}
declare const styles: IAppCss;
export default styles;
Default: 'CRLF'
.
Defines a line separator in type definition file and must be equal to the parameter set in git
to prevent constant overwriting of type definition file.
This parameter can take one of these acronims {'CRLF','LF
}'
test: /\.css$/,
use: [
{
loader: 'style-loader',
},
{
loader: '@budarin/ts-css-loader',
options: {
modules: true,
EOL: 'LF'
}
}
]
Default: false
.
This parameter determines whether only named exports are present in the module interface
test: /\.css$/,
use: [
{
loader: 'style-loader',
},
{
loader: '@budarin/ts-css-loader',
options: {
modules: true,
onlyNamedExport: true
}
}
]
output:
export const foo: string;
Default: false
.
The parameter determines the presence of style-loader/disable
methods in the interface: use
and unuse
.
test: /\.css$/,
use: [
{
loader: 'style-loader/usable',
},
{
loader: '@budarin/ts-css-loader',
options: {
modules: true,
browser: true
}
}
]
output:
declare interface IAppCss {
readonly locals: {
readonly foo: string;
};
readonly use: Function;
readonly unuse: Function;
}
declare const styles: IAppCss;
export default styles;
Default: false
.
Determines the presence of the interface property source: string
for fake-style-loader
and presene all css classes in default export
test: /\.css$/,
use: [
{
loader: 'fake-style-loader',
},
{
loader: '@budarin/ts-css-loader',
options: {
modules: true,
server: true
}
}
]
output:
declare interface IAppCss {
readonly foo: string;
readonly source: string;
}
declare const styles: IAppCss;
export default styles;
Default: 4.
Number of spaces it should use per tab
Default: false
.
To silence the loader because you get annoyed by its warnings or for other reasons, you can simply pass the "silent" query to the loader and it will shut up. e.g.:
test: /\.css$/,
use: [
{
loader: 'style-loader',
},
{
loader: '@budarin/ts-css-loader',
options: {
modules: false,
}
}
]
Default: false
..
To add a "banner" prefix to each generated *.d.ts
file, you can pass a string to this option as shown below. The prefix is quite literally prefixed into the generated file, so please ensure it conforms to the type definition syntax.
test: /\.css$/,
use: [
{
loader: 'style-loader',
},
{
loader: '@budarin/ts-css-loader',
options: {
modules: true,
banner: "// This file is automatically generated file.\n// Please do not change this file!"
}
}
]
output:
// This file is automatically generated file
// Please do not change this file!"
declare interface IAppCss {
readonly locals: {
readonly foo: string;
};
}
declare const styles: IAppCss;
export default styles;
For isomorphic applications, you can use the following configuration:
test: /\.css$/,
use: [
{
loader: ...
},
{
loader: '@budarin/ts-css-loader',
options: {
modules: true,
browser: true,
server: true
}
}
]
output:
declare interface IAppCss {
readonly locals: {
readonly foo: string;
};
readonly use: Function;
readonly unuse: Function;
readonly source: string;
}
declare const styles: IAppCss;
export default styles;
Using the onlyNamedExport
as well as the camelCase
options the generated file will look as follow:
export const someClass: string;
export const someOtherClass: string;
export const someClassSayWhat: string;
If you encounter the following errors:
error TS1192: Module '"xxxxx/xxxx/src/style.sass"' has no default export.
maybe you should export the styles as following:
import * as styles from './style.sass';
As the loader just acts as an intermediary it can handle all kind of css preprocessors (sass
, scss
, stylus
, less
, ...).
The only requirement is that those preprocessors have proper webpack loaders defined - meaning they can already be loaded by webpack anyways.
The loader uses css-loader
(https://github.com/webpack/css-loader) under the hood. Thus it is a peer-dependency and the expected loader to create CSS Modules.
As the loader generates typing files, it is wise to tell webpack to ignore them. The fix is luckily very simple. Webpack ships with a "WatchIgnorePlugin" out of the box. Simply add this to your webpack plugins:
plugins: [
new webpack.WatchIgnorePlugin([
/css\.d\.ts$/
]),
...
]
where css
is the file extension of your style files. If you use sass
you need to put sass
here instead. If you use less
, stylus
or any other style language use their file ending.
As the webpack process is independent from your typescript "runtime" it may take a while for typescript to pick up the typings. Any hints on how this could be fixed deterministically are welcome!