Bruno Quaresma
Bruno Quaresma

Reputation: 10667

Webpack - Export SASS (.scss) files

I have a package and i want export my SASS variables to other packages use it. Currently my all .scss files are compiles and put in /dist/main.css file. My webpack config:

var webpack = require('webpack');
var ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
  entry: ['./src/index.js'],
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'babel'
      },
      {
        test:   /\.(scss|sass|css)$/,
        loader: ExtractTextPlugin.extract("style", "css!sass")
      },
      {
        test: /\.(png|woff|woff2|eot|ttf|svg)$/,
        loader: 'url-loader?limit=10000&name=fonts/[hash].[ext]'
      },
      {
        test: /\.scss$/, loader: 'style!css!sass!sass-resources'
      }
    ]
  },
  resolve: {
    extensions: ['', '.js', '.jsx']
  },
  output: {
    path: __dirname + '/build',
    publicPath: '/',
    filename: 'index.js',
    library: 'Supernova',
    libraryTarget: 'umd'
  },
  externals: {
    'react': 'react',
    'react-dom': 'react-dom'
  },
  plugins: [
    new ExtractTextPlugin("[name].css")
  ]
};

My objective is create a package like bootstrap-sass.

Upvotes: 4

Views: 6879

Answers (2)

airtonix
airtonix

Reputation: 5154

If you want to make the variables you use within your sass files available to consumers of your published package, then you'll need to look at some special configuration for node-sass.

Currently (and as of the time you posted this) node-sass supports writing your own custom sass functions in javascript: https://github.com/sass/node-sass#functions--v300---experimental

This is untested, but we did this a while ago at a company i worked for...to do what you want, you'd need something like:

src/
  your-package.js
  your-styles.scss

tools/
  constants/
    colours.js

  webpack/
    ...
    base.sass.js
    base.js
    development.js
    production.js

  sass/
    functions/
      colours.js

# tools/webpack/base.sass.js

const Config = require('webpack-config').default

import {
  signature as ColourSignature,
  handler as ColourHandler
} from '@tools/sass/functions/colours

module.exports = new Config()
  .merge({
    module: {
      rules: [
        {
          test: /\.scss$/,
          use: [
            ...
            { loader: 'sass-loader',
              options: {
                sourceMap: true,
                functions: {
                  [ColourSignature]: ColourHandler
                }
              }
            },
          ]
        }
      ]
    }
  })

# src/your-package.js

import Colours from '@tools/constants/colours'
import "./your-styles.scss"

export default YourAwesomeComponent {
  static Colours = Colours
}

export const colours = Colours

# src/your-styles.scss

.your-awesome-component { 
  background-color: ColourGet(veganvomit, sobrightithurts);
}
# tools/sass/functions/colour.js

import Colours from '@tools/constants/colours'

export signature = 'ColourGet($name, $shade: default)'
export handler = function(name, shade) {
  const colour = Colours[name]

  if (!colour) return 

  if (typeof colour === 'string') return colour

  return colour[shade]
}
# tools/sass/constants/colours.js

export default {

  veganvomit: {
    sobrightithurts: "darkkhaki",
    light: "#D2691E",
    default: "#8B4513",
    somethingsomethingsomethingdarkside: "#000"
  }

}

So now when you publish your package, they can access sass variables from your default export YourAwesomeClass.Colours or they can import it directly `import { Colours } from 'your-awesome-package'

Upvotes: 2

D Story
D Story

Reputation: 134

I highly recommend using webpack-merge to separate out your Sass config to make it easy for other packages to use it. For your current config, I would do three things:

  1. Add webpack-merge to your project (npm i --save-dev webpack-merge).
  2. Put your Sass config into a separate file, named something like webpack.sass-config.js. Have it include the following:

    var ExtractTextPlugin = require('extract-text-webpack-plugin');
    
    exports.config = function(options) {
      return {
        module: {
          loaders: [
            {
                test:   /\.(scss|sass|css)$/,
                loader: ExtractTextPlugin.extract("style", "css!sass")
            },
            {
                test: /\.scss$/, loader: 'style!css!sass!sass-resources'
            }
          ]
        },
        plugins: [
          new ExtractTextPlugin("[name].css")
        ]
      }
    }
    
    // Side note: returning a function instead of a plain object lets
    // you pass optional parameters from your main config file. This
    // is useful if you want to make something like your compiled css
    // file name different for another Webpack project without having
    // to edit your Sass configuration file.
    
  3. Update your webpack.config.js to the following:

    var merge = require('webpack-merge');
    
    // import your separated Sass configuration
    var sassConfig = require('webpack.sass-config');
    
    // Define your common config for entry, output, JSX, fonts, etc.
    var common = {
      entry: ['./src/index.js'],
      module: {
        loaders: [
          {
            test: /\.jsx?$/,
            exclude: /node_modules/,
            loader: 'babel'
          },
          {
            test: /\.(png|woff|woff2|eot|ttf|svg)$/,
            loader: 'url-loader?limit=10000&name=fonts/[hash].[ext]'
          }
        ]
      },
      resolve: {
        extensions: ['', '.js', '.jsx']
      },
      output: {
        path: __dirname + '/build',
        publicPath: '/',
        filename: 'index.js',
        library: 'Supernova',
        libraryTarget: 'umd'
      },
      externals: {
        'react': 'react',
        'react-dom': 'react-dom'
      }
    };
    
    // Merge your common config and Sass config
    var config = merge(
        common,
        sassConfig.config()
    );
    
    // Export the merged configuration
    modules.exports = config;
    

Obviously, this can go far beyond just your Sass config. I use webpack-merge to separate my development config from my production config. This article on Survive JS is a great resource for how to make the most of your Webpack setup.

Upvotes: 0

Related Questions