Reputation: 3302
How to import CSS modules in Typescript with Webpack?
Generate (or auto-generate) .d.ts
files for CSS? And use classic Typescript import
statement? With ./styles.css.d.ts
:
import * as styles from './styles.css'
Import using require
Webpack function?
let styles = require("./styles.css");
But for the last approach I must define the require
function.
What is the best approach or best option and one that can also handle IntelliSense for the CSS file definitions and classes?
Upvotes: 120
Views: 229030
Reputation: 1
I was trying to find the reason why after webpack and other dependency updates types are not generating and I figured out that css-loader api changed and no loaders for making typescript definitions for styles found, then I create an own package.
"style-loader",
{
loader: require.resolve("css-modules-dts-loader"),
options: {
camelCase: true,
quote: "double",
indentStyle: "space",
indentSize: 4,
sort: true,
mode: isProduction ? "verify" : "emit"
}
},
{
loader: require.resolve("css-loader"),
options: {
sourceMap: true,
modules: {
exportLocalsConvention: "as-is",
localIdentName: "[name]__[local]___[hash:base64]"
},
importLoaders: 1
}
}
css-loader migration steps:
replace all import styles from "..."
with import * as styles from "..."
Upvotes: 0
Reputation: 61
"css-loader": "^7.1.1" has a bug!?!?!
1. if after installing css-loader
2. added a flag
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: true,
},
}
created a file global.d.ts
made an entry declare module "*.module.css";
but this entry doesn't work
import s from "./Main.module.css";
and this is the only one that works
import * as s from "./Main.module.css";
in my case, installing css-loader of an earlier version helped, for example npm i -D [email protected]
Edited
{
loader: "css-loader",
options: {
modules: {
...,
namedExport: false,
exportLocalsConvention: 'as-is',
...
},
},
}
Upvotes: 6
Reputation: 61
globals.d.ts
file under the src
declare module '*.scss'
import styles from './App.module.scss'
package.json
npm i mini-css-extract-plugin
webpack.config.ts
{
test: /\.(sa|sc|c)ss$/i,
use: [
devMode
? "style-loader"
: MiniCssExtractPlugin.loader,
"css-loader",
options: {
loader: 'css-loader',
modules: true,
},
"sass-loader",
],
}
Upvotes: 6
Reputation: 3529
I use create-react-app
, but for some reason other solutions didn't work, something was missing; I think it's because VS Code
uses its own TypeScript
vesrion. So here is all I did until it finally worked; if you use create-react-app
& VS Code
it should work for you as well:
npm i typescript-plugin-css-modules --save-dev
styles.d.ts
(or
something like this) and paste the following content:styles.d.ts
// if you use css
declare module "*.module.css" {
const classes: { [key: string]: string };
export default classes;
}
// if you use scss
declare module "*.module.scss" {
const classes: { [key: string]: string };
export default classes;
}
// if you use less
declare module "*.module.less" {
const classes: { [key: string]: string };
export default classes;
}
.vscode/settings.json
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
So, the file might look like so:
.vscode/settings.json
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}
Upvotes: 4
Reputation: 1628
In 2022, all I needed to do it to add Globals.d.ts
file under the src
folder
with
declare module "*.module.css";
declare module "*.module.scss";
Then I can import CSS modules in my typescript files as usual for css or scss files:
import styles from "./Team.module.scss";
Upvotes: 28
Reputation: 12443
Now in the year 2021, all you need to do is add a src/Globals.d.ts
to your project with these lines:
declare module "*.module.css";
declare module "*.module.scss";
// and so on for whatever flavor of css you're using
Then install and add
{
"compilerOptions": {
"plugins": [{ "name": "typescript-plugin-css-modules" }]
}
}
to your tsconfig.
Example of this correctly functioning in VS code after making that simple change (root is a class defined in my stylesheet):
Webpack and tsc also compile correctly on the command line.
Upvotes: 111
Reputation: 911
This case is related to Typescript. You can add typings.d.ts
in your project with this content:
declare module "*.module.css";
declare module "*.module.scss";
It is good practice to use file name with *.module.*
format if you want to enable CSS Module.
css-loader
will enable CSS Module automatically for files with name that satisfy this RegEx: /\.module\.\w+$/i
. This feature is customable by setting options.modules
property as an object.
For example:
import style from './App.module.css'; // CSS Module enabled
import './index.css'; // Plain CSS loaded
For recent configuration, you can add this rule to webpack.config.js
:
{
test: /\.css$/,
use: [
'style-loader',
{
loader: "css-loader",
options: {
modules: {
localIdentName: "[hash:base64]", // default
auto: true // default
},
sourceMap: true
}
},
]
},
A custom configuration example:
{
loader: "css-loader",
options: {
modules: {
localIdentName: "[name]_[local]_[hash:base64]", // custom class name format
auto: /\.cmod\.\w+$/i, // custom auto enable CSS Module for "*.cmod.css" format
},
}
},
Complete documentation is HERE.
Upvotes: 2
Reputation: 149
I think now typescript can import css file by simply doing import 'fileTobeImportedPath.css'
Upvotes: 2
Reputation: 6832
I have added a file named Global.d.ts
or typings.d.ts
to my ./src
folder with some type definitions:
declare module "*.module.css";
Webpack css config:
{
test: /\.css$/,
use: [
isProductionBuild ? MiniCssExtractPlugin.loader : "style-loader",
{
loader: "css-loader",
options: {
modules: true,
importLoaders: 1,
localIdentName: "[name]_[local]_[hash:base64]",
sourceMap: true,
minimize: true
}
}
]
},
Then I simply import the module like: import styles from "./App.module.css";
Upvotes: 37
Reputation: 275987
Or import using require webpack function
This is just what I used to do and still have that code in a few of my projects out there.
Now : I wrote typestyle : http://typestyle.github.io/#/ but you don't have to use it. Just stick with const styles = require('./styles.css')
if it makes you happy. FWIW you can also use raw css with typestyle if you want http://typestyle.github.io/#/raw
Upvotes: 3
Reputation: 7767
A) As you are saying, there is one simplest (not best) option to use require:
const css = require('./component.css')
require
as it's not standard feature in typescript.Simplest typing for this specific require may be:
declare function require(name: string): string;
Webpack will then compile typescript and use modules properly - BUT without any IDE help and class names checks for build.
B) There is better solution to use standard import:
import * as css from './component.css'
tsc
compiler will failFor proper IntelliSense, Webpack needs to generate types definition for each css file:
Use webpack typings-for-css-modules-loader
webpackConfig.module.loaders: [
{ test: /\.css$/, loader: 'typings-for-css-modules?modules' }
{ test: /\.scss$/, loader: 'typings-for-css-modules?modules&sass' }
];
Loader will generate *.css.d.ts
files for each of css files in your codebase
Mentioned typings-for-css-loader
contains a bug and because of types file generation delay, it's best to declare global *.css
type in case our *.css.d.ts
file is not generated yet.
That little bug scenario:
component.css
import * as css from './component.css'
webpack
component.css.d.ts
), but it's late for typescript compiler to find new typings filewebpack
again will fix build error.Easy fix is to create global definition (eg. file called typings.d.ts
in your source root) for importing CSS Modules:
declare module '*.css' {
interface IClassNames {
[className: string]: string
}
const classNames: IClassNames;
export = classNames;
}
This definition will be used if there is no css file generated (eg. you have added new css file). Otherwise will be used generated specific (needs to be in same folder and named same as source file + .d.ts
extension), eg. component.css.d.ts
definition and IntelliSense will work perfectly.
Example of component.css.d.ts
:
export const wrapper: string;
export const button: string;
export const link: string;
And if you don't want to see generated css typings you may setup filter in IDE to hide all files with extension .css.d.ts in your sources.
Upvotes: 62
Reputation: 3384
let styles = require("./styles.css");
is the best approch because it is es5 version of javascript which is compatible with every feature of react.import * as styles from './styles.css'
is es6 version of javascript.
Upvotes: -12