网站搜索

无法导入 CSS/SCSS 模块。TypeScript 显示“找不到模块”


我正在尝试从一个 CSS 模块导入主题,但 TypeScript 给我一个“找不到模块”的错误,并且主题在运行时没有应用。我认为我的 Webpack 配置有问题,但我不确定问题出在哪里。

我正在使用以下工具:

"typescript": "^2.0.3"
"webpack": "2.1.0-beta.25"
"webpack-dev-server": "^2.1.0-beta.9"
"react": "^15.4.0-rc.4"
"react-toolbox": "^1.2.3"
"node-sass": "^3.10.1"
"style-loader": "^0.13.1"
"css-loader": "^0.25.0"
"sass-loader": "^4.0.2"
"sass-lint": "^1.9.1"
"sasslint-webpack-plugin": "^1.0.4"

这是我的 webpack.config.js

var path = require('path');
var webpack = require('webpack');
var sassLintPlugin = require('sasslint-webpack-plugin');

module.exports = {
  entry: [
    'webpack-dev-server/client?http://localhost:8080',
    'webpack/hot/dev-server',
    './src/index.tsx',
  ],
  output: {
    path: path.resolve(__dirname, 'dist'),
    publicPath: 'http://localhost:8080/',
    filename: 'dist/bundle.js',
  },
  devtool: 'source-map',
  resolve: {
    extensions: ['.webpack.js', '.web.js', '.ts', '.tsx', '.js'],
  },
  module: {
    rules: [{
      test: /\.js$/,
      loader: 'source-map-loader',
      exclude: /node_modules/,
      enforce: 'pre',
    }, {
      test: /\.tsx?$/,
      loader: 'tslint-loader',
      exclude: /node_modules/,
      enforce: 'pre',
    }, {
      test: /\.tsx?$/,
      loaders: [
        'react-hot-loader/webpack',
        'awesome-typescript-loader',
      ],
      exclude: /node_modules/,
    }, {
      test: /\.scss$/,
      loaders: ['style', 'css', 'sass']
    }, {
      test: /\.css$/,
      loaders: ['style', 'css']
    }],
  },
  externals: {
    'react': 'React',
    'react-dom': 'ReactDOM'
  },
  plugins: [
    new sassLintPlugin({
      glob: 'src/**/*.s?(a|c)ss',
      ignoreFiles: ['src/normalize.scss'],
      failOnWarning: false, // Do it.
    }),
    new webpack.HotModuleReplacementPlugin(),
  ],
  devServer: {
    contentBase: './'
  },
};

以及我在尝试导入的 App.tsx:

import * as React from 'react';

import { AppBar } from 'react-toolbox';
import appBarTheme from 'react-toolbox/components/app_bar/theme.scss'
// local ./theme.scss stylesheets aren't found either 

interface IAppStateProps {
  // No props yet
}

interface IAppDispatchProps {
  // No state yet
}

class App extends React.Component<IAppStateProps & IAppDispatchProps, any> {

  constructor(props: IAppStateProps & IAppDispatchProps) {
    super(props);
  }

  public render() {
    return (

        <div className='wrapper'>
          <AppBar title='My App Bar' theme={appBarTheme}>
          </AppBar>
        </div>

    );
  }
}

export default App;

启用类型安全的样式表模块导入还需要什么?

答案#1

TypeScript 不知道除了 .ts 或 .tsx 之外还有其他文件,所以如果导入的文件有未知的后缀,它会抛出错误。

如果你有一个允许你导入其他类型文件的 webpack 配置,你必须告诉 TypeScript 编译器这些文件存在。为此,你需要添加一个声明文件,在其中声明具有合适名称的模块。

要声明的模块内容取决于用于该文件类型的 webpack 加载器。在将 *.scss 文件通过 sass-loader → css-loader → style-loader 管道处理的 webpack 配置中,导入的模块将没有内容,正确的模块声明如下所示:

// declaration.d.ts
declare module '*.scss';

如果加载器配置为 css-modules,只需像这样扩展声明:

// declaration.d.ts
declare module '*.scss' {
    const content: Record<string, string>;
    export default content;
}

答案#2

只需添加包含以下内容的文件 typings.d.ts :

declare module "*.module.css";

并且记得用 'module' 来声明你的 CSS 文件。例如 styles.module.css

导入:

import React from 'react';
import styles from './styles.module.css';

答案#3

这是一个对我来说完全可行的配置(我刚花了一个小时痛苦的反复尝试——以防有人遇到同样的问题):

TypeScript + WebPack + Sass

