Skip to content

Loading files from css. #1553

Closed
Closed
@gwainor

Description

@gwainor

Can you reproduce the problem with latest npm?

Yes.

Description

Font Awesome is installed with npm. I am importing the it from scss:
@import '~font-awesome/css/font-awesome.min.css';

In react-scripts 0.8.2 this was working without a problem. Fonts were loading correctly.
When I check the loaded css, I see that url() of font face replaced correctly with /static/media...

Note: this also happens when importing font with @font-face.

NOTE2: also images cannot bi loaded from scss files.

NOTE3: importing from css or scss files does not work. Files emitted on webpack but I cannot see them from chrome devtool. But importing from JS works.

Expected behavior

Fonts and images which is defined in css or scss should load from browser correctly.

Actual behavior

Fonts and images are not loading from browser on render. For normal fonts (not icon fonts) I imported from google and working fine. But when I try to import from css as local file, It is not loading on render. If I enter the url of the media to browser, I can reach it.

Any import or url() call does not get the files.

Environment

  1. npm ls react-scripts (if you haven’t ejected): Ejected

  2. node -v: v6.9.2

  3. npm -v: 4.2.0

  4. Operating system: Windows 10

  5. Browser and version: Chrome 56

Reproducible Demo

Freshly installed and ejected react-scripts:

package.json

{
  "name": "site",
  "version": "0.1.0",
  "private": true,
  "devDependencies": {
    "autoprefixer": "6.7.2",
    "babel-core": "6.22.1",
    "babel-eslint": "7.1.1",
    "babel-jest": "18.0.0",
    "babel-loader": "6.2.10",
    "babel-preset-react-app": "^2.1.0",
    "babel-runtime": "^6.20.0",
    "case-sensitive-paths-webpack-plugin": "1.1.4",
    "chalk": "1.1.3",
    "connect-history-api-fallback": "1.3.0",
    "cross-spawn": "4.0.2",
    "css-loader": "0.26.1",
    "detect-port": "1.0.1",
    "dotenv": "2.0.0",
    "eslint": "3.8.1",
    "eslint-config-react-app": "^0.5.1",
    "eslint-loader": "1.6.0",
    "eslint-plugin-flowtype": "2.21.0",
    "eslint-plugin-import": "2.0.1",
    "eslint-plugin-jsx-a11y": "2.2.3",
    "eslint-plugin-react": "6.4.1",
    "extract-text-webpack-plugin": "^2.0.0-rc.3",
    "file-loader": "0.10.0",
    "filesize": "3.3.0",
    "fs-extra": "0.30.0",
    "gzip-size": "3.0.0",
    "html-webpack-plugin": "^2.28.0",
    "http-proxy-middleware": "0.17.3",
    "jest": "18.1.0",
    "json-loader": "0.5.4",
    "jsx-control-statements": "^3.1.5",
    "node-sass": "^4.5.0",
    "object-assign": "4.1.1",
    "postcss-loader": "1.2.2",
    "promise": "7.1.1",
    "react-dev-utils": "^0.5.0",
    "react-hot-loader": "^3.0.0-beta.6",
    "recursive-readdir": "2.1.0",
    "redux-logger": "^2.8.1",
    "sass-loader": "^5.0.1",
    "strip-ansi": "3.0.1",
    "style-loader": "0.13.1",
    "url-loader": "0.5.7",
    "webpack": "^2.2.1",
    "webpack-dev-server": "^2.3.0",
    "webpack-manifest-plugin": "1.1.0",
    "whatwg-fetch": "2.0.2"
  },
  "dependencies": {
    "classnames": "^2.2.5",
    "font-awesome": "^4.7.0",
    "normalize-css": "^2.3.1",
    "react": "^15.4.2",
    "react-dom": "^15.4.2",
    "react-helmet": "^4.0.0",
    "react-redux": "^5.0.2",
    "react-router": "^3.0.2",
    "react-router-redux": "^4.0.8",
    "redux": "^3.6.0",
    "redux-thunk": "^2.2.0"
  },
  "scripts": {
    "start": "node scripts/start.js",
    "build": "node scripts/build.js",
    "test": "node scripts/test.js --env=jsdom"
  },
  "jest": {
    "collectCoverageFrom": [
      "src/**/*.{js,jsx}"
    ],
    "setupFiles": [
      "<rootDir>\\config\\polyfills.js"
    ],
    "testPathIgnorePatterns": [
      "<rootDir>[/\\\\](build|docs|node_modules|scripts)[/\\\\]"
    ],
    "testEnvironment": "node",
    "testURL": "http://localhost",
    "transform": {
      "^.+\\.(js|jsx)$": "<rootDir>/node_modules/babel-jest",
      "^.+\\.css$": "<rootDir>\\config\\jest\\cssTransform.js",
      "^(?!.*\\.(js|jsx|css|json)$)": "<rootDir>\\config\\jest\\fileTransform.js"
    },
    "transformIgnorePatterns": [
      "[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$"
    ],
    "moduleNameMapper": {
      "^react-native$": "react-native-web"
    }
  },
  "eslintConfig": {
    "extends": "react-app"
  }
}

config/webpack.config.dev.js

var autoprefixer = require('autoprefixer');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
var InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
var WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
var getClientEnvironment = require('./env');
var paths = require('./paths');

var publicPath = '/';
var publicUrl = '';
var env = getClientEnvironment(publicUrl);

