Angular: How to parse JSON variables into SCSS
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
.
Install packages
@angular-builders/custom-webpack
,node-sass-json-importer
andnode-sass
:npm i -D @angular-builders/custom-webpack node-sass-json-importer node-sass
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' } }, } ], }], }, }
Change
builder
to@angular-builders/custom-webpack:[architect-target]
and addcustomWebpackConfig
option tobuild
,serve
andtest
build targets insideangular.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
Another option is to use raw-loader
, it is available by default in angular-cli. This way you can load raw scss file into ts component:
// Adding `!!` to a request will disable all loaders specified in the configuration
import scss from '!!raw-loader!./config.scss';
console.info('scss', scss);
You have to declare module in .d.ts
file:
declare module '!!raw-loader!./*.scss';
Then you can extract any information you want.
So instead of loading JSON into scss you can load scss into ts.
I have a relatively simple approach for you:
Separate the node-sass
step form the ng build
step and use the generated .css
files instead of the sass
files in your angular app.
This has two advantages:
- no need to heavily tweak and edit any node-modules
- full control over how the sass is compiled
For the implementation i would go ahead as follows:
- add
./node_modules/.bin/node-sass --importer node_modules/node-sass-json-importer/dist/cli.js --recursive ./src --output ./src
to the scripts in yourpackage.json
e.g. with the namebuild-sass
. You can tweak this command to only include the sass files that you need the recursive mode for (make sure to ignore them in the angular.json, so they don't get compiled twice). - run the command once
npm run build-sass
in order to generate the.css
files in the project. - change references in angular components where needed from the
.sass
to.css
- (optionally) add a convenience command
npm run build-sass && ng build
ascompile
in your package.json which you can run whenever you want to build the whole project.
While this approach is relatively simple, it comes with a few drawbacks
- for any components where you want to use the css, the hot-reload feature of
ng serve
will require you to run yournpm run build-sass
to see any changes you made to your styles in real-time - your project will look a bit messier, as there are
.scss
and.css
files for the same component in the/src
folder of which the.css
is generated. You will need to make sure (e.g. by adding a suffix or comment) that noone accidentally edits the generated.css
and those changes get overridden.
Other approaches would almost always involve heavily editing existing or writing your own webpack compiler.