如何使用 Typescript、React 和 Webpack 导入 SCSS 或 CSS 模块
Posted
技术标签:
【中文标题】如何使用 Typescript、React 和 Webpack 导入 SCSS 或 CSS 模块【英文标题】:How to import SCSS or CSS modules with Typescript, React and Webpack 【发布时间】:2019-10-01 15:20:03 【问题描述】:我想在我的项目中使用 .scss
(使用 react 和 typescript 构建),所以我使用 typings-for-css-modules-loader
和 css-loader
和 sass-loader
。
当我npm run dev
时,我收到此错误:
./src/Common.scss
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleBuildError: Module build failed (from ./node_modules/sass-loader/lib/loader.js):
.common
^
Invalid CSS after "e": expected 1 selector or at-rule, was "exports = module.ex"
my.scss
像这样:
.common
height: 100px
而我的 wepack.config 是:
module.exports =
mode: 'development',
entry: [
'webpack-dev-server/client',
path.resolve(root, 'src/index.tsx')
],
devtool: 'inline-source-map',
devServer:
contentBase: './dist',
publicPath: '/',
port: 8080,
historyApiFallback: true
,
resolve:
extensions: [".ts", ".tsx", ".scss", ".js", ".json", "css"]
,
plugins: [
new CleanWebpackPlugin(['dist']),
new BundleAnalyzerPlugin(),
new MiniCssExtractPlugin(
filename: devMode ? '[name].css' : '[name].[hash].css',
chunkFilename: devMode ? '[id].css' : '[id].[hash].css',
)
],
output:
filename: 'bundle.js',
path: path.resolve(root, 'dist'),
publicPath: '/'
,
module:
rules: [
test: /\.tsx?$/,
use: 'ts-loader'
,
test: /\.(js|jsx)$/,
use: 'babel-loader',
exclude: /node_modules/
,
test: /\.(sa|sc|c)ss$/,
use: [
loader: devMode ? MiniCssExtractPlugin.loader : 'style-loader'
,
loader: 'css-loader',
options:
sourceMap: true,
modules: true,
,
loader: 'sass-loader', options:
sourceMap: true
]
,
test: /\.(c|sc)ss$/, loader: 'typings-for-css-modules-loader?modules&sass' ,
test: /\.(jpg|png|gif)$/,
use: [
loader: 'file-loader',
options:
name (file)
if (devMode === 'development')
return '[path][name].[ext]'
return '[hash].[ext]'
]
]
,
optimization:
splitChunks:
chunks: 'all'
;
当我将css-loader
与sass-loader
一起使用或单独使用typings-for-css-modules-loader
时,此错误已修复。
但是我又遇到了这样的错误:
ERROR in /Users/hly/Bpeanut.github.io/src/app/HeaderBar.tsx
./src/app/HeaderBar.tsx
[tsl] ERROR in /Users/hly/Bpeanut.github.io/src/app/HeaderBar.tsx(40,39)
TS2339: Property 'header' does not exist on type 'typeof import("/Users/hly/Bpeanut.github.io/src/app/HeaderBar.scss")'.
HeaderBar.tsx
这样(错误就在这里):
import * as styles from './HeaderBar.scss';
class default HeaderBar extends Component
render()
return(<div className=styles.header>123</div>)
^
和HeaderBar.scss
喜欢:
.header
height: 100px;
HeaderBar.scss.d.ts
:
export interface IHeaderBarScss
'header': string;
export const locals: IHeaderBarScss;
现在我找到了另一种解决方法。
使用const styles = require('./HeaderBar.scss');
代替import * as styles from './HeaderBar.scss';
它工作。
谢谢。
【问题讨论】:
根据文档,您必须将css-loader
替换为 typings-for-css-modules-loader
。目前您同时使用这两种方法可能会导致错误。
【参考方案1】:
我不使用 typings-for-css-modules-loader
来处理我的带有 css 和 scss 的项目,并且使用这种配置它工作得很好:
test: /\.s?css$/,
use: [
loader: MiniCssExtractPlugin.loader,
options:
sourceMap: true
,
loader: 'css-loader',
options:
sourceMap: true
,
loader: 'sass-loader',
options:
sourceMap: true
]
,
这能解决你的错误吗?
【讨论】:
谢谢。我过去和你用过同样的方法。它可以修复这个错误。但还有一个暴露了。 @LoveY.H 什么是新的? 我写在webpack.config
下。我的错。谢谢。
@LoveY.H 好的 :) 在这种情况下,请验证我的回答【参考方案2】:
将 sass-loader 与 css-loader 和 style-loader 链接起来,立即将所有样式应用到 DOM。
npm install style-loader css-loader sass-loader --save-dev
// webpack.config.js
module.exports =
...
module:
rules: [
test: /\.scss$/,
use: [
"style-loader", // creates style nodes from JS strings
"css-loader", // translates CSS into CommonJS
"sass-loader" // compiles Sass to CSS, using Node Sass by default
]
]
;
欲了解更多信息,请访问sass loader
【讨论】:
【参考方案3】:在我的 create-react-app
项目中寻找使用 CSS 模块的方法时,我偶然发现了这个问题。
因此,添加create-react-app
场景的答案。
SCSS 或 CSS 模块文件名应以 module.scss
或 module.css
结尾,以便能够在 create-react-app
项目中使用。
以下示例显示了一个组件 QuestionForm.tsx
和一个 SCSS 模块 QuestionForm.module.scss
一起工作。
// QuestionForm.tsx
import React, useState from 'react';
import style from './QuestionForm.module.scss';
export type PersonalData =
name: string;
;
type QuestionFormProps =
personalData: PersonalData;
onChange: (data: PersonalData) => void;
;
export const QuestionForm: React.FC<QuestionFormProps> = ( personalData, onChange ) =>
const [name, setName] = useState<string>(personalData.name);
const handleSubmit = (event: React.FormEvent) =>
event.preventDefault();
onChange( name );
;
const handleNameChange = (event: React.ChangeEvent<htmlInputElement>) =>
setName(event.target.value);
;
return (
<form className=style.container onSubmit=handleSubmit>
<div className=style.titleWrapper>
<h2 className=style.title>Questionnaire</h2>
</div>
<label>
What is your name?
<input type="text" minLength=2 maxLength=20 value=name onChange=handleNameChange required />
</label>
<div className=style.cta>
<input className="buttonPrimary" type="submit" value="Submit" />
</div>
</form>
);
;
// QuestionForm.module.scss
@mixin flex($direction: row, $align: center, $justify: center)
align-items: $align;
display: flex;
flex-direction: $direction;
justify-content: $justify;
width: 100%;
.container
@include flex(column, flex-end, space-evenly);
border: 1px solid whitesmoke;
border-radius: 5px;
height: 230px;
padding: 0 10px;
width: 400px;
.cta
@include flex();
.titleWrapper
@include flex();
.title
font-size: 1.5rem;
font-weight: bold;
【讨论】:
以上是关于如何使用 Typescript、React 和 Webpack 导入 SCSS 或 CSS 模块的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 GraphQL 构建 TypeScript+React 应用
如何使用 usestate 和 setstate 而不是 this.setState 使用 react 和 typescript?
如何使用 Typescript、React 和 Webpack 导入 SCSS 或 CSS 模块
React-native:如何在 React-native 中使用(和翻译)带有 jsx 的 typescript .tsx 文件?