我正在尝试从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;
启用类型安全样式表模块导入还需要什么?
答案 0 :(得分:31)
TypeScript不知道有.tsx
或*.scss
以外的文件,因此如果导入文件后缀未知,则会抛出错误。
如果您有一个允许导入其他类型文件的webpack配置,则必须告诉TypeScript编译器这些文件是否存在。为此,请添加一个声明文件,在其中声明具有拟合名称的模块。
要声明的模块的内容取决于用于文件类型的webpack加载程序。在通过 sass-loader → css-loader → style-loader 管道// declaration.d.ts
declare module '*.scss';
文件的webpack配置中,将没有导入模块中的内容,正确的模块声明如下所示:
// declaration.d.ts
declare module '*.scss' {
const content: {[className: string]: string};
export default content;
}
如果为css-modules配置了加载器,只需像这样扩展声明:
function customValidation(){
var a = document.getElementById("val1").value;
var b = document.getElementById("val2").value;
if((a == "" && b == "")
|| (a > "" && !isNumber(a)) || (b > "" && !isNumber(b))
|| (a < 0 || b < 0)
|| (a == 0 && b == 0)
|| (a > 0 && b > 0)){
alert("Input incorrect; "
+ "only one of the fields must contain a value "
+ "and that should be a positive number");
return false;
}
if(a > 0){
n = a;
}
else{
n = b;
}
for(i=0; i < (Number(n) + Number(1)); i++){
alert("Executing: "+i);
//
//
}
}
//-----------------------------------------------------
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
//-----------------------------------------------------
答案 1 :(得分:7)
我正在使用 typescript-plugin-css-modules
npm install -D typescript-plugin-css-modules
tsconfig.json
{
"compilerOptions": {
"plugins": [{ "name": "typescript-plugin-css-modules" }]
}
}
答案 2 :(得分:2)
只需添加文件 typings.d.ts 包含:
declare module "*.module.css";
记得用“module”声明你的css文件。例如 styles.module.css
导入:
import React from 'react';
import styles from './styles.module.css'
答案 3 :(得分:1)
请注意,如果将这些解决方案与tsconfig路径结合使用以缩短导入时间,则将需要其他配置。
如果您碰巧使用路径tsconfig,例如:
{
"compilerOptions": {
"paths": {
"style/*": [ "src/style/*" ],
}
}
}
因此您可以这样做:
import { header } from 'style/ui.scss';
然后,您还需要在Webpack上添加modules resolve配置,例如:
module.exports = {
...
resolve: {
...
alias: {
style: path.resolve(__dirname, 'src', 'style')
}
}
}
确保根据您的设置设置了路径。
这使webpack知道要看哪里,因为它认为新的导入路径实际上是一个模块,因此它默认为node_modules目录。通过这种配置,它知道在哪里寻找并找到它,并且构建可以正常工作。
答案 4 :(得分:0)
这是一个对我有用的完整配置(如果有人遇到相同的问题,我为此花了一个小时的反复试验-
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
的dev-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"
}
然后,您应该在mystyle.d.ts
旁边获得一个mystyle.scss
,其中包含您定义的CSS类,您可以将其作为Typescript模块导入并像这样使用:
import * as styles from './mystyles.scss';
const foo = <div className={styles.myClass}>FOO</div>;
CSS将自动加载(以style
元素的形式插入到DOM中),并包含隐式标识符而不是.scss中的CSS类,以隔离页面中的样式(除非您使用{{ 1}})。
请注意,无论何时添加CSS类或删除它们或重命名它们,第一次编译都会失败,因为导入的mystyles.d.ts是旧版本,而不是编译期间刚刚生成的新版本。只是再次编译。
享受。
答案 5 :(得分:-1)
声明全局类型时的问题是未验证导入的分辨率\可访问性。
答案 6 :(得分:-2)
我在 angular 方面遇到了同样的问题,我尝试运行 npm audit fix
并解决了我的问题。