CSS / SCSS modülleri içe aktarılamıyor. TypeScript "Modül Bulunamıyor" diyor


88

Bir CSS modülünden bir temayı içe aktarmaya çalışıyorum ancak TypeScript bana "Modül Bulunamıyor" hatası veriyor ve tema çalışma zamanında uygulanmıyor. Webpack yapılandırmamda bir sorun olduğunu düşünüyorum, ancak sorunun nerede olduğundan emin değilim.

Aşağıdaki araçları kullanıyorum:

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

İşte benim 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: './'
  },
};

ve App.tsxithal etmeye çalıştığım yer:

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;

Tür güvenli stil sayfası modülünü içe aktarmayı etkinleştirmek için başka ne gereklidir?

Yanıtlar:


125

TypeScript, .tsveya .tsxbu türden başka dosyalar olduğunu bilmez, bir içe aktarmada bilinmeyen bir dosya soneki varsa, bir hata verir.

Diğer dosya türlerini içe aktarmanıza izin veren bir web paketi yapılandırmanız varsa, TypeScript derleyicisine bu dosyaların var olduğunu söylemeniz gerekir. Bunu yapmak için, uygun adlara sahip modülleri bildirdiğiniz bir bildirim dosyası ekleyin.

Bildirilecek modülün içeriği, dosya türü için kullanılan web paketi yükleyiciye bağlıdır. *.scssDosyaları sass-loadercss-loaderstyle-loader aracılığıyla yönlendiren bir web paketi yapılandırmasında , içe aktarılan modülde içerik olmayacak ve doğru modül bildirimi aşağıdaki gibi görünecektir:

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

Yükleyiciler css modülleri için yapılandırılmışsa, bildirimi şu şekilde genişletin:

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

2
Hey bu benim için işe yaramadı, son zamanlarda bir şey değişti. stackoverflow.com/questions/56563243/…
Kay

50

İşte benim için çalışan eksiksiz bir konfigürasyon (bunun üzerinde sadece bir saat acı verici deneme yanılma geçirdim - herhangi birinin aynı sorunlarla karşılaşması durumunda):

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

        ]
    }
}; 

Ayrıca declarations.d.tsprojenize bir de ekleyin:

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

Ve tüm bunlara package.jsondev-bağımlılıklarınızda ihtiyacınız olacak :

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

Ardından , tanımladığınız CSS sınıflarını içeren, bir Typecript modülü olarak içe aktarabileceğiniz ve aşağıdaki gibi kullanabileceğiniz bir mystyle.d.tsyan almalısınız mystyle.scss:

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

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

CSS otomatik olarak yüklenir ( styleDOM'a bir öğe olarak enjekte edilir ) ve sayfadaki stillerinizi izole etmek için (kullanmadığınız sürece :global(.a-global-class) { ... }) .scss'deki CSS sınıflarınız yerine şifreli tanımlayıcılar içerir .

İçe aktarılan mystyles.d.ts eski sürüm olduğundan ve henüz derleme sırasında oluşturulan yeni sürüm olmadığından, CSS sınıfları eklediğinizde veya bunları kaldırdığınızda veya yeniden adlandırdığınızda ilk derlemenin başarısız olacağını unutmayın . Sadece tekrar derleyin.

Zevk almak.


"NOT: CSS sınıflarını ekledikten / kaldırdıktan / yeniden adlandırdıktan sonraki ilk yapı başarısız olur, çünkü yeni oluşturulan .d.ts typcript modülü ancak daha sonra alınır" - Bu kısım nasıl çözülür?
Jon Lauridsen

3
@JonLauridsen, webpack.config.js'deki kural dizisinin en altına (sonuna) ts-loader ayarlanarak çözülebilir. Bu nedenle ts-loader, daha önce oluşturulacaklarından dolayı her derleme için doğru bir * .scss.d.ts dosyalarını alacaktır.
Yan Pak

1
@YanPak Teşekkürler, ts-yükleyiciyi stil yükleyicilerin altına taşımanın yanı sıra dizinime bir global.d.tsde eklemek benim srciçin düzeltildi.
lux

5

Tsconfig.json Yol Ayarını Kullanıyorsanız Uyarı

Bu çözümleri, içe aktarmanızı kısaltmak için tsconfig yollarıyla birlikte kullanıyorsanız, ek yapılandırmaya ihtiyacınız olacağını unutmayın.

Böyle bir yol tsconfig kullanıyorsanız:

{
  "compilerOptions": {
    "paths": {
      "style/*": [ "src/style/*" ],
    }
  }
}

Böylece şunları yapabilirsiniz:

import { header } from 'style/ui.scss';

Ardından , web paketinize aşağıdaki gibi bir modül çözümleme yapılandırması eklemeniz gerekir :

module.exports = {
  ...
  resolve: {
    ...
    alias: {
      style: path.resolve(__dirname, 'src', 'style')
    }
  }
}

Yolun kurulumunuza göre ayarlandığından emin olun.

Bu, web paketinin nereye bakılacağını bilmesini sağlar, çünkü yeni içe aktarma yolunun aslında bir modül olduğunu düşünür, bu nedenle öntanımlı olarak node_modules dizinidir. Bu konfigürasyon ile nereye bakacağını bilir ve bulur ve yapı çalışır.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.