webpack.config.js
module.exports = {
  //mode: "production", 
    mode: "development", devtool: "inline-source-map",

    entry: [ "./src/app.tsx"/*main*/ ], 
    output: {
        filename: "./bundle.js"  // in /dist
    },
    resolve: {
        // Add `.ts` and `.tsx` as a resolvable extension.
        extensions: [".ts", ".tsx", ".js", ".css", ".scss"]
    },
    module: {
        rules: [

            { test: /\.tsx?$/, loader: "ts-loader" }, 

            { test: /\.scss$/, use: [ 
                { loader: "style-loader" },  // to inject the result into the DOM as a style block
                { loader: "css-modules-typescript-loader"},  // to generate a .d.ts module next to the .scss file (also requires a declaration.d.ts with "declare modules '*.scss';" in it to tell TypeScript that "import styles from './styles.scss';" means to load the module "./styles.scss.d.td")
                { loader: "css-loader", options: { modules: true } },  // to convert the resulting CSS to Javascript to be bundled (modules:true to rename CSS classes in output to cryptic identifiers, except if wrapped in a :global(...) pseudo class)
                { loader: "sass-loader" },  // to convert SASS to CSS
                // NOTE: The first build after adding/removing/renaming CSS classes fails, since the newly generated .d.ts typescript module is picked up only later
            ] }, 

        ]
    }
}; 

还要在你的项目中放置一个 declarations.d.ts:

// We need to tell TypeScript that when we write "import styles from './styles.scss' we mean to load a module (to look for a './styles.scss.d.ts'). 
declare module '*.scss'; 

你将需要在你的 package.json 的开发依赖中包含所有这些:

  "devDependencies": {
    "@types/node-sass": "^4.11.0",
    "node-sass": "^4.12.0",
    "css-loader": "^1.0.0",
    "css-modules-typescript-loader": "^2.0.1",
    "sass-loader": "^7.1.0",
    "style-loader": "^0.23.1",
    "ts-loader": "^5.3.3",
    "typescript": "^3.4.4",
    "webpack": "^4.30.0",
    "webpack-cli": "^3.3.0"
  }

然后你应该在你的 mystyle.scss 旁边得到一个 mystyle.d.ts,其中包含你定义的 CSS 类,你可以将其作为 TypeScript 模块导入并像这样使用:

import * as styles from './mystyles.scss'; 

const foo = <div className={styles.myClass}>FOO</div>; 

CSS 将自动加载(作为 style 元素注入到 DOM 中)并在 .scss 中包含神秘的标识符,而不是你的 CSS 类,以便在页面中隔离你的样式(除非你使用 :global(.a-global-class) { ... })。

请注意,每当您添加、删除或重命名 CSS 类时,第一次编译会失败,因为导入的 mystyles.d.ts 是旧版本,而不是在编译过程中刚生成的新版本。只需再次编译即可。

享受吧。

答案#4

正如@Kalle所提到的

TypeScript 不知道除了 .ts 或 .tsx 之外还有其他文件,因此如果导入了未知的文件后缀,它会抛出错误。

为了避免 TS 显示此错误,我的方法是创建一个 types 文件夹,并在里面添加一个 .d.ts 扩展名的文件,其中包含声明。

像这样:

关于 .d.ts 文件

TypeScript 有两种主要的文件类型。.ts 文件是实现文件,包含类型和可执行代码。这些文件会生成 .js 输出,也是你通常编写代码的地方。

.d.ts 文件是只包含类型信息的声明文件。这些文件不会生成 .js 输出;它们仅用于类型检查。

你可以在这里阅读更多关于 TS 声明的内容

答案#5

我正在使用 typescript-plugin-css-modules

npm install -D typescript-plugin-css-modules

tsconfig.json

{
  "compilerOptions": {
    "plugins": [{ "name": "typescript-plugin-css-modules" }]
  }
}

答案#6

这对我有效(我正在使用 Typescript + vite)。

  1. 将此添加到项目根文件夹中的 declaration.d.ts 文件

    declare module "*.module.css";
    declare module "*.module.scss";
    
  2. 将 "declaration.d.ts" 添加到 "include" 中的 tsconfig.json。

    {
      "compilerOptions": {...},
      "include": ["src", "declaration.d.ts"],
    }
    

这将允许声明在 src 文件夹中生效,而不仅仅是在 declarations.d.ts 所在的 root 文件夹中。

你可以直接在你直接导入样式的文件夹中添加 declaration.d.ts,但这是一个非常糟糕的主意。

答案#7

只需添加包含以下内容的 declaration.d.ts 文件:

declare module "*.module.css";

记得将你的 CSS 文件声明为 .module.css。

导入:

import styles from './styles.module.css'

如果使用 Sass,请将 .css 语句替换为 .scss。

答案#8

只需在你的项目中放置一个 "declarations.d.ts" 文件,并在其中添加以下行:

declare module '*.css';

答案#9

以上的答案对我没有用,而且我当时在使用 scss + TS + React。我做的是:

在 src 文件夹中创建一个 declarations.d.ts 文件,并在其中添加以下代码

declare module "*.scss" {
  const content: { [className: string]: string };
  export = content;
}

然后在 src 文件夹中创建了一个 tsconfig.json 文件,并添加了以下代码

{
  "compilerOptions": {
     // In anticipation of installing the plugin
    "plugins": [{ "name": "typescript-plugin-css-modules" }]
  },
  // Include source directories and declarations
  "include": ["src/**/*.ts", "declarations.d.ts"]
}

然后最终安装插件为

npm i typescript-plugin-css-modules

而且它成功了!

相关文章