Angular: cómo analizar variables JSON en SCSS

8

Dentro de una aplicación angular, hago visuales D3 a través de D3 simple o Vega . También está sucediendo el estilo SCSS.

Me gustaría poder referirme a las mismas variables globales para diseñar desde Javascript y desde SCSS. Los archivos JSON hacen el truco muy bien para almacenar la configuración que cargo en Typecript a través de una simple importdeclaración. Pero, ¿cómo se hace lo mismo desde SCSS?

node-sass-json-importer Parece un buen candidato, pero agregarlo a una aplicación Angular 9 CLI no es obvio para mí.

Esta publicación de StackOverflow analizó el tema hace un tiempo, pero implicó modificar recursos bajo los node_modulescuales es apenas sostenible.

También hay algunas entradas en el documento original sobre cómo se puede modificar el paquete web en una aplicación no angular . No sé cómo relacionar esto con una aplicación angular construida a través de la CLI.

Webpack / sass-loader Blockquote

Webpack v1

import jsonImporter from 'node-sass-json-importer';

// Webpack config
export default {
  module: {
    loaders: [{
      test: /\.scss$/,
      loaders: ["style", "css", "sass"]
    }],
  },
  // Apply the JSON importer via sass-loader's options.
  sassLoader: {
    importer: jsonImporter()
  }
};

Webpack v2

import jsonImporter from 'node-sass-json-importer';

// Webpack config
export default {
  module: {
    rules: [
      test: /\.scss$/,
      use: [
        'style-loader',
        {
          loader: 'css-loader',
          options: {
            importLoaders: 1
          },
        },
        {
          loader: 'sass-loader',
          // Apply the JSON importer via sass-loader's options.
          options: {
            importer: jsonImporter(),
          },
        },
      ],
    ],
  },
};
Zumbido
fuente
1
Tal vez esta es una opción? npmjs.com/package/@angular-builders/custom-webpack
MikeOne
¿Esto ayuda? github.com/vigetlabs/sass-json-vars
Tarun Lalwani
parece estar relacionado con node-sass-json-importador pero mi desafío restante sería lograr que esto funcione en una aplicación Angular 9 CLI
BuZz
No he rechazado nada. Cualquiera puede votar negativamente, no solo el OP.
BuZz

Respuestas:

5

Puede hacerlo sin cambiar ningún node_modulesarchivo mediante la @angular-builders/custom-webpackconfiguración de reglas personalizadas de Webpack y, como menciona, node-sass-json-importerpara importar archivos JSON dentro de archivos SCSS.

Tendrá que instalar node-sassla implementationopción porque node-sass-json-importeres compatible con node-sass.

  1. Instalar paquetes @angular-builders/custom-webpack, node-sass-json-importery node-sass:

    npm i -D @angular-builders/custom-webpack node-sass-json-importer node-sass
  2. Cree el archivo de configuración de Webpack ( webpack.config.js) en el directorio raíz del proyecto con los siguientes contenidos:

    const jsonImporter = require('node-sass-json-importer');
    
    module.exports = {
      module: {
        rules: [{
          test: /\.scss$|\.sass$/,
          use: [
            {
              loader: require.resolve('sass-loader'),
              options: {
                implementation: require('node-sass'),
                sassOptions: {
                  // bootstrap-sass requires a minimum precision of 8
                  precision: 8,
                  importer: jsonImporter(),
                  outputStyle: 'expanded'
                }
              },
            }
          ],
        }],
      },
    }
    
  3. Cambiar buildera @angular-builders/custom-webpack:[architect-target]y añadir customWebpackConfigopciones a build, servey la testconstrucción dentro de los objetivos angular.json:

    "projects": {
      ...
      "[project]": {
        ...
        "architect": {
          "build": {
            "builder: "@angular-builders/custom-webpack:browser",
            "options": {
              "customWebpackConfig": {
                "path": "webpack.config.js"
              },
              ...
            },
            ...
          },
          "serve": {
            "builder: "@angular-builders/custom-webpack:dev-server",
            "customWebpackConfig": {
              "path": "webpack.config.js"
            },
            ...
          },
          "test": {
            "builder: "@angular-builders/custom-webpack:karma",
            "customWebpackConfig": {
              "path": "webpack.config.js"
            },
            ...
          },
        },
        ...
      },
      ...
    }
    

