如何使用 Typescript、React 和 Webpack 导入 SCSS 或 CSS 模块
How to import SCSS or CSS modules with Typescript, React and Webpack
我想在我的项目中使用 .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"
我的.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';
而且有效。
谢谢。
我没有将 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
}
}
]
},
这是否解决了您的错误?
将 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
我在寻找在我的 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;
}
我想在我的项目中使用 .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"
我的.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';
而且有效。
谢谢。
我没有将 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
}
}
]
},
这是否解决了您的错误?
将 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
我在寻找在我的 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;
}