35

Inside a scss file, I'm trying to import custom, widely used chunk of scss (in a React/SASS/Webpack stack).

So that I can use a shared mixin.

Let's say I'm creating an MyAdminButton and I want to import scss file that concerns all the buttons of the project. (It's custom scss, not vendor/external one).

It would look like this :

//this actually works but it is a code smell : what if the current file moves ?
@import "../../stylesheets/_common-btn-styles.scss";

.my-admin-btn {
    // here I can use a shared mixin defined in _common-btn-styles.scss
}

This sounds not good since if my scss file move, then everything is broken.

Thanks for your help

bdavidxyz
  • 2,492
  • 1
  • 20
  • 40
  • Because refactoring occurs quite frequently, espescially if I put the scss file next to my js file : put everything that relates to the same component in same folder is very useful. – bdavidxyz Mar 11 '16 at 10:26
  • I have both manual dirty-check and automated tests, but I'm looking for robustness here. I know I will move folder without any fear. – bdavidxyz Mar 11 '16 at 11:24
  • You can use the `-I` argument to specify an import path. See `man scss` for more information. – Klaus Aug 12 '16 at 11:22
  • @Klaus huh? How do you use CLI arguments in code? – shinzou Aug 09 '18 at 13:10

7 Answers7

34

Found. Actually you can configure sass-loader in webpack.config.json, as described here : https://github.com/jtangelder/sass-loader

Here is the relevant part :

sassLoader: {
   includePaths: [path.resolve(__dirname, "./some-folder")]
}
bdavidxyz
  • 2,492
  • 1
  • 20
  • 40
  • 13
    Where in the file did you place it? and did absolute path actually work? – shinzou Aug 09 '18 at 13:10
  • how i understood, that i should create react app not with npx create-react-app, instead of i should install all packages manual, and set up custom webpack. Only in this case can use it ? Or of i have already created app with create-react-app, can i just create webpack.config.js and use it there ? will it attach to main file a webpack of default react file ? Thx – Oleksii Oct 24 '22 at 20:12
  • what would be an example of an absolute path in the actual scss file? – vsync Jun 14 '23 at 15:45
6

If you use Create React App v3 which allows absolute imports you can use the tilde

@import "~theme/colors";
Mordechai
  • 15,437
  • 2
  • 41
  • 82
  • Works also for sass in Angular 11 – Julian Egner Mar 12 '21 at 16:31
  • Not a real solution unless you are starting a new project using specifically *CRA* (not recommended anymore). – vsync Jun 14 '23 at 13:43
  • @vsync CRA is indeed outdated, but it works with Next.js as well – Mordechai Jun 14 '23 at 21:33
  • This question is about Webpack and not a specific framework that does inaccessible magic (because it is a framework). People come here because they want to know how to configure their webpack (like me) – vsync Jun 14 '23 at 22:23
4

You could add stylesheets to the Webpack modules with resolve.modules

// webpack.config.js
const path = require('path')

module.exports = {
  // ...
  resolve: {
    modules: [
      'node_modules',
      path.join(__dirname, 'path/to/stylesheets'),
    ],
  },
}

And sass-loader allows you to import _common-btn-styles.scss from the modules. https://webpack.js.org/loaders/sass-loader/#resolving-import-at-rules

@import "~_common-btn-styles.scss";

.my-admin-btn {
  // Use the shared mixins
}
Chesare22
  • 81
  • 1
  • 3
4

Webpack 5

Configuration is different for webpack 5 as includePaths should be specified in the option sassOptions:

// Webpack config
{
  test: /\.scss$/,
  loader: 'sass-loader',
  options: {
    sassOptions: {
      includePaths: [path.resolve(__dirname, '<path to styles>')],
    },
  },
},

Webpack 4

I had to do so more research to solve this issue using other answers so here is my working solution:

// Webpack config
{
  test: /\.scss$/,
  loader: 'sass-loader',
  options: {
    includePaths: [path.resolve(__dirname, '<path to styles>')],
  },
},

Then in your scss file:

@import 'filename.scss'; // Imported from <path to styles> folder.

.style {
  //...
}
Baboo
  • 4,008
  • 3
  • 18
  • 33
4

In react-scripts latest version you can add a .env file at the project root with the variable SASS_PATH=node_modules:src.

To specify more directories you can add them to SASS_PATH separated by a : like path1:path2:path3

official doc

somesh sam
  • 152
  • 2
  • 8
2

If using the Dart Sass implementation with sass-loader, the options are slightly different.

The options for sassOptions are here

sassOptions: {
...
  loadPaths: [path.resolve(__dirname, '../src/')],
}
dmackerman
  • 2,938
  • 5
  • 26
  • 43
1

If you are using NextJS there is a simple implementation. You can read the documentation here.

In my case, I am using Tailwindcss and SASS, and here are the configuration files and sass files.

// next.config.js


const path = require('path');

/** @type {import('next').NextConfig} */
module.exports = {
  experimental: {
    appDir: true,
  },
  sassOptions: {
    // define the absolute path...
    includePaths: [path.join(__dirname, 'styles')],
  },
};

// styles/_components.sass

@import 'tailwindcss/components'

@layer components
  .flex-center
    @apply flex items-center justify-center
  .container
    @apply mx-auto px-3 max-w-xl sm:max-w-lg md:px-6 md:max-w-3xl


// styles/global.sass

@import 'tailwindcss/base'
@import 'tailwindcss/utilities'
@import 'components' // absolute import


// app/styles.module.sass

@import 'components' // absolute import

.header
  @apply container flex h-16 items-center justify-between sticky top-0

GrayGalaxy
  • 91
  • 7
  • I figured, that if you are using _PostCSS_, _TailwindCSS_ etc. you don't need to define sassOptions. PostCSS will take care of the paths. For my case, I configured absolute URLs in **tsconfig.json**, and using the import from its absolute path like: `@import 'style/components'` – GrayGalaxy Aug 01 '23 at 13:14