# SCSS Transpiling and Bundling
## SASS vs. SCSS
The difference is mostly syntactical. They have a very similar feature set and transpile/interpret down to CSS, however:
- `SCSS` is a superset of `CSS`, so therefore CSS` `is valid `SCSS`. You can therefore copy `CSS` from the browser straight into your `SCSS` file.
- Meanwhile `Sass` is it's own syntax relying heavily on strict indentation instead of curly brackets and semicolons like `SCSS/CSS`
## SASS/SCSS Compilers are written in JS
Therefore a JS Engine needs to be present to transpile to CSS.
A popular minifier and bundler for .NET Core is [WebOptimizer](https://github.com/ligershark/WebOptimizer). For it to [transpile SASS/SCSS](https://github.com/ligershark/WebOptimizer.sass) it requires a library such as [JavaScriptEngineSwitcher.Extensions.MsDependencyInjection](https://www.nuget.org/packages/JavaScriptEngineSwitcher.Extensions.MsDependencyInjection) which allows several different JS engines to be embedded in your solution.
## Mixing SCSS and CSS
WebOptimizer has several middleware methods to declare your bundles. Since SCSS is a superset of CSS, you can do the following:
```csharp
pipeline.AddScssBundle(
"/static/css/mybundle.css", //output CSS
"node_modules/bootstrap/dist/css/bootstrap.css",
"wwwroot/css/site.css",
"wwwroot/scss/bootstrap-custom.scss")
.UseContentRoot();
```
## Example ServicesConfiguration extension
```csharp
using JavaScriptEngineSwitcher.ChakraCore;
using JavaScriptEngineSwitcher.Extensions.MsDependencyInjection;
using Microsoft.AspNetCore.ResponseCompression;
using WebOptimizer;
namespace Services;
public static class ServicesConfiguration
{
public static void ConfigureWebOptimizer(this IServiceCollection services)
{
services.AddJsEngineSwitcher(
o => o.DefaultEngineName = ChakraCoreJsEngine.EngineName)
.AddChakraCore();
services.AddWebOptimizer(ConfigureBundles);
/**
Until ASP.NET Core 7:
The cache busted assets have a modified `Response Header: content-type`
from the default `application/javascript` to `text/javascript`, which
is not contained in the default ResponseCompressionDefaults.MimeTypes
before ASP.NET Core 7.0
https://github.com/ligershark/WebOptimizer#https-compression-considerations
*/
services.AddResponseCompression(options =>
{
options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
new[] { "text/javascript" }
);
});
}
private static Action<IAssetPipeline> ConfigureBundles => (pipeline) =>
{
pipeline.AddJavaScriptBundle(
"/static/js/scripts.js",
"node_modules/bootstrap/dist/js/bootstrap.bundle.js",
"wwwroot/js/site.js")
.UseContentRoot();
pipeline.AddScssBundle(
"/static/css/site.css",
"node_modules/bootstrap/dist/css/bootstrap.css",
"wwwroot/scss/bootstrap-custom.scss")
.UseContentRoot();
};
}
```
Usage in Program.cs:
```csharp
var builder = WebApplication.CreateBuilder(args);
var config = builder.Configuration;
//...
builder.Services.ConfigureWebOptimizer(); // <~~~~~~~~~~~~~~
var app = builder.Build();
app.UseHttpsRedirection();
app.UseResponseCompression(); // <~~~~~~~~~~~~~~
app.UseWebOptimizer(); // <~~~~~~~~~~~~~~
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
//...
app.Run();
```