为什么isomorphic-style-loader引发TypeError:当与CSS-Modules一起使用时,无法读取未定义的属性"apply" [英] Why does isomorphic-style-loader throw a TypeError: Cannot read property 'apply' of undefined when being used in unison with CSS-Modules
问题描述
我当前正在尝试在服务器上呈现该应用程序,该应用程序适用于HTML和JS,但发现无法加载我的样式(.less | .scss).我进行了一些研究,但不确定,基于其他遇到相同问题的原因,我在Webpack配置中缺少 isomorphic-style-loader
.我至少按照我的理解进行了设置,但是现在发现运行该应用程序时出现以下错误:
I'm currently trying to render the application on the server, which works for the HTML and JS, but found that my styles (.less | .scss) would not load. I did some research and figured, not sure, that I was missing the isomorphic-style-loader
in my Webpack configuration based on others running into the same issues. I set it up, at least how I understood it, but am now finding that when running the application I receive the following error:
TypeError:无法读取WithStyles.componentWillMount中未定义的属性"apply"
我对整个React/Express还是有点陌生,但是我一直在尝试跟随教程和学习,如果有什么地方不合适,请原谅.我希望看看是否有人可以解释导致此错误的确切原因,并为我提供一些解决该错误的方法的思路.下面是一些示例代码,如果有任何帮助,它们类似于我遇到的代码.
I'm somewhat new to the whole React / Express thing but have been trying to follow along with tutorials and learning as I go, if anything seems out of place, please excuse me. I am hoping to see if anybody can explain what exactly causes this error, and provide me with some idea of what I could follow to resolve this error. Below is some example code that resembles the one I am having issues with, if it helps in any way.
(作为参考,我正在关注Tyler McGinnis React Router Server Rendering教程,并尝试对其进行扩展以添加样式-在此处链接)
(For reference I was following Tyler McGinnis React Router Server Rendering tutorial and tried to expand upon it to add styling - Link Here)
在此先感谢您提供可能导致此错误的原因的任何解释.
Thanks beforehand for any explanation provided as to what may be causing this error.
import path from 'path'
import webpack from 'webpack'
import nodeExternals from 'webpack-node-externals'
const paths = {
browser: path.join(__dirname, './src/browser'),
server: path.join(__dirname, './src/server'),
build: path.resolve(__dirname, 'public')
}
let browserConfig = {
entry: `${paths.browser}/index.js`,
output: {
path: paths.build,
filename: 'bundle.js',
publicPath: '/'
},
module: {
rules: [
{
test: /\.s?(a|c)ss$/,
use: [
'isomorphic-style-loader',
{
loader: 'css-loader',
options: {
modules: true,
importLoaders: 1,
localIdentName: '[name]__[local]___[hash:base64:5]',
sourceMap: true
}
},
'sass-loader',
'postcss-loader'
]
}, {
test: /\.less$/,
use: [
'isomorphic-style-loader',
{
loader: 'css-loader',
options: {
modules: true,
importLoaders: 1,
localIdentName: '[name]__[local]___[hash:base64:5]',
sourceMap: true
}
},
{
loader: 'less-loader',
options: {
javascriptEnabled: true
}
},
'postcss-loader'
]
}, {
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/
}
]
},
plugins: [
new webpack.DefinePlugin({
__isBrowser__: true
})
],
resolve: {
extensions: ['.js', '.jsx', '.json', '.css', '.scss', '.sass', '.less']
}
}
let serverConfig = {
entry: `${paths.server}/index.js`,
target: 'node',
externals: [nodeExternals()],
output: {
path: __dirname,
filename: 'server.js',
publicPath: '/'
},
module: {
rules: [
{
test: /\.s?(a|c)ss$/,
use: [
'isomorphic-style-loader',
{
loader: 'css-loader',
options: {
modules: true,
importLoaders: 1,
localIdentName: '[name]__[local]___[hash:base64:5]',
sourceMap: true
}
},
'sass-loader',
'postcss-loader'
]
}, {
test: /\.less$/,
use: [
'isomorphic-style-loader',
{
loader: 'css-loader',
options: {
modules: true,
importLoaders: 1,
localIdentName: '[name]__[local]___[hash:base64:5]',
sourceMap: true
}
},
{
loader: 'less-loader',
options: {
javascriptEnabled: true
}
},
'postcss-loader'
]
}, {
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/
}
]
},
plugins: [
new webpack.DefinePlugin({
__isBrowser__: false
})
],
resolve: {
extensions: ['.js', '.jsx', '.json', '.css', '.scss', '.sass', '.less']
}
}
module.exports = [browserConfig, serverConfig]
server.js
import express from "express"
import cors from "cors"
import React from "react"
import bodyParser from 'body-parser'
import serialize from "serialize-javascript"
import { renderToString } from "react-dom/server"
import { StaticRouter, matchPath } from "react-router-dom"
import App from '../shared/App'
import routes from '../shared/routes'
const app = express()
const port = process.env.PORT || 3000
app.use(cors())
app.use(bodyParser.json()) // support json encoded bodies
app.use(bodyParser.urlencoded({extended: true})) // support encoded bodies
app.use(express.static("public"))
app.get("*", (req, res, next) => {
const activeRoute = routes.find((route) => matchPath(req.url, route)) || {}
const promise = activeRoute.fetchInitialData
? activeRoute.fetchInitialData(req.path)
: Promise.resolve()
promise.then((data) => {
const css = new Set()
const context = { data, insertCss: (...styles) => styles.forEach(style => css.add(style._getCss())) }
const markup = renderToString(
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>
)
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>React on the Server!</title>
<script src="/bundle.js" defer></script>
<script>window.__INITIAL_DATA__ = ${serialize(data)}</script>
</head>
<body>
<div id="app">${markup}</div>
</body>
</html>
`)
}).catch(next)
})
app.listen(port, () => console.log(`Server is listening on port: ${port}`))
routes.js
import AboutMain from './components/About/AboutMain'
const routes = [
{
path: '/about',
component: AboutMain
}
]
export default routes
browser.js
// Import the neccessary modules for use in file
import React from 'react' // Main React module
import { hydrate } from 'react-dom' // render alternative for server rendering
import App from '../shared/App'
import { BrowserRouter } from 'react-router-dom' // React Router component for client side routing
import '../shared/components/global.scss' // Only has general rules, which do get applied
hydrate(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('app')
)
App.js
import React, { Component } from 'react'
import routes from './routes'
import { Route, Link, Redirect, Switch } from 'react-router-dom'
class App extends Component {
render() {
return (
<div>
<Switch>
{routes.map(({ path, exact, component: Component, ...rest }) => (
<Route key={path} path={path} exact={exact} render={(props) => (
<Component {...props} {...rest} />
)} />
))}
<Route render={(props) => <NoMatch {...props} /> } />
</Switch>
</div>
)
}
}
export default App
AboutMain.js
// Importing Required Modules
import React, {Component, Fragment} from 'react' // Importing React, Component, Fragment from "react"
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import s from './about.scss'
class AboutMain extends Component {
state = {
phrase: 'We Made It!'
}
render() {
return (
<Fragment>
<header className={s.banner}>
<h1 className={s.heading}>{this.state.phrase}</h1>
</header>
</Fragment>
)
}
}
export default withStyles(s)(AboutMain) <-- Error Seems to occur here, at least I think.
about.scss
.banner {
margin: 0 auto;
padding: 15px;
border: 2px solid #000;
}
.heading {
text-transform: uppercase;
text-decoration: underline;
}
推荐答案
整夜检查代码并无休止地搜索Google.我找到了一个修复程序,该代码的主要问题是在 webpack.config.babel.js
设置中.
After reviewing the code all night and endlessly searching Google. I found a fix that the main issue with my code was in the webpack.config.babel.js
setup.
我更改了浏览器对sass的测试||scss使用 style-loader
,而不是 isomorphic-style-loader
.我还从应用程序中删除了所有 isomorphic-style-loader
逻辑(即 withStyles
, insertCss
等)
I changed the browser test for sass || scss to use style-loader
, rather than the isomorphic-style-loader
. I also removed all isomorphic-style-loader
logic from my app (ie. withStyles
, insertCss
, etc.)
我不确定这是否正确,但是与此同时,它似乎可以解决我的问题,并且不会返回任何错误或网络问题.
I'm not sure if this was the correct approach, but for the meantime, it seems to fix my problem and does not return any errors or network issues.
这篇关于为什么isomorphic-style-loader引发TypeError:当与CSS-Modules一起使用时,无法读取未定义的属性"apply"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!