简体   繁体   English

如何使用 Typescript、React 和 Webpack 导入 CSS 模块

[英]How to import CSS modules with Typescript, React and Webpack

How to import CSS modules in Typescript with Webpack?如何使用 Webpack 在 Typescript 中导入 CSS 模块?

  1. Generate (or auto-generate) .d.ts files for CSS?为 CSS 生成(或自动生成) .d.ts文件? And use classic Typescript import statement?并使用经典的 Typescript import语句? With ./styles.css.d.ts :使用./styles.css.d.ts

     import * as styles from './styles.css'
  2. Import using require Webpack function?使用require Webpack 功能导入?

     let styles = require("./styles.css");

But for the last approach I must define the require function.但对于最后一种方法,我必须定义require函数。

What is the best approach or best option and one that can also handle IntelliSense for the CSS file definitions and classes?最好的方法或最佳选择是什么,并且还可以处理 CSS 文件定义和类的 IntelliSense?

A) As you are saying, there is one simplest (not best) option to use require : A)正如您所说,有一个最简单(不是最好)的选项可以使用require

const css = require('./component.css')
  • We need to have typings for require as it's not standard feature in typescript.我们需要对require进行打字,因为它不是打字稿中的标准功能。
  • 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 .然后 Webpack 将编译打字稿并正确使用模块 -但没有任何 IDE 帮助和类名检查 build

B) There is better solution to use standard import : B) 使用标准导入有更好的解决方案:

import * as css from './component.css'
  • enables full class names IntelliSense启用完整的类名 IntelliSense
  • requires types definition for each css file, otherwise tsc compiler will fail需要为每个 css 文件定义类型,否则tsc编译器将失败

For proper IntelliSense, Webpack needs to generate types definition for each css file:为了正确的 IntelliSense,Webpack 需要为每个 css 文件生成类型定义:

  1. Use webpack typings-for-css-modules-loader使用 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' } ];
  2. Loader will generate *.css.d.ts files for each of css files in your codebase Loader 将为代码库中的每个 css 文件生成*.css.d.ts文件

  3. Typescript compiler will understand that css import will be module with properties (class names) of type string. Typescript 编译器将理解 css 导入将是具有字符串类型的属性(类名)的模块。

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.提到的typings-for-css-loader包含一个错误,由于类型文件生成延迟,最好声明全局*.css类型,以防我们的*.css.d.ts文件尚未生成。

That little bug scenario:那个小错误场景:

  1. Create css file component.css创建 css 文件component.css
  2. Include it in component import * as css from './component.css'将它包含在组件import * as css from './component.css'
  3. Run webpack运行webpack
  4. Typescript compiler will try to compile code (ERROR) Typescript 编译器将尝试编译代码(错误)
  5. Loader will generate Css modules typings file ( component.css.d.ts ), but it's late for typescript compiler to find new typings file加载器会生成 Css 模块类型文件( component.css.d.ts ),但是打字稿编译器找到新的类型文件已经晚了
  6. Run webpack again will fix build error.再次运行webpack将修复构建错误。

Easy fix is to create global definition (eg. file called typings.d.ts in your source root) for importing CSS Modules:简单的解决方法是为导入 CSS 模块创建全局定义(例如,在源根目录中名为typings.d.ts文件):

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).如果没有生成 css 文件(例如,您添加了新的 css 文件),将使用此定义。 Otherwise will be used generated specific (needs to be in same folder and named same as source file + .d.ts extension) , eg.否则将使用生成的特定(需要在同一文件夹中并与源文件+ .d.ts扩展名相同) ,例如。 component.css.d.ts definition and IntelliSense will work perfectly. component.css.d.ts定义和 IntelliSense 将完美运行。

Example of component.css.d.ts : 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.如果您不想看到生成的 css 类型,您可以在 IDE 中设置过滤器以隐藏源中扩展名为 .css.d.ts 的所有文件。

