ค้นหาเว็บไซต์

ไม่สามารถนำเข้าโมดูล 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 ที่ใช้กับประเภทไฟล์ ในการตั้งค่า webpack ซึ่งส่งไฟล์ *.scss ผ่าน sass-loader → css-loader → style-loader จะไม่มีเนื้อหาในโมดูลที่นำเข้า และการประกาศโมดูลที่ถูกต้องจะมีลักษณะดังนี้:

// 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";

และอย่าลืมประกาศไฟล์ css ของคุณด้วย 'module' ตัวอย่างเช่น 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'; 

และคุณจะต้องมีทั้งหมดนี้ใน dev-dependencies ของ 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.d.ts อยู่ข้าง ๆ กับ mystyle.scss ของคุณ ซึ่งมีคลาส CSS ที่คุณกำหนดไว้ ซึ่งคุณสามารถนำเข้ามาเป็นโมดูล Typescript และใช้งานแบบนี้ได้:

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

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

CSS จะถูกโหลดโดยอัตโนมัติ (ฝังเป็นองค์ประกอบ style ลงใน DOM) และจะมีตัวระบุที่ซับซ้อนแทนคลาส CSS ของคุณในไฟล์ .scss เพื่อแยกสไตล์ของคุณออกจากหน้า (เว้นแต่คุณจะใช้ :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 ได้ด้วย ไม่ใช่แค่โฟลเดอร์ root ที่ไฟล์ declarations.d.ts ตั้งอยู่

คุณสามารถเพิ่ม declaration.d.ts โดยตรงในโฟลเดอร์ที่คุณนำเข้า styles โดยตรงได้ แต่ก็เป็นความคิดที่ไม่ดีมาก ๆ

คำตอบ #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 สิ่งที่ฉันทำคือ:

สร้างไฟล์ declarations.d.ts ในโฟลเดอร์ src และเพิ่มโค้ดต่อไปนี้ลงในไฟล์นั้น

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

จากนั้นสร้างไฟล์ tsconfig.json ในโฟลเดอร์ src และเพิ่มโค้ดดังต่อไปนี้

{
  "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

และมันใช้ได้ผล!

บทความที่เกี่ยวข้อง