11
votes

I have the following structure:

node_modules
  - my_component
    - font
    - scss
      - my_component.scss
src
  - my_app.js
  - my_app.scss

I'm trying to import the styles in my_component.scss. This file contains @font-face declarations with references to ../font/. So something like:

// my_component.scss
@font-face {
  font-family: 'Helvetica Neue';
  font-weight: $weight-medium;
  src: url('../font/font-file.eot');
}

In my_app.js I'm requiring the SCSS file associated with it. So

// my_app.js

require('./my_app.scss');

//other app-specific code

I'm my_app.scss, I'm importing my_component.scss:

// my_app.scss

import 'my_component';

and the sassConfig is set to resolve to node_modules/my_component/scss so that the import works.

My loader config uses sass-loader, resolve-url-loader and css-loader. Here's a snippet:

//loaders.js

loaders.push({
  test: /\.scss$/,
  loader: 'style!css?sourcemap!resolve-url!sass?sourceMap'
});

Here is what I observe:

  1. When I run webpack-dev-server, the url references resolve correctly
  2. However, when I run webpack with the same conf file, I get Module not found: Error: Cannot resolve 'file' or 'directory' ../font/font-file.ttf in src/font/

Things I've tried:

  1. Using a $font-path variable to refer to ../fonts and setting it to node_modules/my_components/font
  2. Checking the order of my loaders, updating my webpack version etc.

Update

My sassLoader config previously had configuration for node-sass-import-once. When I removed it, my font urls started resolving again, however my generated CSS contains a ton of duplicate styles.

node-sass is repeatedly importing each @import without doing any sort of deduping (I know it's not supposed to be able to do it by itself). But node-sass-import-once which is meant for this sort of thing, breaks resolve-url-loader.

Here are my questions:

  1. Why does node-sass-import-once break the Webpack resolve-url-loader?
  2. Is there any way to dedupe the imports Webpack and get generated CSS free of style duplication?
1

1 Answers

3
votes

Without seeing your Webpack config I can only hazard a guess but it looks like you are trying to import a CSS file from node_modules.

When you want to import CSS from node_modules you may have to use the ~. As sokra himself says in this issue:

css @import is relative to the current directory. For resolving "like a module" you can prefix ~.

So maybe something like @import `~module/my_component.scss`; might do the trick.

Resolving imports this way also solved an issue I had where x.css was required by x.js and imported by y.css when x.css imported some sass variable config. Using resolve.alias in Webpack config I could simply do something like:

// webpack.config.js
resolve: {
  alias: {
    styles: 'src/styles/'
  }
}

And then use the tilde to import:

// y.css
@import `~styles/x.scss

If this works then you needn't remove thenode-sass-import-once and everything should resolve correctly.