I have added a file named Global.d.ts or typings.d.ts to my ./src folder with some type definitions:我添加了一个名为Global.d.tstypings.d.ts./src一些类型定义文件夹:

declare module "*.module.css";

Webpack css config: Webpack css 配置:

{
  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";然后我简单地导入模块,如: import styles from "./App.module.css";

Now in the year 2021, all you need to do is add a src/Globals.d.ts to your project with these lines:现在是 2021 年,您需要做的就是使用以下src/Globals.d.ts添加到您的项目中:

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.到您的 tsconfig。

Example of this correctly functioning in VS code after making that simple change (root is a class defined in my stylesheet):进行简单更改后在 VS 代码中正确运行的示例(root 是我的样式表中定义的类):

在此处输入图片说明

Webpack and tsc also compile correctly on the command line. Webpack 和 tsc 也可以在命令行上正确编译。

In 2022, all I needed to do it to add Globals.d.ts file under the src folder在 2022 年,我需要做的就是在src文件夹下添加Globals.d.ts文件
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:然后我可以像往常一样为 css 或 scss 文件在我的打字稿文件中导入 CSS 模块:

import styles from "./Team.module.scss";

Or import using require webpack function或者使用 require webpack 函数导入

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.现在:我写了 typestyle : http ://typestyle.github.io/#/ 但你不必使用它。 Just stick with const styles = require('./styles.css') if it makes you happy.如果它让你开心,就坚持使用const styles = require('./styles.css') FWIW you can also use raw css with typestyle if you want http://typestyle.github.io/#/raw FWIW 如果你想要http://typestyle.github.io/#/raw,你也可以使用带有 typestyle 的原始 css

我认为现在打字稿可以通过简单地执行 import 'fileTobeImportedPath.css' 来导入 css 文件

This case is related to Typescript.此案例与 Typescript 相关。 You can add typings.d.ts in your project with this content:您可以使用以下内容在项目中添加typings.d.ts

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 模块,最好使用带有*.module.*格式的文件名。

css-loader will enable CSS Module automatically for files with name that satisfy this RegEx: /\\.module\\.\\w+$/i . css-loader将自动为名称满足此正则表达式的文件启用 CSS 模块: /\\.module\\.\\w+$/i This feature is customable by setting options.modules property as an object.此功能可通过将options.modules属性设置为对象来定制。

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 :对于最近的配置,您可以将此规则添加到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 .完整的文档在这里

I use create-react-app , but for some reason other solutions didn't work, something was missing;我使用create-react-app ,但由于某种原因其他解决方案不起作用,缺少了一些东西; I think it's because VS Code uses its own TypeScript vesrion.我认为这是因为VS Code使用了自己的TypeScript版本。 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:如果您使用create-react-appVS Code ,它也应该适用于您:

  1. run npm i typescript-plugin-css-modules --save-dev运行npm i typescript-plugin-css-modules --save-dev
  2. in the project's root folder, create a file named styles.d.ts (or something like this) and paste the following content:在项目的根文件夹中,创建一个名为styles.d.ts (或类似名称)的文件并粘贴以下内容:

styles.d.ts样式.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;
}
  1. in.vscode/settings.json (create the file if you don't already have it) - add the below fields: in.vscode/settings.json(如果您还没有文件,请创建它)- 添加以下字段:

.vscode/settings.json .vscode/settings.json

"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true

So, the file might look like so:因此,该文件可能如下所示:

.vscode/settings.json .vscode/settings.json

{
   "typescript.tsdk": "node_modules/typescript/lib",
   "typescript.enablePromptUseWorkspaceTsdk": true
}

let styles = require("./styles.css"); is the best approch because it is es5 version of javascript which is compatible with every feature of react.是最好的方法,因为它是 es5 版本的 javascript,与 react 的每个功能兼容。 import * as styles from './styles.css' is es6 version of javascript. import * as styles from './styles.css'是 es6 版本的 javascript。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM