web-dev-qa-db-fra.com

Sass avec modules CSS et Webpack

Je construis un projet depuis un certain temps en utilisant les modules Webpack, Sass et CSS. Normalement, dans mes fichiers .scss, Je définis une classe comme:

:local(.button) {
    color: white;
}

et dans mes composants React, dans la méthode render, j'ai besoin des styles:

render = () => {
    const styles = require('./MyStyles.scss');
    <div className={ styles.button } />
}

et tout va bien avec le monde. Tout fonctionne comme prévu.

Aujourd'hui, je lisais la page Modules CSS et j'ai remarqué qu'aucun des sélecteurs n'était englobé par :local() comme le mien et en outre qu'ils importaient les styles comme:

import styles from './MyStyles.scss';

Et je me suis dit "Wow, ça a l'air beaucoup plus agréable, il est plus facile de voir où il est importé, ect. Et j'aimerais ne pas utiliser :local() et avoir juste des choses locales par défaut." J'ai donc essayé cela et j'ai immédiatement rencontré plusieurs problèmes.

1) `importer des styles depuis './MyStyles.scss';

Parce que j'utilise ESLint sur mes fichiers React, je reçois immédiatement une erreur indiquant que MyStyles.scss N'a pas d'export par défaut qui aurait normalement du sens, mais la page Modules CSS déclaré:

Lors de l'importation du module CSS à partir d'un module JS, il exporte un objet avec tous les mappages des noms locaux vers les noms globaux.

donc je m'attendais naturellement à ce que l'exportation par défaut de la feuille de style soit également l'objet auquel ils se réfèrent.

2) J'ai essayé import { button } from './MyStyles.scss';

Cela passe les peluches mais les journaux button comme non définis.

3) Si je reviens à la méthode require pour importer mes styles, tout ce qui n'est pas spécifié avec :local N'est pas défini.

Pour référence, mon chargeur de webpack (j'inclus également Node-Neat et Node-Bourbon , deux bibliothèques géniales):

{ test: /.(scss|css)$/, loader: 'style!css?sourceMap&localIdentName=[local]___[hash:base64:5]!resolve-url!sass?outputStyle=expanded&sourceMap&includePaths[]=' + encodeURIComponent(require('node-bourbon').includePaths) +
'&includePaths[]=' + encodeURIComponent(require('node-neat').includePaths[1]) + '&includePaths[]=' + path.resolve(__dirname, '..', 'src/client/') }

Mes questions, après tout cela, sont:

1) Lorsque j'utilise des modules CSS avec Sass, suis-je limité à l'utilisation de :local Ou :global?

2) Puisque j'utilise webpack, cela signifie-t-il que je ne peux que require mes styles?

42
barndog

Peu de temps après la publication, j'ai trouvé la solution. Le problème, qui m'a semblé assez déroutant, était dans ma configuration Webpack. À l'origine, mon chargeur ressemblait à:

loader: 'style!css?sourceMap&localIdentName=[local]___[hash:base64:5]!resolve-url!sass?outputStyle=expanded&sourceMap

ce qui m'a permis 1) require mon Sass et 2) d'envelopper mes styles dans :local.

Cependant, le chargeur css manquait l'option modules de sorte qu'il ressemblait à:

loader: 'style!css?modules&sourceMap&localIdentName=[local]___[hash:base64:5]!resolve-url!sass?outputStyle=expanded&sourceMap

Maintenant, je peux import mes styles et je n'ai pas à les encapsuler dans :local (Bien que je présume que je peux toujours si je le veux).

Ce que j'ai trouvé le plus intéressant à propos de tout cela, c'est que sans l'option modules, on peut toujours utiliser les fonctionnalités CSS Modules-esque, bien que quelque peu limitantes.

MODIFIER:

Quelque chose que j'ai remarqué, un avertissement futur à quiconque regarde cette réponse, est que si vous utilisez eslint-plugin-import pour peloter les importations dans votre code javascript, cela générera une erreur lors de l'importation de styles comme:

import styles from './MyStyles.scss';

en raison de la façon dont les modules CSS exportent l'objet de styles résultant. Cela signifie que vous devrez faire require('./MyStyles.scss') pour contourner les avertissements ou les erreurs.

44
barndog