无法导入CSS/SCSS模块.TypeScript说"找不到模块"

zak*_*ces 33 import sass typescript webpack css-modules

我正在尝试从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"
Run Code Online (Sandbox Code Playgroud)

这是我的 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: './'
  },
};
Run Code Online (Sandbox Code Playgroud)

以及我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;
Run Code Online (Sandbox Code Playgroud)

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

Gas*_*ass 70

正如@Kalle 提到的

\n
\n

TypeScript 不知道还有 .ts 或 .tsx 以外的文件,因此如果导入的文件后缀未知,\nit 将抛出错误。

\n
\n

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

\n

就像这样:

\n

在此输入图像描述

\n

关于.d.ts文件

\n
\n

TypeScript 有两种主要类型的文件。.ts文件是包含类型和可执行代码的实现文件。这些是\n生成的文件.js输出,并且是您\xe2\x80\x99d 通常编写代码的位置。

\n

.d.ts文件是仅包含类型信息的声明文件。\n这些文件不\xe2\x80\x99 产生.js输出;它们仅用于\n类型检查。

\n
\n

您可以在此处阅读有关 TS 声明的更多信息

\n


Kal*_*lle 53

TypeScript不知道存在除了.ts或之外的文件,.tsx如果导入具有未知文件后缀,它将引发错误.

如果您有一个允许导入其他类型文件的webpack配置,则必须告诉TypeScript编译器这些文件是否存在.为此,请添加一个声明文件,在其中声明具有拟合名称的模块.

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

// declaration.d.ts
declare module '*.scss';
Run Code Online (Sandbox Code Playgroud)

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

// declaration.d.ts
declare module '*.scss' {
    const content: {[className: string]: string};
    export default content;
}
Run Code Online (Sandbox Code Playgroud)

  • 请将 `declaration.d.ts` 包含到 tsconfig.json 文件中,如下所示`{ "include": ["./declaration.d.ts"] }` (20认同)
  • 嘿,这对我不起作用,最近发生了一些变化。/sf/ask/3959427041/ (4认同)
  • 供任何可能有帮助的人参考。对我来说,我必须将declaration.d.ts 文件放在项目根目录中。将其放在 tsconfig 文件中“types”下具有路径的子文件夹中对我来说不起作用。 (2认同)
  • @Etheryte 是的,你是对的,包括未定义的类型更接近现实,但这也对开发人员体验产生强烈影响,你必须选择妥协。 (2认同)

小智 24

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

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

    declare module "*.module.css";
    declare module "*.module.scss";
    
    Run Code Online (Sandbox Code Playgroud)
  2. “declaration.d.ts”添加到“include”tsconfig.json

    {
      "compilerOptions": {...},
      "include": ["src", "declaration.d.ts"],
    }
    
    Run Code Online (Sandbox Code Playgroud)

这将允许声明src也适用于该文件夹,而不仅仅是所在的root文件夹declarations.d.ts

您可以declaration.d.ts直接添加到直接导入样式的文件夹中,但这是一个坏主意。


小智 17

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

declare module "*.module.css";
Run Code Online (Sandbox Code Playgroud)

请记住使用 .css 来声明您的 css 文件.module.css

输入:

import styles from './styles.module.css'
Run Code Online (Sandbox Code Playgroud)

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


Rya*_*var 16

只需在您的项目中添加一个“declarations.d.ts”并添加以下行即可:

declare module '*.css';
Run Code Online (Sandbox Code Playgroud)


fre*_*evd 11

这是一个对我有用的完整配置(我只是花了一个小时痛苦的反复试验,以防有人遇到相同的问题):

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
            ] }, 

        ]
    }
}; 
Run Code Online (Sandbox Code Playgroud)

还要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'; 
Run Code Online (Sandbox Code Playgroud)

您将在package.jsondev-dependencies中需要所有这些:

  "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"
  }
Run Code Online (Sandbox Code Playgroud)

然后,您应该mystyle.d.tsmystyle.scss包含您定义的CSS类的旁边,您可以将其作为Typescript模块导入并像这样使用:

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

const foo = <div className={styles.myClass}>FOO</div>; 
Run Code Online (Sandbox Code Playgroud)

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

请注意,无论何时添加CSS类或删除它们或重命名它们,第一次编译都会失败,因为导入的mystyles.d.ts是旧版本,而不是编译期间刚刚生成的新版本。只是再次编译。

请享用。

  • @JonLauridsen,可以通过在 webpack.config.js 规则数组的底部(末尾)设置 ts-loader 来解决。因此 ts-loader 将在每次编译时拾取正确的 *.scss.d.ts 文件,因为它们之前会生成。 (4认同)
  • @YanPak 谢谢,将 `global.d.ts` 添加到我的 `src` 目录中,并将 ts-loader 移动到样式加载器下方,为我解决了这个问题。 (2认同)

小智 9

上面的答案对我来说不起作用,我正在研究 scss + TS + React。我所做的是:

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

declare module "*.scss" {
  const content: { [className: string]: string };
  export = content;
}
Run Code Online (Sandbox Code Playgroud)

然后在 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"]
}
Run Code Online (Sandbox Code Playgroud)

然后最后安装插件为

npm i typescript-plugin-css-modules
Run Code Online (Sandbox Code Playgroud)

成功了!


小智 7

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

npm install -D typescript-plugin-css-modules

配置文件

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

Run Code Online (Sandbox Code Playgroud)

  • 对我不起作用(( (3认同)

sla*_*ris 7

根据 @Kalle 提供的答案,我还发现我需要使声明类型在includetsconfig 选项中可发现:

"include": ["./src/**/*.tsx", "./src/**/*.ts", "./typings/*.ts"]
Run Code Online (Sandbox Code Playgroud)

包含@Kalle 的答案中看到的文件typingsdeclaration.d.ts


小智 6

如果您使用 tsconfig.json 路径设置,请注意

请注意,如果您将这些解决方案与 tsconfig 路径结合使用以缩短导入,您将需要额外的配置。

如果您碰巧使用这样的路径 tsconfig:

{
  "compilerOptions": {
    "paths": {
      "style/*": [ "src/style/*" ],
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

所以你可以这样做:

{
  "compilerOptions": {
    "paths": {
      "style/*": [ "src/style/*" ],
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后你还需要在你的 webpack 上添加一个模块解析配置,如下所示:

import { header } from 'style/ui.scss';
Run Code Online (Sandbox Code Playgroud)

确保根据您的设置设置路径。

这使得 webpack 知道在哪里查找,因为它认为新的导入路径实际上是一个模块,因此它默认为 node_modules 目录。使用此配置,它知道在哪里查找并找到它并且构建工作。


Ger*_*tas 6

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

declare module "*.module.css";
Run Code Online (Sandbox Code Playgroud)

并记住使用“模块”声明您的 css 文件。例如 styles.module.css

输入:

import React from 'react';
import styles from './styles.module.css'
Run Code Online (Sandbox Code Playgroud)

  • `typings.d.ts` 需要位于 `src` 文件夹或下面的某个位置。如果您使用 SASS,也不要忘记添加 `declare module "*.module.scss";` (11认同)
  • 仅添加 `typings.d.ts` 文件有效 (3认同)