我有一个React-TypeScript SSR应用程序,在其中我使用SCSS文件进行样式设计。我需要在Webpack中编写一条规则来加载SCSS,但我还无法做到这一点。
我在网上找到了各种解决方案,所有这些解决方案都非常复杂,并且使用诸如mini-css-extract-plugin之类的东西。我无法让他们工作。
我目前有两个webpack配置文件,一个用于客户端(网络),一个用于服务器(节点),这两个文件都这样加载SCSS:
{
test: /\.scss$/,
use: ["css-loader", "sass-loader"]
}
我还遇到了另一个问题,因为它引发有关窗口对象的错误,所以我不能使用样式加载器。有没有人有在Webpack中加载SCSS的可行示例(最好是简单的示例)?
答案 0 :(得分:1)
您在正确的2个Web配置文件上可以使用
https://gist.github.com/mburakerman/629783c16acf5e5f03de60528d3139af
但是不要在project.json中设置任何其他配置文件,例如babel.rc .yaml等或其他定义
尝试
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader'
]
// ..
plugins: [
new MiniCssExtractPlugin({
filename: 'assets/css/bundle-[contenthash].css',
chunkFilename: 'assets/css/bundle-[contenthash].css'
})
],
查看完整示例https://github.com/dewelloper/pzone/blob/master/webpack.config.store.js
答案 1 :(得分:0)
使用 react
、webpack
、Sass
的服务器端渲染样板
(对于 css 模块和纯 sass)
webpack.config.js
const path = require('path');
const isDevelopment = true;
module.exports = [
{
name: 'client',
target: 'web',
entry: './client.jsx',
output: {
path: path.join(__dirname, 'static'),
filename: 'client.js',
publicPath: '/static/',
},
resolve: {
extensions: ['.js', '.jsx']
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules\/)/,
use: [
{
loader: 'babel-loader',
}
]
},
{
test: /\.scss$/,
use: [
{
loader: 'style-loader',
},
{
loader: "css-loader",
options: {
modules: {
localIdentName: "[name]__[local]___[hash:base64:5]",
},
sourceMap: isDevelopment,
}
},
{
loader: 'sass-loader'
}
]
}
],
},
},
{
name: 'server',
target: 'node',
entry: './server.jsx',
output: {
path: path.join(__dirname, 'static'),
filename: 'server.js',
libraryTarget: 'commonjs2',
publicPath: '/static/',
},
devtool: 'source-map',
resolve: {
extensions: ['.js', '.jsx']
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules\/)/,
use: [
{
loader: 'babel-loader',
}
]
},
{
test: /\.scss$/,
use: [
{
loader: 'isomorphic-style-loader',
},
{
loader: "css-loader",
options: {
modules: {
localIdentName: "[name]__[local]___[hash:base64:5]",
},
sourceMap: isDevelopment,
}
},
{
loader: 'sass-loader'
}
]
}
],
},
}
];
开发依赖:
npm i -D @babel/cli @babel/preset-es2015 @babel/core @babel/plugin-proposal-class-properties @babel/preset-env @babel/preset-react babel-core babel-loader babel-plugin-lodash babel-plugin-react-transform babel-preset-env babel-preset-es2015 babel-preset-react babel-preset-stage-0 css-loader express isomorphic-style-loader node-sass sass-loader style-loader webpack webpack-dev-middleware webpack-hot-middleware webpack-hot-server-middleware
和依赖项:
npm i react react-dom react-helmet react-router-dom
sever.jsx:
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import { StaticRouter } from 'react-router-dom';
import {Helmet} from "react-helmet";
import Template from './template';
import App from './App';
export default function serverRenderer({ clientStats, serverStats }) {
return (req, res, next) => {
const context = {};
const markup = ReactDOMServer.renderToString(
<StaticRouter location={ req.url } context={ context }>
<App />
</StaticRouter>
);
const helmet = Helmet.renderStatic();
res.status(200).send(Template({
markup: markup,
helmet: helmet,
}));
};
}
App.jsx:
import React, { Component } from 'react';
import { Switch, Route } from 'react-router-dom';
import Menu from './Menu'
import Helmet from "react-helmet";
import homepageStyles from './homepage.scss';
class Homepage extends Component {
render() {
return (
<div className={ homepageStyles.component }>
<Helmet
title="Welcome to our Homepage"
/>
<Menu />
<h1>Homepage</h1>
</div>
);
}
}
class About extends Component {
render() {
return (
<div>
<h1>About</h1>
</div>
);
}
}
class Contact extends Component {
render() {
return (
<div>
<h1>Contact</h1>
</div>
);
}
}
export default class App extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<Helmet
htmlAttributes={{lang: "en", amp: undefined}} // amp takes no value
titleTemplate="%s | React App"
titleAttributes={{itemprop: "name", lang: "en"}}
meta={[
{name: "description", content: "Server side rendering example"},
{name: "viewport", content: "width=device-width, initial-scale=1"},
]}
/>
<Switch>
<Route exact path='/' component={ Homepage } />
<Route path="/about" component={ About } />
<Route path="/contact" component={ Contact } />
</Switch>
</div>
);
}
}
模板.jsx
export default ({ markup, helmet }) => {
return `<!doctype html>
<html ${helmet.htmlAttributes.toString()}>
<head>
${helmet.title.toString()}
${helmet.meta.toString()}
${helmet.link.toString()}
</head>
<body ${helmet.bodyAttributes.toString()}>
<div id="root">${markup}</div>
<div>Heeeeeeeeeeeeeeeeeeeelmet</div>
<script src="/static/client.js" async></script>
</body>
</html>`;
};
menu.jsx:
import { Link } from 'react-router-dom';
import React, { Component } from 'react';
import './menu.scss';
class Menu extends Component {
render() {
return (
<div>
<ul>
<li>
<Link to={'/'}>Homepage</Link>
</li>
<li>
<Link to={'/about'}>About</Link>
</li>
<li>
<Link to={'/contact'}>Contact</Link>
</li>
</ul>
</div>
);
}
}
export default Menu;
.babelrc:
{
"presets": [
"@babel/react",
"@babel/preset-env"
],
"plugins": [
"@babel/proposal-class-properties"
]
}
主页.sccs
.component {
color: blue;
}
menu.scss:
li {
background-color: yellow;
}
我使用了这篇文章: