Search code examples
csssass

What is the purpose of entrypoint files in Sass?


I'm new to using IBM's Carbon Design System. We have some legacy applications - which don't use frameworks like React - so we've opted to use the @carbon/styles package.

When reading the docs it says

You can bring in all the styles for the Carbon Design System by including @carbon/styles in your Sass files. For example: @use '@carbon/styles';

I've created a Sass file, app.scss, which I'm compiling to app.css and linking that in my webpage.

If I place the following into app.scss

@use '@carbon/styles';

.test {
    color: colors.$blue-50;
}

then compile it (using sass app.scss app.css) I get this error message:

Error: There is no module with the namespace "colors". color: colors.$blue-50;

But if I change the Sass file so it has this - and recompile - there are no errors. I can use things like <p class="test">Test</p> in my webpage and get the word "Test" in blue, which is the expected result.

@use '@carbon/styles';
@use '@carbon/styles/scss/colors';

.test {
    color: colors.$blue-50;
}

The difference between these 2 files is that the second one has @use '@carbon/styles/scss/colors';.

I don't understand this because it says in the docs that @use '@carbon/styles'; is so you can "bring in all the styles".

In node_modules/@carbon/styles/index.scss it has this

@forward 'scss/colors'

The Sass documentation for @forward says

It loads the module at the given URL just like @use, but it makes the public members of the loaded module available to users of your module as though they were defined directly in your module. Those members aren’t available in your module, though—if you want that, you’ll need to write a @use rule as well. Don’t worry, it’ll only load the module once!

This is incredibly confusing. The first sentence makes it sounds like scss/colors can be referenced directly by app.scss, whereas the second sentence suggests the opposite.

In any case I don't understand what @use '@carbon/styles'; is actually letting me do. It suggests that this provides a single entrypoint to all of these files which it refers to. But then you have to reference them manually afterwards to actually use them in your own Sass file.

What is the purpose of the entrypoint file given its scope is so limited?

I'm using sass 1.71.1 compiled with dart2js 3.3.0 for reference.


Solution

  • The Sass rule @use loads another file as a module and gives it a namespace.

    As per the Sass docs:

    By default, a module’s namespace is just the last component of its URL without a file extension. ...

    So in your first example you use the whole library, @use '@carbon/styles'; and the last component of its URL is styles.
    In order to get the variable $blue-50 you would have to use the namespace styles

    @use '@carbon/styles';
    
    .test {
        color: styles.$blue-50;
    }
    

    In your second example, you are using two modules (or a bunch of modules combined into one "module", in case of carbon/styles) and therefore got two namespaces:

    1. @use '@carbon/styles'; -> Namespace: styles
    2. @use '@carbon/styles/scss/colors'; -> Namespace: colors

    So in your second case, styles.$blue-50 and colors.$blue-50 both reference the same variable.


    One additional note on @use, you can actually choose what the namespace for a used module should be.

    @use '@carbon/styles' as carbon;`
    

    as carbon tells the compiler, that the module styles should be loaded under the namespace carbon. Then you can reference the package with color: carbon.$blue-50;.

    This way, you instantly know which package / module was used when coming back to your project after month (or years), as styles is a pretty generic word.