1
votes

Interface utilisateur matérielle: les noms de classe en développement sont modifiés

J'ai une configuration matérielle d'interface utilisateur avec SSR. Je fonctionne très bien ...

Mon problème est que lorsque je compile mon code, material-ui génère des noms de classe étranges comme jss116 ou jss19 .

C'est vraiment ennuyeux lors de l'inspection de mon code en développement. Je veux avoir (dans mon environnement de développement), des noms de classe plus significatifs. Est-ce possible?

server.tsx

import * as React from "react";
import * as ReactDOM from 'react-dom';
import {BrowserRouter, Router} from "react-router-dom";

import {createStore} from 'redux';
import {Provider} from 'react-redux';
import {appReducer} from '../shared/reducers';

import App from "../shared/App";
import {create} from "jss";
import {createGenerateClassName, MuiThemeProvider, jssPreset} from '@material-ui/core/styles';
import theme from '../shared/MainTheme';
import JssProvider from 'react-jss/lib/JssProvider';
import configureStore from '../shared/store/index';

declare global {
    interface Window {
        __PRELOADED_STATE__ : any
    }
}

const preloadedState = window.__PRELOADED_STATE__;
delete window.__PRELOADED_STATE__;
// const store = createStore(appReducer, preloadedState);
// const store = configureStore(appReducer, preloadedState);
const store = configureStore(preloadedState);

const Main = () => {
    React
        .useEffect(function didMount() {
            const jssStyles = document.getElementById('jss-server-side');
            if (jssStyles && jssStyles.parentNode) {
                jssStyles
                    .parentNode
                    .removeChild(jssStyles);
            }
        }, []);

    return <App/>
}

const generateClassName = createGenerateClassName();
const jss = create(jssPreset());

ReactDOM.hydrate(
    <JssProvider jss={jss} generateClassName={generateClassName}>
    <MuiThemeProvider theme={theme}>
        <BrowserRouter>
            <Provider store={store}>
                <Main/>
            </Provider>
        </BrowserRouter>
    </MuiThemeProvider>
</JssProvider>, document.querySelector('#root'),);

client.tsx

import * as path from 'path';
import * as express from "express";
import * as bodyParser from "body-parser";
import * as React from "react";
import * as ReactDOMServer from "react-dom/server";
import {StaticRouter} from "react-router";
import {matchPath} from "react-router-dom";
import {Helmet} from "react-helmet";
import { createStore, Action } from 'redux';
import { Provider } from 'react-redux';

import {SheetsRegistry, create} from 'jss';
import JssProvider from 'react-jss/lib/JssProvider';
import {MuiThemeProvider, jssPreset, createGenerateClassName} from '@material-ui/core/styles';

import App from "../shared/App";
import routes from '../shared/routes';
import theme from '../shared/MainTheme';


const app = express();
const PORT = process.env.PORT || 3000;

app.use(bodyParser.urlencoded());
app.use(bodyParser.json());
app.use(express.static("build/public"));

console.log("Public path:", path.join(__dirname, "public"));

const appReducer = (prevState: any, action: Action) => ({...prevState, message: "Reducer"});

app.get('*', (req, res, next) => {

    const now = new Date();
    console.log(`GET ${now} - ${req.originalUrl}`);

    const activeRoute = routes.find(route => !!matchPath(req.url, route)) || {
     path: "/" };
    // TODO: Fetch initial state according to the active route.
    const preloadedState = {activeRoute};
    const store = createStore(appReducer, preloadedState as any);

    const sheetsRegistry = new SheetsRegistry();
    const sheetsManager = new Map();
    const generateClassName = createGenerateClassName();
    const jss = create(jssPreset());



    const context = {}
    const content = ReactDOMServer.renderToString(
        <StaticRouter location={req.url} context={context}>
            <JssProvider jss={jss} registry={sheetsRegistry} generateClassName={generateClassName}>
                <MuiThemeProvider theme={theme} sheetsManager={sheetsManager}>
                    <Provider store={store}>
                        <App/>
                    </Provider>
                </MuiThemeProvider>
            </JssProvider>
        </StaticRouter>
    );

    const helmet = Helmet.renderStatic();
    const css = sheetsRegistry.toString();

    const html = `
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="UTF-8">            
            <meta name="viewport" content="width=device-width, initial-scale=1.0">            
            <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
            <link rel="icon" href="/favicon.ico" type="image/x-icon" />
            <style id="jss-server-side">${css}</style>            
        </head>
        <body>
            <div id="root" style="overflow-x: hidden; width: 100%; margin: 0;">${content}</div>
            <script src="client_bundle.js" type="text/javascript"></script>
            <script type="text/javascript">
                window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace(/</g, '\\u003c')}
            </script>
        </body>
        </html>
    `;

    res.send(html);
});

app.listen(PORT, () => {
    console.log(`App is running on port ${PORT}`)
})


0 commentaires

4 Réponses :


0
votes

Vous pouvez changer la valeur des accessoires generateClassName en votre générateur personnalisé en fonction de l'environnement. En production, vous pouvez simplement utiliser le createGenerateClassName .

Par exemple:

let generateClassName = null;

if (process.env.NODE_ENV === "production") {
  // use the default class name creator from mui
  generateClassName = createGenerateClassName();
} else {
  // make your own name generator
  const createGenerateId = () => {
    let counter = 0;
    return (rule, sheet) => `pizza--${rule.key}-${counter++}`;
  };
  generateClassName = createGenerateId();
}

// ... in render
<JssProvider generateClassName={generateClassName} ...>
  ...
</JssProvider>

Cet exemple est tiré de Docs CSS-in-JS .


0 commentaires

1
votes

Vous devriez pouvoir obtenir des noms significatifs en développement en définissant correctement NODE_ENV dans votre outil de compilation.


0 commentaires

3
votes

J'ai finalement réglé ce problème en exécutant webpack comme ceci:

webpack --mode = development ./server.ts

Il s'avère que, pour une raison quelconque, Webpack n'écoute pas NODE_ENV


2 commentaires

Où gérez-vous exactement cela? Je ne savais pas que nous devions exécuter webpack séparément lors de l'exécution de notre application react.


Merci Daniel, tu as sauvé la journée, j'ai eu exactement le même problème en mode webpack différent pour le client et le serveur



0
votes

J'ai rencontré ce problème et je l'ai résolu en utilisant la fonction createGenerateClassName et en définissant l'option disableGlobal sur true .

const generateClassName = createGenerateClassName({
    disableGlobal: true,
});

const App = () => ({
    <StylesProvider generateClassName={generateClassName}>...</StylesProvider>
});


0 commentaires