var postCssConfig = {
  loader: 'postcss-loader',
  options: {
    ident: 'postcss', // https://webpack.js.org/guides/migrating/#complex-options
    plugins: function () {
      return [
        autoprefixer({
          browsers: [
            '>1%',
            'last 4 versions',
            'Firefox ESR',
            'not ie < 9', // React doesn't support IE8 anyway
          ]
        })
      ]
    }
  }
};

module.exports = {
  devtool: 'cheap-module-source-map',
  entry: [
    require.resolve('react-dev-utils/webpackHotDevClient'),
    require.resolve('./polyfills'),
    paths.appIndexJs
  ],
  output: {
    path: paths.appBuild,
    pathinfo: true,
    filename: 'static/js/bundle.js',
    publicPath: publicPath
  },
  resolve: {
    modules: [paths.appSrc, 'node_modules'].concat(paths.nodePaths),
    extensions: ['.js', '.json', '.jsx'],
    alias: {
      'react-native': 'react-native-web'
    }
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        enforce: 'pre',
        use: [{
          loader: 'eslint-loader'
        }],
        include: paths.appSrc
      },
      {
        exclude: [
          /\.html$/,
          /\.(js|jsx)$/,
          /\.css$/,
          /\.(sass|scss)$/,
          /\.json$/,
          /\.svg$/
        ],
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: 'static/media/[name].[hash:8].[ext]'
        }
      },
      {
        test: /\.(js|jsx)$/,
        include: paths.appSrc,
        loader: 'babel-loader',
        options: {
          cacheDirectory: true
        }
      },
      {
        test: /\.css$/,
        exclude: /\.module\.css$/,
        use: [
          'style-loader', {
            loader: 'css-loader',
            options: {
              sourceMap: true,
              importLoaders: 1
            }
          },
          postCssConfig
        ]
      },
      // Sass loader
      {
        test: /\.(sass|scss)$/,
        exclude: /\.module\.(sass|scss)$/,
        use: [
          'style-loader', {
            loader: 'css-loader',
            options: {
              sourceMap: true,
              importLoaders: 2
            }
          },
          postCssConfig, {
            loader: 'sass-loader',
            options: {
              sourceMap: true
            }
          }
        ]
      },
      // Css module loader
      {
        test: /\.module\.css$/,
        use: [
          'style-loader', {
            loader: 'css-loader',
            options: {
              modules: true,
              camelCase: true,
              sourceMap: true,
              importLoaders: 1,
              localIdentName: '[name]__[local]___[hash:base64:5]'
            }
          },
          postCssConfig
        ]
      },
      // Sass module loader
      {
        test: /\.module\.(sass|scss)$/,
        use: [
          'style-loader', {
            loader: 'css-loader',
            options: {
              modules: true,
              camelCase: true,
              sourceMap: true,
              importLoaders: 2,
              localIdentName: '[name]__[local]___[hash:base64:5]'
            }
          },
          postCssConfig, {
            loader: 'sass-loader',
            options: {
              sourceMap: true
            }
          }
        ]
      },
      {
        test: /\.svg$/,
        loader: 'file-loader',
        options: {
          name: 'static/media/[name].[hash:8].[ext]'
        }
      }
    ]
  },
  plugins: [
    new InterpolateHtmlPlugin(env.raw),
    new HtmlWebpackPlugin({
      inject: true,
      template: paths.appHtml,
    }),
    new webpack.DefinePlugin(env.stringified),
    new webpack.HotModuleReplacementPlugin(),
    new CaseSensitivePathsPlugin(),
    new WatchMissingNodeModulesPlugin(paths.appNodeModules)
  ],
  node: {
    fs: 'empty',
    net: 'empty',
    tls: 'empty'
  },
  performance: {
    hints: false
  }
};

index.js (this is where I import the style file which contains font-awesome import.)

// import { AppContainer } from 'react-hot-loader';
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { Router, browserHistory } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import routes from 'routes';
import configureStore from 'store/configureStore';
import 'index.scss';

const store = configureStore();
const history = syncHistoryWithStore(browserHistory, store);

const rootEl = document.getElementById('react-root');

render(
  <Provider store={store}>
    <Router history={history} routes={routes} />
  </Provider>,
  rootEl
);

index.scss

@import '~normalize-css/normalize.css';
@import url('https://fonts.googleapis.com/css?family=Lato:400,400i,700,700i|Quattrocento:400,700&subset=latin-ext');
@import '~font-awesome/css/font-awesome.min.css';
@import 'assets/styles/grid';
@import 'assets/styles/variables';

...

In some component:

import React, { Component } from 'react';
import cx from 'classnames';
import s from './style.module.scss';

class Navigation extends Component {
  render() {
    return (
      <section className={s.navigation}>
        <ul>
          <NavLink to="/about-me" text="About Me" icon="user" />
          <NavLink to="/projects" text="Projects" icon="briefcase" />
          <NavLink to="/blog" text="Blog" icon="pencil" />
          <NavLink to="/contact" text="Contact" icon="plane" />
        </ul>
      </section>
    );
  }
}

function NavLink(props) {
  return (
    <li className={s.navLink}>
      <a href={props.to}>
        <div className={s.icon}>
          <i className={cx('fa', `fa-${props.icon}`)} />
        </div>
        <div className={s.text}>{props.text}</div>
      </a>
    </li>
  );
}

export default Navigation;

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions