Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webpack Sass import URL resolving

I'm building a web application using React and Webpack with this directory structure

/src
    /components
    /containers
        App.js
        App.scss
    /assets
        /fonts
            MarkOT/
                MarkOT.css
                MarkOT.eot
                ...
            ...
        /images
    /styles
        _vars.scss

I'm trying to import _vars.scss from App.scss like so:

@import '../../styles/vars';

and that works just fine. What doesn't work is if I have imports inside of _vars.scss

@import "../assets/fonts/MarkOT-ExtraLight/MarkOT-ExtraLight.css";
@import "../assets/fonts/MarkOT-Light/MarkOT-Light.css";
@import "../assets/fonts/MarkOT/MarkOT.css";
@import "../assets/fonts/MarkOT-Medium/MarkOT-Medium.css";
@import "../assets/fonts/MarkOT-Book/MarkOT-Book.css";

where those imports should resolve relative to the styles folder. Instead the imports are getting resolved relative to containers/App/App.scss. I read on sass-loaders website that one should use the resolve-url-loader to solve this issue but I can't get it to work.

An import to like @import "~../assets/fonts/MarkOT-ExtraLight/MarkOT-ExtraLight.css"; just contains a @font-face declaration:

@font-face {
  font-family: 'MarkOT';
  src: url('MarkOT.eot?#iefix') format('embedded-opentype'),  url('MarkOT.otf')  format('opentype'),
     url('MarkOT.woff') format('woff'), url('MarkOT.ttf')  format('truetype'), url('MarkOT.svg#MarkOT') format('svg');
  font-weight: normal;
  font-style: normal;
}

Here's my webpack config:

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

module.exports = {
  devtool: 'source-map',
  context: path.resolve(__dirname, '..'),
  entry: {
      app: path.resolve(__dirname, '../src/client/index.js'),
      vendors: ['react', 'react-dom', 'react-router']
  },
  output: {
    path: path.resolve(__dirname, '../dist'),
    pathInfo: true,
    filename: 'bundle.js',
    css: 'main.css'
  },
  module: {
     preLoaders: [
        {
         test: /\.js?$/,
         loader: "eslint-loader",
         exclude: /node_modules/
        }
    ],
     loaders: [
      {
        test: /src\/.+.js$/,
        exclude: /node_modules/,
        loader: 'babel',
        query: {
          presets: ['react', 'es2015', 'stage-0']
        }
      },
      { test: /\.jpe?g$|\.gif$|\.png$|\.svg$|\.woff$|\.ttf$/, loader: "file-loader" },
      { test: /\.scss?$/, loader: ExtractTextPlugin.extract('style', '!css?sourceMap!resolve-url!sass?outputStyle=expanded&sourceMap&includePaths[]=' + encodeURIComponent(require('node-bourbon').includePaths) +
    '&includePaths[]=' + encodeURIComponent(require('node-neat').includePaths[1])) }
    ]
  },
  resolve: {
    modulesDirectories: [
      'src',
      'node_modules'
    ]
   },
   plugins: [
     new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js'),
     new ExtractTextPlugin('main.css')
  ]
 };

This line in particular is for handling my styles:

{ test: /\.scss?$/, loader: ExtractTextPlugin.extract('style', '!css?sourceMap!resolve-url!sass?outputStyle=expanded&sourceMap&includePaths[]=' + encodeURIComponent(require('node-bourbon').includePaths) +
    '&includePaths[]=' + encodeURIComponent(require('node-neat').includePaths[1])) }

As it said on the resolve-url-loader website, I included source maps in both the sass and css loaders (as well as included paths to the bourbon and neat libraries, all of which loads fine).

Is there something blatantly obvious I'm missing that I can't see?

EDIT:

I was able to workaround the issue by creating a _font.scss file in the same directory as _var.scss, moving all the @font-face declarations into _font.scss and then replacing all the instances of url with require inside the font declarations.

I don't love that I wasn't able to figure out why the other one was working but it works so that's good. What I found interesting is that url didn't work, I was under the impression that css-loader took care of that.

like image 311
barndog Avatar asked Dec 10 '15 00:12

barndog


People also ask

How do I import a SCSS file into Webpack?

First, SCSS is converted to CSS ( sass-loader ), then run through css-loader to process @import() , url() etc, then style-loader (to be appended to the DOM) or Mini CSS Extract Plugin to externalise the CSS when doing a production build.

Is Sass-loader deprecated?

Is Sass-loader deprecated? Warning: LibSass and Node Sass are deprecated. While they will continue to receive maintenance releases indefinitely, there are no plans to add additional features or compatibility with any new CSS or Sass features.

Is sass the same as SCSS?

SASS (Syntactically Awesome Style Sheets) is a pre-processor scripting language that will be compiled or interpreted into CSS. SassScript is itself a scripting language whereas SCSS is the main syntax for the SASS which builds on top of the existing CSS syntax.


1 Answers

in your webpack.config

  resolve: {
    modulesDirectories: [ 'src', 'node_modules' ],
    alias: {
      styles: /*put the base folder of your styles here*/
    }
  }

and then in your stylesheet import using a @styles then the relative path

@import '~styles/yourStyle.scss';
like image 84
Mostafa Fateen Avatar answered Sep 27 '22 19:09

Mostafa Fateen