Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular: How to parse JSON variables into SCSS

Within an Angular application, I do D3 visuals through either plain D3 or Vega. There's also SCSS styling going on.

I'd like to be able to refer to the same global variables for styling from Javascript and from SCSS. JSON files do the trick very well for storing settings that I load into Typescript through a simple import statement. But how does one go about doing the same from SCSS ?

node-sass-json-importer seems like a good candidate but adding it to an Angular 9 CLI application isn't obvious to me.

This StackOverflow post brushed on the topic a while back, but it involved modifying resources under node_modules which is hardly sustainable.

There are also some inputs in the orginal doc as to how one can go about tweaking webpack in a non-Angular app. I do not know how to relate this to an Angular app built through the 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(),
          },
        },
      ],
    ],
  },
};
like image 654
BuZz Avatar asked Mar 03 '20 15:03

BuZz


1 Answers

You can do it without changing any node_modules files by using @angular-builders/custom-webpack to setup custom Webpack rules and as you mention node-sass-json-importer to import JSON files inside SCSS files.

You'll have to install node-sass for the implementation option because node-sass-json-importer is compatible with node-sass.

  1. Install packages @angular-builders/custom-webpack, node-sass-json-importer and node-sass:

    npm i -D @angular-builders/custom-webpack node-sass-json-importer node-sass
    
  2. Create Webpack config file (webpack.config.js) to the project root directory with the following contents:

    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. Change builder to @angular-builders/custom-webpack:[architect-target] and add customWebpackConfig option to build, serve and test build targets inside 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"
            },
            ...
          },
        },
        ...
      },
      ...
    }
    

Now you can include any .json file inside any component .scss file:

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"
}

I have created a Github repository with all these working that you can clone and test from here: 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
like image 189
Christos Lytras Avatar answered Oct 03 '22 22:10

Christos Lytras