Add SASS to a TypeScript project for Dataverse
In some of my recent blog posts, we learned how to set up a TypeScript project and how to add React and tests to it. Today we will learn how to add SASS to a TypeScript project for Dataverse.
The following configuration is working as of writing this blog post (February 2021). Everything in the Front-end space is evolving very fast. There might be stuff that is not working as described when you read the post. If you find something please let me know.
At the end of this post, you can find a “Summary” section where I list all the commands we executed and the configuration files we created. To have a quicker start and skip all the explanations you could directly go there.
You can find the project with all the configuration on GitHub.
What is SASS?
First of all, I would like to explain briefly what SASS is. SASS is a CSS pre-processor. It advances the syntax of CSS. Stylesheets written in one of the two “advanced” syntaxes will be processed and transpiled to regular CSS.
It’s like TypeScript is to JavaScript. You write in one “language” and transpile it to a language the browser understands.
I usually use the SCSS syntax which has the ability to nest selectors. This makes it easier to see which style is applied to which element. In addition to that, it will allow some kind of style grouping.
Every CSS written in a .scss-file is also valid SCSS.
There are a lot more features in SCSS in addition to the mentioned feature. Some of those are:
- Variables – Even though they are kind of available in CSS now as well
- Reference symbol
- Operators
- Modules
- Mixings
- Extension
- And many more
Scenario
Let’s assume we have a webresource we load from a SiteMap and is an own front end application within our Model-Driven app. Those sometimes get complex. Since one usually wants the same look and feel as the rest of the Model-Driven app the CSS can easily get very big. I find it a lot easier to handle big CSS files as SASS.
Objectives
The objectives of this post are to show how improve the handling of CSS in a TypeScript project for Dataverse.
This includes the following techniques
SCSS
As mentioned SCSS has some advantages over vanilla CSS. So we will learn how to use SCSS and how to transpile it to CSS.
We will use the sass npm package for that.
Webpack is able to transpile SCSS to CSS. Unfortunately we can not use that in our case. The reason is that Webpack is not able to handle SCSS files as an entry point. In addition to that it will include the CSS in the bundle.js file. Since we have “standalone” SCSS files which should result in a .css file, we can’t use Webpack for it.
Linting
A linter usually is basically a spellchecker for one’s JavaScript/TypeScript code. It scans the code and enforces semantic code rules. There are some for CSS (and SCSS) as well.
To achieve this we will use stylelint, which is the most common one. It also works for SCSS.
Compressing
To improve load time one could compress the generated CSS.
We will do that with the sass npm package as well.
Prerequisites
For this part we have the following prerequisites.
Software
As for my first two mentioned blog posts you need to have NodeJS and NPM installed on your machine. I do assume that is already the case, if not you can download it here.
I will use Visual Studio Code for everything related to TypeScript. One could of course use any other IDE.
Project
We will use the project created in my last blog post about adding React and Tests to a TypeScript project.
Files
For the test purpose we need one files.
demo.scss
This file should be created in the ts/src/scss folder and contain the following code.
body { text-align: left; h1 { text-decoration: underline; text-align: center; } }
As you can see the file has a nice nested structure, which makes it easier to determine where it will apply the styling. This structure is not valid CSS, though. So as mentioned earlier we have to transpile it to CSS.
Setup
Now that we sorted that out, let’s start adding SASS to a TypeScript project for Dataverse.
Install packages
First of all we have to install all the needed packages.
To do so we will open our front-end folder with Visual Studio Code and execute the following commands.
Open correct folder
In the Terminal (within VS Code) we go to the “ts” folder with the help of the following command.
cd ts
All the commands that follow will be executed in the Terminal within Visual Studio Code and within the “ts” folder.
Install sass
The first package we need is “sass“. It is the official npm package for sass and will transpile our .scss-files to css, as well as minify them.
npm install sass --save-dev
Install stylelint
As the next package, we need “stylelint“. This will implement some linting rules for our SCSS files to improve quality
npm install stylelint --save-dev
Install stylelint-config-standard
“stylelint-config-standard” contains, as the name says, a standard configuration for stylelint. This should be enough for the beginning. You could choose to add your own configuration to specify some custom guidelines you might have.
npm install stylelint-config-standard --save-dev
Install npm-run-all
We will use “npm-run-all” to run different npm scripts in one. This will help us to minimize the redundant configuration in our scripts in the package.json.
npm install npm-run-all --save-dev
Install all
Of course one could install all of those packages with only one command.
npm install sass stylelint stylelint-config-standard npm-run-all --save-dev
Configuration
After we have installed all the needed packages we have to configure everything to really add SASS to our TypeScript project for Dataverse.
Stylelint
The first configuration is to create the stylelint config-file. To do so we have to create a file “stylelintrc.json” in our root folder. Since we only want to use the installed standard configuration and don’t want to add additional stuff the following content will be enough.
{ "extends": "stylelint-config-standard" }
This would be the place where one could configure their own linting rules.
npm Scripts
This is the most tricky part of this implementation.
We will replace the whole “scripts” object within our “package.json” file with the following code block. I will explain it row by row
"scripts": { "test": "jest", "test-watch": "jest --watch", "build-ts-dev": "webpack --config webpack.config.dev.js", "build-ts-watch": "webpack --watch --config webpack.config.dev.js", "build-ts-prod": "webpack --config webpack.config.prod.js", "build-scss-only": "sass src/scss:../Webresources/css", "build-scss-dev": "npm-run-all lint-scss build-scss-only", "build-scss-prod": "npm-run-all lint-scss \"build-scss-only -- --style=compressed\"", "build-scss-watch": "npm-run-all \"build-scss-only -- --watch\"", "build-dev": "npm-run-all --parallel build-ts-dev build-scss-dev", "build-watch": "npm-run-all --parallel build-ts-watch build-scss-watch test-watch", "build": "npm-run-all test --parallel build-ts-prod build-scss-prod", "watch": "npm run build-watch", "format-ts": "prettier ./src/code/**/* --write", "lint-ts": "eslint ./src/code/**/* --fix", "lint-scss": "stylelint src/scss/**/*.{scss,sass} --fix" }
test & test-watch
Those where not changed from the previous implementation. They will run the TypeScript test, respectively re run them whenever something is changed.
build-ts-dev, build-ts-watch & build-ts-prod
These 3 commands where basically only renamed. We just added the “-ts” in between. Everything else is still the same. The run our different webpack configurations.
build-scss-only
This is the first new command. It will, as the name suggests, only run the transpilation of SCSS to CSS.
To do so it uses the sass npm package. the input folder is “src/scss” and the output folder is “../Webresources/css”.
We created this as a separate command to be able to reuse it within the others.
build-scss-dev
It will transpile our files in development mode (not compressed). Before that we would like to run stylelint on our files. Therefore we execute two of our scripts (lint-scss and build-scss-only) in sequence using the npm-run-all package.
build-scss-prod
This script is basically the same as the build-scss-dev with one addition. It adds a configuration to our sass script to compress the files.
build-scss-watch
It will run our build-scss-only script with an additional –watch parameter. This will result in a watch job which retranspiles our SCSS files whenever something changes in them.
build-dev
We had the same script before. Now it is calling build dev commands for both TypeScript and SCSS using the npm-run-all package. Those two will even be executed in parallel to speed up the process.
build-watch
It will run all 3 watch scripts we have. For TypeScript, SCSS and Tests. It uses npm-run-all for that.
build
It could also be called “build-prod”, but since this is the one that should be run in the end I thought just “build” would fit better. It executes the build prod commands for both TypeScript and SCSS in parallel. Before doing so it will run the TypeScript tests to make sure everything works as expected.
watch
This command is only an alias to “build-watch” to make it easier to remember and faster to type.
format-ts
We had this one earlier. It was just renamed from “format”.
lint-ts
This one was also just renamed from just “lint” to “lint-ts” to make it clear what will happen.
lint-scss
Last but not least is our linting for the SCSS-files. It calles stylelint with src/scss (and every sub folder) as the input. It only takes files with the endings .scss or .sass in consideration. The last parameter, –fix, is to fix issues while executing.
VS Code
Normally one would like to run stylelint while developing and not only when transpiling the SCSS files. This can be achieved by installing a plugin to VS code.
This should work immediately. VS Code has a build in CSS/SCSS linter, which isn’t as powerful as stylelint. To prevent that both linters highlight the same mistake we have to deactivate the one from VS Code. To do so we change the “settings.json” file within the “.vscode” folder which should be located in the project root folder and add the following rows.
"css.validate": false, "less.validate": false, "scss.validate": false
This manual one-time configuration has to be done by every developer since the .vscode folder will not be included in your repo.
Conclusion
As you could see add SASS to a TypeScript project for Dataverse isn’t very hard.
A bit tricky is the script’s part in the package.json. It gets so complex if one is not using one method to transpile everything (Typescript using webpack and SCSS using the sass package).
With that, your transpiled CSS-Files will be within your Webresources folder where they could be picked up of some automated deployment process (using Sparkl for example).
I hope this article helped you. Feel free to contact me if you have any questions. I am always happy to help.
Summary
In this chapter, you can find all the commands and files to execute/create/modify to add SASS to a TypeScript project for Dataverse. The intention is to give a very short quick start guide without any explanation.
Install packages
Open the project folder with VS Code, cd into the ts folder with the Terminal within VS Code and execute the following commands.
npm install sass stylelint stylelint-config-standard npm-run-all --save-dev
Install VS Code Extensions
Install the following extension
Configuration
Add the following files, or if present change the content to the following.
package.json
Replace the scripts part with the following
"scripts": { "test": "jest", "test-watch": "jest --watch", "build-ts-dev": "webpack --config webpack.config.dev.js", "build-ts-watch": "webpack --watch --config webpack.config.dev.js", "build-ts-prod": "webpack --config webpack.config.prod.js", "build-scss-only": "sass src/scss:../Webresources/css", "build-scss-dev": "npm-run-all lint-scss build-scss-only", "build-scss-prod": "npm-run-all lint-scss \"build-scss-only -- --style=compressed\"", "build-scss-watch": "npm-run-all \"build-scss-only -- --watch\"", "build-dev": "npm-run-all --parallel build-ts-dev build-scss-dev", "build-watch": "npm-run-all --parallel build-ts-watch build-scss-watch test-watch", "build": "npm-run-all test --parallel build-ts-prod build-scss-prod", "watch": "npm run build-watch", "format-ts": "prettier ./src/code/**/* --write", "lint-ts": "eslint ./src/code/**/* --fix", "lint-scss": "stylelint src/scss/**/*.{scss,sass} --fix" }
stylelintrc.json
Create a new file in your ts folder called “stylelintrc.json”. Add the following content to it.
{ "extends": "stylelint-config-standard" }
.vscode/settings.json
Add the following to the settings.json file which should be located in the .vscode folder in the project root folder
"css.validate": false, "less.validate": false, "scss.validate": false
You can also subscribe and get new blog posts emailed to you directly.
Hey Benedikt, nice article. I would love to see a bit more reasoning why I should use SCSS. A bit of class nesting does not catch me. Give me “inheritance”, variables, calculations and all that.
Hej, Thank you so much. Sure I can add a bit more of that. To be honest the class nesting was the feature that caught me it makes the code so much cleaner and easier to understand.