Ahora puede incluir cualquier .jsonarchivo dentro de cualquier .scssarchivo componente :

hello-world.component.scss:

@import 'hello-world.vars.json';

.hello-bg {
  padding: 20px;
  background-color: $bg-color;
  border: 2px solid $border-color;
}

hello-world.vars.json:

{
  "bg-color": "yellow",
  "border-color": "red"
}

He creado un repositorio de Github con todos estos trabajos que puedes clonar y probar desde aquí: https://github.com/clytras/angular-json-scss

git clone https://github.com/clytras/angular-json-scss.git
cd angular-json-scss
npm install
ng serve
Christos Lytras
fuente
3

Otra opción es usar raw-loader, está disponible por defecto en angular-cli. De esta manera, puede cargar un archivo scss sin procesar en el componente ts:

// Adding `!!` to a request will disable all loaders specified in the configuration
import scss from '!!raw-loader!./config.scss';

console.info('scss', scss);

Tienes que declarar el módulo en el .d.tsarchivo:

declare module '!!raw-loader!./*.scss';

Luego puede extraer cualquier información que desee.

Entonces, en lugar de cargar JSON en scss, puede cargar scss en ts.

kemsky
fuente
Esto funcionó para mí, pero me resultó un poco difícil de seguir. Proporcione nombres de archivo de ejemplo para el módulo declarado (.d.ts) y la hoja de estilo (.scss). También sería útil si proporcionara un código .scss de ejemplo y cómo accedería a él. Pude usar expresiones regulares, pero un archivo .scss más complicado podría ser más difícil de identificar de esa manera.
Todd
2

Tengo un enfoque relativamente simple para ti:

Separe el node-sasspaso del ng buildpaso y use los .cssarchivos generados en lugar de los sassarchivos en su aplicación angular.

Esto tiene dos ventajas:

  • no es necesario modificar y editar ningún módulo de nodo
  • control total sobre cómo se compila el sass

Para la implementación, seguiría de la siguiente manera:

  1. agregue ./node_modules/.bin/node-sass --importer node_modules/node-sass-json-importer/dist/cli.js --recursive ./src --output ./srca las secuencias de comandos en su package.jsoneg con el nombre build-sass. Puede ajustar este comando para incluir solo los archivos sass para los que necesita el modo recursivo (asegúrese de ignorarlos en angular.json, para que no se compilen dos veces).
  2. ejecute el comando una vez npm run build-sasspara generar los .cssarchivos en el proyecto.
  3. cambiar referencias en componentes angulares donde sea necesario del .sassa.css
  4. (opcionalmente) agregue un comando conveniente npm run build-sass && ng buildcomo compileen su package.json que puede ejecutar cuando quiera construir todo el proyecto.

Si bien este enfoque es relativamente simple, tiene algunos inconvenientes.

  • para cualquier componente en el que desee utilizar el CSS, la función de recarga en caliente ng serverequerirá que ejecute su npm run build-sasspara ver los cambios que realizó en sus estilos en tiempo real
  • su proyecto se verá un poco más desordenado, ya que hay .scssy .cssarchivos para el mismo componente en la /srccarpeta de la cual el .cssse genera. Deberá asegurarse (por ejemplo, agregando un sufijo o comentario) de que nadie edite accidentalmente lo generado .cssy que esos cambios se anulen.

Otros enfoques casi siempre implicarían editar en gran medida los existentes o escribir su propio compilador de paquetes web.

kacase
fuente