Giter Site home page Giter Site logo

css-loader's Introduction

npm node tests coverage discussion size

css-loader

The css-loader interprets @import and url() like import/require() and will resolve them.

Getting Started

Warning

To use the latest version of css-loader, webpack@5 is required

To begin, you'll need to install css-loader:

npm install --save-dev css-loader

or

yarn add -D css-loader

or

pnpm add -D css-loader

Then add the plugin to your webpack config. For example:

file.js

import * as css from "file.css";

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ["style-loader", "css-loader"],
      },
    ],
  },
};

And run webpack via your preferred method.

If, for one reason or another, you need to extract CSS as a file (i.e. do not store CSS in a JS module) you might want to check out the recommend example.

Options

url

Type:

type url =
  | boolean
  | {
      filter: (url: string, resourcePath: string) => boolean;
    };

Default: true

Allow to enable/disables handling the CSS functions url and image-set. If set to false, css-loader will not parse any paths specified in url or image-set. A function can also be passed to control this behavior dynamically based on the path to the asset. Starting with version 4.0.0, absolute paths are parsed based on the server root.

Examples resolutions:

url(image.png) => require('./image.png')
url('image.png') => require('./image.png')
url(./image.png) => require('./image.png')
url('./image.png') => require('./image.png')
url('http://dontwritehorriblecode.com/2112.png') => require('http://dontwritehorriblecode.com/2112.png')
image-set(url('image2x.png') 1x, url('image1x.png') 2x) => require('./image1x.png') and require('./image2x.png')

To import assets from a node_modules path (include resolve.modules) and for alias, prefix it with a ~:

url(~module/image.png) => require('module/image.png')
url('~module/image.png') => require('module/image.png')
url(~aliasDirectory/image.png) => require('otherDirectory/image.png')

boolean

Enable/disable url() resolving.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          url: true,
        },
      },
    ],
  },
};

object

Allow to filter url(). All filtered url() will not be resolved (left in the code as they were written).

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          url: {
            filter: (url, resourcePath) => {
              // resourcePath - path to css file

              // Don't handle `img.png` urls
              if (url.includes("img.png")) {
                return false;
              }

              // Don't handle images under root-relative /external_images/
              if (/^\/external_images\//.test(path)) {
                return false;
              }

              return true;
            },
          },
        },
      },
    ],
  },
};

import

Type:

type importFn =
  | boolean
  | {
      filter: (
        url: string,
        media: string,
        resourcePath: string,
        supports?: string,
        layer?: string,
      ) => boolean;
    };

Default: true

Allows to enables/disables @import at-rules handling. Control @import resolving. Absolute urls in @import will be moved in runtime code.

Examples resolutions:

@import 'style.css' => require('./style.css')
@import url(style.css) => require('./style.css')
@import url('style.css') => require('./style.css')
@import './style.css' => require('./style.css')
@import url(./style.css) => require('./style.css')
@import url('./style.css') => require('./style.css')
@import url('http://dontwritehorriblecode.com/style.css') => @import url('http://dontwritehorriblecode.com/style.css') in runtime

To import styles from a node_modules path (include resolve.modules) and for alias, prefix it with a ~:

@import url(~module/style.css) => require('module/style.css')
@import url('~module/style.css') => require('module/style.css')
@import url(~aliasDirectory/style.css) => require('otherDirectory/style.css')

boolean

Enable/disable @import resolving.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          import: true,
        },
      },
    ],
  },
};

object

filter

Type:

type filter = (url: string, media: string, resourcePath: string) => boolean;

Default: undefined

Allow to filter @import. All filtered @import will not be resolved (left in the code as they were written).

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          import: {
            filter: (url, media, resourcePath) => {
              // resourcePath - path to css file

              // Don't handle `style.css` import
              if (url.includes("style.css")) {
                return false;
              }

              return true;
            },
          },
        },
      },
    ],
  },
};

modules

Type:

type modules =
  | boolean
  | "local"
  | "global"
  | "pure"
  | "icss"
  | {
      auto: boolean | regExp | ((resourcePath: string) => boolean);
      mode:
        | "local"
        | "global"
        | "pure"
        | "icss"
        | ((resourcePath) => "local" | "global" | "pure" | "icss");
      localIdentName: string;
      localIdentContext: string;
      localIdentHashSalt: string;
      localIdentHashFunction: string;
      localIdentHashDigest: string;
      localIdentRegExp: string | regExp;
      getLocalIdent: (
        context: LoaderContext,
        localIdentName: string,
        localName: string,
      ) => string;
      namedExport: boolean;
      exportGlobals: boolean;
      exportLocalsConvention:
        | "as-is"
        | "camel-case"
        | "camel-case-only"
        | "dashes"
        | "dashes-only"
        | ((name: string) => string);
      exportOnlyLocals: boolean;
      getJSON: ({
        resourcePath,
        imports,
        exports,
        replacements,
      }: {
        resourcePath: string;
        imports: object[];
        exports: object[];
        replacements: object[];
      }) => Promise<void> | void;
    };

Default: undefined

Allows to enable/disable CSS Modules or ICSS and setup configuration:

  • undefined - enable CSS modules for all files matching /\.module\.\w+$/i.test(filename) and /\.icss\.\w+$/i.test(filename) regexp.
  • true - enable CSS modules for all files.
  • false - disables CSS Modules for all files.
  • string - disables CSS Modules for all files and set the mode option, more information you can read here
  • object - enable CSS modules for all files, if modules.auto option is not specified, otherwise the modules.auto option will determine whether if it is CSS modules or not, more information you can read here

The modules option enables/disables the CSS Modules specification and setup basic behaviour.

Using false value increase performance because we avoid parsing CSS Modules features, it will be useful for developers who use vanilla css or use other technologies.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: true,
        },
      },
    ],
  },
};

Features

Scope

Using local value requires you to specify :global classes. Using global value requires you to specify :local classes. Using pure value requires selectors must contain at least one local class or id.

You can find more information here.

Styles can be locally scoped to avoid globally scoping styles.

The syntax :local(.className) can be used to declare className in the local scope. The local identifiers are exported by the module.

With :local (without brackets) local mode can be switched on for this selector. The :global(.className) notation can be used to declare an explicit global selector. With :global (without brackets) global mode can be switched on for this selector.

The loader replaces local selectors with unique identifiers. The chosen unique identifiers are exported by the module.

:local(.className) {
  background: red;
}
:local .className {
  color: green;
}
:local(.className .subClass) {
  color: green;
}
:local .className .subClass :global(.global-class-name) {
  color: blue;
}
._23_aKvs-b8bW2Vg3fwHozO {
  background: red;
}
._23_aKvs-b8bW2Vg3fwHozO {
  color: green;
}
._23_aKvs-b8bW2Vg3fwHozO ._13LGdX8RMStbBE9w-t0gZ1 {
  color: green;
}
._23_aKvs-b8bW2Vg3fwHozO ._13LGdX8RMStbBE9w-t0gZ1 .global-class-name {
  color: blue;
}

Note

Identifiers are exported

exports.locals = {
  className: "_23_aKvs-b8bW2Vg3fwHozO",
  subClass: "_13LGdX8RMStbBE9w-t0gZ1",
};

CamelCase is recommended for local selectors. They are easier to use within the imported JS module.

You can use :local(#someId), but this is not recommended. Use classes instead of ids.

Composing

When declaring a local classname you can compose a local class from another local classname.

:local(.className) {
  background: red;
  color: yellow;
}

:local(.subClass) {
  composes: className;
  background: blue;
}

This doesn't result in any change to the CSS itself but exports multiple classnames.

exports.locals = {
  className: "_23_aKvs-b8bW2Vg3fwHozO",
  subClass: "_13LGdX8RMStbBE9w-t0gZ1 _23_aKvs-b8bW2Vg3fwHozO",
};
._23_aKvs-b8bW2Vg3fwHozO {
  background: red;
  color: yellow;
}

._13LGdX8RMStbBE9w-t0gZ1 {
  background: blue;
}
Importing

To import a local classname from another module.

Note

We strongly recommend that you specify the extension when importing a file, since it is possible to import a file with any extension and it is not known in advance which file to use.

:local(.continueButton) {
  composes: button from "library/button.css";
  background: red;
}
:local(.nameEdit) {
  composes: edit highlight from "./edit.css";
  background: red;
}

To import from multiple modules use multiple composes: rules.

:local(.className) {
  composes:
    edit highlight from "./edit.css",
    button from "module/button.css",
    classFromThisModule;
  background: red;
}

or

:local(.className) {
  composes: edit highlight from "./edit.css";
  composes: button from "module/button.css";
  composes: classFromThisModule;
  background: red;
}
Values

You can use @value to specific values to be reused throughout a document.

We recommend use prefix v- for values, s- for selectors and m- for media at-rules.

@value v-primary: #BF4040;
@value s-black: black-selector;
@value m-large: (min-width: 960px);

.header {
  color: v-primary;
  padding: 0 10px;
}

.s-black {
  color: black;
}

@media m-large {
  .header {
    padding: 0 20px;
  }
}

boolean

Enable CSS Modules features.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: true,
        },
      },
    ],
  },
};

string

Enable CSS Modules features and setup mode.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          // Using `local` value has same effect like using `modules: true`
          modules: "global",
        },
      },
    ],
  },
};

object

Enable CSS Modules features and setup options for them.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            mode: "local",
            auto: true,
            exportGlobals: true,
            localIdentName: "[path][name]__[local]--[hash:base64:5]",
            localIdentContext: path.resolve(__dirname, "src"),
            localIdentHashSalt: "my-custom-hash",
            namedExport: true,
            exportLocalsConvention: "as-is",
            exportOnlyLocals: false,
            getJSON: ({ resourcePath, imports, exports, replacements }) => {},
          },
        },
      },
    ],
  },
};
auto

Type:

type auto =
  | boolean
  | regExp
  | ((
      resourcePath: string,
      resourceQuery: string,
      resourceFragment: string,
    ) => boolean);

Default: undefined

Allows auto enable CSS modules/ICSS based on the filename, query or fragment when modules option is object.

Possible values:

  • undefined - enable CSS modules for all files.
  • true - enable CSS modules for all files matching /\.module\.\w+$/i.test(filename) and /\.icss\.\w+$/i.test(filename) regexp.
  • false - disables CSS Modules.
  • RegExp - enable CSS modules for all files matching /RegExp/i.test(filename) regexp.
  • function - enable CSS Modules for files based on the filename satisfying your filter function check.
boolean

Possible values:

  • true - enables CSS modules or interoperable CSS format, sets the modules.mode option to local value for all files which satisfy /\.module(s)?\.\w+$/i.test(filename) condition or sets the modules.mode option to icss value for all files which satisfy /\.icss\.\w+$/i.test(filename) condition
  • false - disables CSS modules or interoperable CSS format based on filename

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            auto: true,
          },
        },
      },
    ],
  },
};
RegExp

Enable CSS modules for files based on the filename satisfying your regex check.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            auto: /\.custom-module\.\w+$/i,
          },
        },
      },
    ],
  },
};
function

Enable CSS modules for files based on the filename, query or fragment satisfying your filter function check.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            auto: (resourcePath, resourceQuery, resourceFragment) => {
              return resourcePath.endsWith(".custom-module.css");
            },
          },
        },
      },
    ],
  },
};
mode

Type:

type mode =
  | "local"
  | "global"
  | "pure"
  | "icss"
  | ((
      resourcePath: string,
      resourceQuery: string,
      resourceFragment: string,
    ) => "local" | "global" | "pure" | "icss");

Default: 'local'

Setup mode option. You can omit the value when you want local mode.

Controls the level of compilation applied to the input styles.

The local, global, and pure handles class and id scoping and @value values. The icss will only compile the low level Interoperable CSS format for declaring :import and :export dependencies between CSS and other languages.

ICSS underpins CSS Module support, and provides a low level syntax for other tools to implement CSS-module variations of their own.

string

Possible values - local, global, pure, and icss.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            mode: "global",
          },
        },
      },
    ],
  },
};
function

Allows set different values for the mode option based on the filename, query or fragment.

Possible return values - local, global, pure and icss.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            // Callback must return "local", "global", or "pure" values
            mode: (resourcePath, resourceQuery, resourceFragment) => {
              if (/pure.css$/i.test(resourcePath)) {
                return "pure";
              }

              if (/global.css$/i.test(resourcePath)) {
                return "global";
              }

              return "local";
            },
          },
        },
      },
    ],
  },
};
localIdentName

Type:

type localIdentName = string;

Default: '[hash:base64]'

Allows to configure the generated local ident name.

For more information on options see:

Supported template strings:

  • [name] the basename of the resource
  • [folder] the folder the resource relative to the compiler.context option or modules.localIdentContext option.
  • [path] the path of the resource relative to the compiler.context option or modules.localIdentContext option.
  • [file] - filename and path.
  • [ext] - extension with leading ..
  • [hash] - the hash of the string, generated based on localIdentHashSalt, localIdentHashFunction, localIdentHashDigest, localIdentHashDigestLength, localIdentContext, resourcePath and exportName
  • [<hashFunction>:hash:<hashDigest>:<hashDigestLength>] - hash with hash settings.
  • [local] - original class.

Recommendations:

  • use '[path][name]__[local]' for development
  • use '[hash:base64]' for production

The [local] placeholder contains original class.

Note: all reserved (<>:"/\|?*) and control filesystem characters (excluding characters in the [local] placeholder) will be converted to -.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            localIdentName: "[path][name]__[local]--[hash:base64:5]",
          },
        },
      },
    ],
  },
};
localIdentContext

Type:

type localIdentContex = string;

Default: compiler.context

Allows to redefine basic loader context for local ident name.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            localIdentContext: path.resolve(__dirname, "src"),
          },
        },
      },
    ],
  },
};
localIdentHashSalt

Type:

type localIdentHashSalt = string;

Default: undefined

Allows to add custom hash to generate more unique classes. For more information see output.hashSalt.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            localIdentHashSalt: "hash",
          },
        },
      },
    ],
  },
};
localIdentHashFunction

Type:

type localIdentHashFunction = string;

Default: md4

Allows to specify hash function to generate classes . For more information see output.hashFunction.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            localIdentHashFunction: "md4",
          },
        },
      },
    ],
  },
};
localIdentHashDigest

Type:

type localIdentHashDigest = string;

Default: hex

Allows to specify hash digest to generate classes. For more information see output.hashDigest.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            localIdentHashDigest: "base64",
          },
        },
      },
    ],
  },
};
localIdentHashDigestLength

Type:

type localIdentHashDigestLength = number;

Default: 20

Allows to specify hash digest length to generate classes. For more information see output.hashDigestLength.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            localIdentHashDigestLength: 5,
          },
        },
      },
    ],
  },
};
hashStrategy

Type: 'resource-path-and-local-name' | 'minimal-subset' Default: 'resource-path-and-local-name'

Should local name be used when computing the hash.

  • 'resource-path-and-local-name' Both resource path and local name are used when hashing. Each identifier in a module gets its own hash digest, always.
  • 'minimal-subset' Auto detect if identifier names can be omitted from hashing. Use this value to optimize the output for better GZIP or Brotli compression.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            hashStrategy: "minimal-subset",
          },
        },
      },
    ],
  },
};
localIdentRegExp

Type:

type localIdentRegExp = string | RegExp;

Default: undefined

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            localIdentRegExp: /page-(.*)\.css/i,
          },
        },
      },
    ],
  },
};
getLocalIdent

Type:

type getLocalIdent = (
  context: LoaderContext,
  localIdentName: string,
  localName: string,
) => string;

Default: undefined

Allows to specify a function to generate the classname. By default we use built-in function to generate a classname. If the custom function returns null or undefined, we fallback to the built-in function to generate the classname.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            getLocalIdent: (context, localIdentName, localName, options) => {
              return "whatever_random_class_name";
            },
          },
        },
      },
    ],
  },
};
namedExport

Type:

type namedExport = boolean;

Default: Depends on the value of the esModule option. If the value of the esModule options is true, this value will also be true, otherwise it will be false.

Enables/disables ES modules named export for locals.

Warning

Because it is not allowed to use the default class in CSS when the namedExport is true (since ECMA modules have a reserved keyword default for default export), it will be automatically renamed to the _default class.

styles.css

.foo-baz {
  color: red;
}
.bar {
  color: blue;
}
.default {
  color: green;
}

index.js

import * as styles from "./styles.css";

// If using `exportLocalsConvention: "as-is"` (default value):
console.log(styles["foo-baz"], styles.bar);

// If using `exportLocalsConvention: "camel-case-only"`:
console.log(styles.fooBaz, styles.bar);

// For the `default` classname
console.log(styles["_default"]);

You can enable a ES module named export using:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          esModule: true,
          modules: {
            namedExport: true,
          },
        },
      },
    ],
  },
};

To set a custom name for namedExport, can use exportLocalsConvention option as a function. Example below in the examples section.

exportGlobals

Type:

type exportsGLobals = boolean;

Default: false

Allow css-loader to export names from global class or id, so you can use that as local name.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            exportGlobals: true,
          },
        },
      },
    ],
  },
};
exportLocalsConvention

Type:

type exportLocalsConvention =
  | "as-is"
  | "camel-case"
  | "camel-case-only"
  | "dashes"
  | "dashes-only"
  | ((name: string) => string);

Default: Depends on the value of the modules.namedExport option, if true - as-is, otherwise camel-case-only.

Warning

Names of locals are converted to camelcase when the named export is false, i.e. the exportLocalsConvention option has camelCaseOnly value by default. You can set this back to any other valid option but selectors which are not valid JavaScript identifiers may run into problems which do not implement the entire modules specification.

Style of exported class names.

string

By default, the exported JSON keys mirror the class names (i.e as-is value).

Name Type Description
'as-is' string Class names will be exported as is.
'camel-case' string Class names will be camelized, the original class name will not to be removed from the locals
'camel-case-only' string Class names will be camelized, the original class name will be removed from the locals
'dashes' string Only dashes in class names will be camelized
'dashes-only' string Dashes in class names will be camelized, the original class name will be removed from the locals

file.css

.class-name {
}

file.js

import { className } from "file.css";

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            exportLocalsConvention: "camel-case-only",
          },
        },
      },
    ],
  },
};
function

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            exportLocalsConvention: function (name) {
              return name.replace(/-/g, "_");
            },
          },
        },
      },
    ],
  },
};

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            exportLocalsConvention: function (name) {
              return [
                name.replace(/-/g, "_"),
                // dashesCamelCase
                name.replace(/-+(\w)/g, (match, firstLetter) =>
                  firstLetter.toUpperCase(),
                ),
              ];
            },
          },
        },
      },
    ],
  },
};
exportOnlyLocals

Type:

type exportOnlyLocals = boolean;

Default: false

Export only locals.

Useful when you use css modules for pre-rendering (for example SSR). For pre-rendering with mini-css-extract-plugin you should use this option instead of style-loader!css-loader in the pre-rendering bundle. It doesn't embed CSS but only exports the identifier mappings.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            exportOnlyLocals: true,
          },
        },
      },
    ],
  },
};
getJSON

Type:

type getJSON = ({
  resourcePath,
  imports,
  exports,
  replacements,
}: {
  resourcePath: string;
  imports: object[];
  exports: object[];
  replacements: object[];
}) => Promise<void> | void;

Default: undefined

Enables a callback to output the CSS modules mapping JSON. The callback is invoked with an object containing the following:

  • resourcePath: the absolute path of the original resource, e.g., /foo/bar/baz.module.css

  • imports: an array of import objects with data about import types and file paths, e.g.,

[
  {
    "type": "icss_import",
    "importName": "___CSS_LOADER_ICSS_IMPORT_0___",
    "url": "\"-!../../../../../node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!../../../../../node_modules/postcss-loader/dist/cjs.js!../../../../../node_modules/sass-loader/dist/cjs.js!../../../../baz.module.css\"",
    "icss": true,
    "index": 0
  }
]

(Note that this will include all imports, not just those relevant to CSS modules.)

  • exports: an array of export objects with exported names and values, e.g.,
[
  {
    "name": "main",
    "value": "D2Oy"
  }
]
  • replacements: an array of import replacement objects used for linking imports and exports, e.g.,
{
  "replacementName": "___CSS_LOADER_ICSS_IMPORT_0_REPLACEMENT_0___",
  "importName": "___CSS_LOADER_ICSS_IMPORT_0___",
  "localName": "main"
}

Using getJSON, it's possible to output a files with all CSS module mappings. In the following example, we use getJSON to cache canonical mappings and add stand-ins for any composed values (through composes), and we use a custom plugin to consolidate the values and output them to a file:

webpack.config.js

const path = require("path");
const fs = require("fs");

const CSS_LOADER_REPLACEMENT_REGEX =
  /(___CSS_LOADER_ICSS_IMPORT_\d+_REPLACEMENT_\d+___)/g;
const REPLACEMENT_REGEX = /___REPLACEMENT\[(.*?)]\[(.*?)]___/g;
const IDENTIFIER_REGEX = /\[(.*?)]\[(.*?)]/;
const replacementsMap = {};
const canonicalValuesMap = {};
const allExportsJson = {};

function generateIdentifier(resourcePath, localName) {
  return `[${resourcePath}][${localName}]`;
}

function addReplacements(resourcePath, imports, exportsJson, replacements) {
  const importReplacementsMap = {};

  // create a dict to quickly identify imports and get their absolute stand-in strings in the currently loaded file
  // e.g., { '___CSS_LOADER_ICSS_IMPORT_0_REPLACEMENT_0___': '___REPLACEMENT[/foo/bar/baz.css][main]___' }
  importReplacementsMap[resourcePath] = replacements.reduce(
    (acc, { replacementName, importName, localName }) => {
      const replacementImportUrl = imports.find(
        (importData) => importData.importName === importName,
      ).url;
      const relativePathRe = /.*!(.*)"/;
      const [, relativePath] = replacementImportUrl.match(relativePathRe);
      const importPath = path.resolve(path.dirname(resourcePath), relativePath);
      const identifier = generateIdentifier(importPath, localName);
      return { ...acc, [replacementName]: `___REPLACEMENT${identifier}___` };
    },
    {},
  );

  // iterate through the raw exports and add stand-in variables
  // ('___REPLACEMENT[<absolute_path>][<class_name>]___')
  // to be replaced in the plugin below
  for (const [localName, classNames] of Object.entries(exportsJson)) {
    const identifier = generateIdentifier(resourcePath, localName);

    if (CSS_LOADER_REPLACEMENT_REGEX.test(classNames)) {
      // if there are any replacements needed in the concatenated class names,
      // add them all to the replacements map to be replaced altogether later
      replacementsMap[identifier] = classNames.replaceAll(
        CSS_LOADER_REPLACEMENT_REGEX,
        (_, replacementName) =>
          importReplacementsMap[resourcePath][replacementName],
      );
    } else {
      // otherwise, no class names need replacements so we can add them to
      // canonical values map and all exports JSON verbatim
      canonicalValuesMap[identifier] = classNames;

      allExportsJson[resourcePath] = allExportsJson[resourcePath] || {};
      allExportsJson[resourcePath][localName] = classNames;
    }
  }
}

function replaceReplacements(classNames) {
  return classNames.replaceAll(
    REPLACEMENT_REGEX,
    (_, resourcePath, localName) => {
      const identifier = generateIdentifier(resourcePath, localName);

      if (identifier in canonicalValuesMap) {
        return canonicalValuesMap[identifier];
      }

      // Recurse through other stand-in that may be imports
      const canonicalValue = replaceReplacements(replacementsMap[identifier]);

      canonicalValuesMap[identifier] = canonicalValue;

      return canonicalValue;
    },
  );
}

function getJSON({ resourcePath, imports, exports, replacements }) {
  const exportsJson = exports.reduce((acc, { name, value }) => {
    return { ...acc, [name]: value };
  }, {});

  if (replacements.length > 0) {
    // replacements present --> add stand-in values for absolute paths and local names,
    // which will be resolved to their canonical values in the plugin below
    addReplacements(resourcePath, imports, exportsJson, replacements);
  } else {
    // no replacements present --> add to canonicalValuesMap verbatim
    // since all values here are canonical/don't need resolution
    for (const [key, value] of Object.entries(exportsJson)) {
      const id = `[${resourcePath}][${key}]`;

      canonicalValuesMap[id] = value;
    }

    allExportsJson[resourcePath] = exportsJson;
  }
}

class CssModulesJsonPlugin {
  constructor(options) {
    this.options = options;
  }

  // eslint-disable-next-line class-methods-use-this
  apply(compiler) {
    compiler.hooks.emit.tap("CssModulesJsonPlugin", () => {
      for (const [identifier, classNames] of Object.entries(replacementsMap)) {
        const adjustedClassNames = replaceReplacements(classNames);

        replacementsMap[identifier] = adjustedClassNames;

        const [, resourcePath, localName] = identifier.match(IDENTIFIER_REGEX);

        allExportsJson[resourcePath] = allExportsJson[resourcePath] || {};
        allExportsJson[resourcePath][localName] = adjustedClassNames;
      }

      fs.writeFileSync(
        this.options.filepath,
        JSON.stringify(
          // Make path to be relative to `context` (your project root)
          Object.fromEntries(
            Object.entries(allExportsJson).map((key) => {
              key[0] = path
                .relative(compiler.context, key[0])
                .replace(/\\/g, "/");

              return key;
            }),
          ),
          null,
          2,
        ),
        "utf8",
      );
    });
  }
}

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: { modules: { getJSON } },
      },
    ],
  },
  plugins: [
    new CssModulesJsonPlugin({
      filepath: path.resolve(__dirname, "./output.css.json"),
    }),
  ],
};

In the above, all import aliases are replaced with ___REPLACEMENT[<resourcePath>][<localName>]___ in getJSON, and they're resolved in the custom plugin. All CSS mappings are contained in allExportsJson:

{
  "foo/bar/baz.module.css": {
    "main": "D2Oy",
    "header": "thNN"
  },
  "foot/bear/bath.module.css": {
    "logo": "sqiR",
    "info": "XMyI"
  }
}

This is saved to a local file named output.css.json.

importLoaders

Type:

type importLoaders = number;

Default: 0

Allows to enables/disables or setups number of loaders applied before CSS loader for @import at-rules, CSS modules and ICSS imports, i.e. @import/composes/@value value from './values.css'/etc.

The option importLoaders allows you to configure how many loaders before css-loader should be applied to @imported resources and CSS modules/ICSS imports.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          "style-loader",
          {
            loader: "css-loader",
            options: {
              importLoaders: 2,
              // 0 => no loaders (default);
              // 1 => postcss-loader;
              // 2 => postcss-loader, sass-loader
            },
          },
          "postcss-loader",
          "sass-loader",
        ],
      },
    ],
  },
};

This may change in the future when the module system (i. e. webpack) supports loader matching by origin.

sourceMap

Type:

type sourceMap = boolean;

Default: depends on the compiler.devtool value

By default generation of source maps depends on the devtool option. All values enable source map generation except eval and false value.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          sourceMap: true,
        },
      },
    ],
  },
};

esModule

Type:

type esModule = boolean;

Default: true

By default, css-loader generates JS modules that use the ES modules syntax. There are some cases in which using ES modules is beneficial, like in the case of module concatenation and tree shaking.

You can enable a CommonJS modules syntax using:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          esModule: false,
        },
      },
    ],
  },
};

exportType

Type:

type exportType = "array" | "string" | "css-style-sheet";

Default: 'array'

Allows exporting styles as array with modules, string or constructable stylesheet (i.e. CSSStyleSheet). Default value is 'array', i.e. loader exports array of modules with specific API which is used in style-loader or other.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        assert: { type: "css" },
        loader: "css-loader",
        options: {
          exportType: "css-style-sheet",
        },
      },
    ],
  },
};

src/index.js

import sheet from "./styles.css" assert { type: "css" };

document.adoptedStyleSheets = [sheet];
shadowRoot.adoptedStyleSheets = [sheet];

'array'

The default export is array of modules with specific API which is used in style-loader or other.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.(sa|sc|c)ss$/i,
        use: ["style-loader", "css-loader", "postcss-loader", "sass-loader"],
      },
    ],
  },
};

src/index.js

// `style-loader` applies styles to DOM
import "./styles.css";

'string'

Warning

You should not use style-loader or mini-css-extract-plugin with this value.

Warning

The esModule option should be enabled if you want to use it with CSS modules, by default for locals will be used named export.

The default export is string.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.(sa|sc|c)ss$/i,
        use: ["css-loader", "postcss-loader", "sass-loader"],
      },
    ],
  },
};

src/index.js

import sheet from "./styles.css";

console.log(sheet);

'css-style-sheet'

Warning

@import rules not yet allowed, more information

Warning

You don't need style-loader anymore, please remove it.

Warning

The esModule option should be enabled if you want to use it with CSS modules, by default for locals will be used named export.

Warning

Source maps are not currently supported in Chrome due bug

The default export is a constructable stylesheet (i.e. CSSStyleSheet).

Useful for custom elements and shadow DOM.

More information:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        assert: { type: "css" },
        loader: "css-loader",
        options: {
          exportType: "css-style-sheet",
        },
      },

      // For Sass/SCSS:
      //
      // {
      //   assert: { type: "css" },
      //   rules: [
      //     {
      //       loader: "css-loader",
      //       options: {
      //         exportType: "css-style-sheet",
      //         // Other options
      //       },
      //     },
      //     {
      //       loader: "sass-loader",
      //       options: {
      //         // Other options
      //       },
      //     },
      //   ],
      // },
    ],
  },
};

src/index.js

// Example for Sass/SCSS:
// import sheet from "./styles.scss" assert { type: "css" };

// Example for CSS modules:
// import sheet, { myClass } from "./styles.scss" assert { type: "css" };

// Example for CSS:
import sheet from "./styles.css" assert { type: "css" };

document.adoptedStyleSheets = [sheet];
shadowRoot.adoptedStyleSheets = [sheet];

For migration purposes, you can use the following configuration:

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        oneOf: [
          {
            assert: { type: "css" },
            loader: "css-loader",
            options: {
              exportType: "css-style-sheet",
              // Other options
            },
          },
          {
            use: [
              "style-loader",
              {
                loader: "css-loader",
                options: {
                  // Other options
                },
              },
            ],
          },
        ],
      },
    ],
  },
};

Examples

Recommend

For production builds it's recommended to extract the CSS from your bundle being able to use parallel loading of CSS/JS resources later on. This can be achieved by using the mini-css-extract-plugin, because it creates separate css files. For development mode (including webpack-dev-server) you can use style-loader, because it injects CSS into the DOM using multiple <style></style> and works faster.

Note

Do not use style-loader and mini-css-extract-plugin together.

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== "production";

module.exports = {
  module: {
    rules: [
      {
        // If you enable `experiments.css` or `experiments.futureDefaults`, please uncomment line below
        // type: "javascript/auto",
        test: /\.(sa|sc|c)ss$/i,
        use: [
          devMode ? "style-loader" : MiniCssExtractPlugin.loader,
          "css-loader",
          "postcss-loader",
          "sass-loader",
        ],
      },
    ],
  },
  plugins: [].concat(devMode ? [] : [new MiniCssExtractPlugin()]),
};

Disable url resolving using the /* webpackIgnore: true */ comment

With the help of the /* webpackIgnore: true */comment, it is possible to disable sources handling for rules and for individual declarations.

/* webpackIgnore: true */
@import url(./basic.css);
@import /* webpackIgnore: true */ url(./imported.css);

.class {
  /* Disabled url handling for the all urls in the 'background' declaration */
  color: red;
  /* webpackIgnore: true */
  background: url("./url/img.png"), url("./url/img.png");
}

.class {
  /* Disabled url handling for the first url in the 'background' declaration */
  color: red;
  background:
    /* webpackIgnore: true */ url("./url/img.png"), url("./url/img.png");
}

.class {
  /* Disabled url handling for the second url in the 'background' declaration */
  color: red;
  background:
    url("./url/img.png"),
    /* webpackIgnore: true */ url("./url/img.png");
}

/* prettier-ignore */
.class {
  /* Disabled url handling for the second url in the 'background' declaration */
  color: red;
  background: url("./url/img.png"),
    /* webpackIgnore: true */
    url("./url/img.png");
}

/* prettier-ignore */
.class {
  /* Disabled url handling for third and sixth urls in the 'background-image' declaration */
  background-image: image-set(
    url(./url/img.png) 2x,
    url(./url/img.png) 3x,
    /* webpackIgnore:  true */ url(./url/img.png) 4x,
    url(./url/img.png) 5x,
    url(./url/img.png) 6x,
    /* webpackIgnore:  true */
    url(./url/img.png) 7x
  );
}

Assets

The following webpack.config.js can load CSS files, embed small PNG/JPG/GIF/SVG images as well as fonts as Data URLs and copy larger files to the output directory.

For webpack v5:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/i,
        // More information here https://webpack.js.org/guides/asset-modules/
        type: "asset",
      },
    ],
  },
};

Extract

For production builds it's recommended to extract the CSS from your bundle being able to use parallel loading of CSS/JS resources later on.

  • This can be achieved by using the mini-css-extract-plugin to extract the CSS when running in production mode.

  • As an alternative, if seeking better development performance and css outputs that mimic production. extract-css-chunks-webpack-plugin offers a hot module reload friendly, extended version of mini-css-extract-plugin. HMR real CSS files in dev, works like mini-css in non-dev

Pure CSS, CSS modules and PostCSS

When you have pure CSS (without CSS modules), CSS modules and PostCSS in your project you can use this setup:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        // For pure CSS - /\.css$/i,
        // For Sass/SCSS - /\.((c|sa|sc)ss)$/i,
        // For Less - /\.((c|le)ss)$/i,
        test: /\.((c|sa|sc)ss)$/i,
        use: [
          "style-loader",
          {
            loader: "css-loader",
            options: {
              // Run `postcss-loader` on each CSS `@import` and CSS modules/ICSS imports, do not forget that `sass-loader` compile non CSS `@import`'s into a single file
              // If you need run `sass-loader` and `postcss-loader` on each CSS `@import` please set it to `2`
              importLoaders: 1,
            },
          },
          {
            loader: "postcss-loader",
            options: { plugins: () => [postcssPresetEnv({ stage: 0 })] },
          },
          // Can be `less-loader`
          {
            loader: "sass-loader",
          },
        ],
      },
      // For webpack v5
      {
        test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/i,
        // More information here https://webpack.js.org/guides/asset-modules/
        type: "asset",
      },
    ],
  },
};

Resolve unresolved URLs using an alias

index.css

.class {
  background: url(/assets/unresolved/img.png);
}

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ["style-loader", "css-loader"],
      },
    ],
  },
  resolve: {
    alias: {
      "/assets/unresolved/img.png": path.resolve(
        __dirname,
        "assets/real-path-to-img/img.png",
      ),
    },
  },
};

Named export with custom export names

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          modules: {
            namedExport: true,
            exportLocalsConvention: function (name) {
              return name.replace(/-/g, "_");
            },
          },
        },
      },
    ],
  },
};

Separating Interoperable CSS-only and CSS Module features

The following setup is an example of allowing Interoperable CSS features only (such as :import and :export) without using further CSS Module functionality by setting mode option for all files that do not match *.module.scss naming convention. This is for reference as having ICSS features applied to all files was default css-loader behavior before v4. Meanwhile all files matching *.module.scss are treated as CSS Modules in this example.

An example case is assumed where a project requires canvas drawing variables to be synchronized with CSS - canvas drawing uses the same color (set by color name in JavaScript) as HTML background (set by class name in CSS).

webpack.config.js

module.exports = {
  module: {
    rules: [
      // ...
      // --------
      // SCSS ALL EXCEPT MODULES
      {
        test: /\.scss$/i,
        exclude: /\.module\.scss$/i,
        use: [
          {
            loader: "style-loader",
          },
          {
            loader: "css-loader",
            options: {
              importLoaders: 1,
              modules: {
                mode: "icss",
              },
            },
          },
          {
            loader: "sass-loader",
          },
        ],
      },
      // --------
      // SCSS MODULES
      {
        test: /\.module\.scss$/i,
        use: [
          {
            loader: "style-loader",
          },
          {
            loader: "css-loader",
            options: {
              importLoaders: 1,
              modules: {
                mode: "local",
              },
            },
          },
          {
            loader: "sass-loader",
          },
        ],
      },
      // --------
      // ...
    ],
  },
};

variables.scss

File treated as ICSS-only.

$colorBackground: red;
:export {
  colorBackgroundCanvas: $colorBackground;
}

Component.module.scss

File treated as CSS Module.

@import "variables.scss";
.componentClass {
  background-color: $colorBackground;
}

Component.jsx

Using both CSS Module functionality as well as SCSS variables directly in JavaScript.

import * as svars from "variables.scss";
import * as styles from "Component.module.scss";

// Render DOM with CSS modules class name
// <div className={styles.componentClass}>
//   <canvas ref={mountsCanvas}/>
// </div>

// Somewhere in JavaScript canvas drawing code use the variable directly
// const ctx = mountsCanvas.current.getContext('2d',{alpha: false});
ctx.fillStyle = `${svars.colorBackgroundCanvas}`;

Contributing

Please take a moment to read our contributing guidelines if you haven't yet done so.

CONTRIBUTING

License

MIT

css-loader's People

Contributors

alexander-akait avatar andreypopp avatar anshumanv avatar bebraw avatar ben-eb avatar bpscott avatar cap-bernardito avatar dependabot[bot] avatar ersachin3112 avatar evilebottnawi avatar jhnns avatar joscha avatar joshwiens avatar jounqin avatar jquense avatar kgram avatar kud avatar lemieux avatar liambuchanan avatar markdalgleish avatar michael-ciniawsky avatar mrsteele avatar shama avatar shyykoserhiy avatar simon04 avatar snitin315 avatar sokra avatar spacek33z avatar subzey avatar thelarkinn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

css-loader's Issues

new output option - output as string

I've been trying to use this in combination with file-loader, so I can chain converting from SASS and processing all my files used in my SASS to then output a CSS file that references those files.

eg.

    loaders: [
        {
            test: /\.scss$/,
            loaders: [
                'file-loader?name=[name].css',
                'css-loader?outputStyle=default | string',
                'autoprefixer-loader?{browsers:["last 2 version", "Firefox 15"]}',
                'sass-loader?outputStyle=compressed'
            ]
        },
        {
            test: /\.png$|\.jpg$|\.gif$|\.ico/,
            loader: 'file-loader?name=assets/[hash:7]-[name].[ext]'
        },
        {
            test: /\.eot$|\.woff$|\.ttf$|\.svg$/,
            loader: 'file-loader?name=assets/[hash:7]-[name].[ext]'
        }
    ]

?outputStyle=string will allow us to create a files easily and still manage all our CSS dependencies with the mighty css-loader.

loader breaks inline css url data

When I have inline svg image like this:

background-image: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 42 26' fill='%23007aff'><rect width='4' height='4'/><rect x='8' y='1' width='34' height='2'/><rect y='11' width='4' height='4'/><rect x='8' y='12' width='34' height='2'/><rect y='22' width='4' height='4'/><rect x='8' y='23' width='34' height='2'/></svg>")

css-loader compile it to:

background-image: url(data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 42 26' fill='%23007aff'><rect width='4' height='4'/><rect x='8' y='1' width='34' height='2'/><rect y='11' width='4' height='4'/><rect x='8' y='12' width='34' height='2'/><rect y='22' width='4' height='4'/><rect x='8' y='23' width='34' height='2'/></svg>)

Lost quotes, this code is invalid

Cannot do relative require() for resource via url()

I've a stylesheet that use a font but using relative url (relative to the css) doesn't work.

In src/path/style.css the following CSS doesn't work ("cannot found" error)

@font-face {
  font-family: 'myFont;
  src: url("./myFont.otf");
}

I had to use

@font-face {
  font-family: 'myFont;
  src: url("src/path/myFont.otf");
}

But it's not how require() should work right ?

hash urls should not be resolved

When using CSS to apply filters to SVG elements like:

.highlight {
    filter: url(#highlight);
}

the url should be left untouched.

I suppose the hash portion of the URL should be preserved in other cases as well, as it may convey specific information to the stylesheet.

Unexpected token

Hi!
Just getting started with CSS loader. here's my css:

body {
  background: pink;
}

and my js:

var React = require('react');

require('./home.css');

var Home = React.createClass({

    render() {
        return(
            <form className="CreatePlan">
                <h1>Create another plan</h1>
            </form>
        );
    }

});

module.exports = Home;

and my config:

var webpack = require('webpack');

module.exports = {
  devtool: 'eval',
  entry: [
    'webpack-dev-server/client?http://0.0.0.0:3000',
    'webpack/hot/only-dev-server',
    './scripts/index'
  ],
  output: {
    path: __dirname + '/scripts/',
    filename: 'bundle.js',
    publicPath: '/scripts/'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  ],
  resolve: {
    extensions: ['', '.js']
  },
  module: {
    loaders: [
      { test: /\.css$/, loader: "style!css" },
      { test: /\.js$/, loaders: ['react-hot', 'jsx?harmony'], exclude: /node_modules/ },
    ]
  }
};

and the error:

/Users/vince/projects/react-hot-boilerplate/node_modules/css-loader/node_modules/source-map/node_modules/amdefine/amdefine.js:274
});
^
SyntaxError: Unexpected token }
    at Module._compile (module.js:439:25)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/Users/vince/projects/react-hot-boilerplate/node_modules/css-loader/node_modules/source-map/lib/source-map/source-map-generator.js:8:18)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)

any ideas why?

Extract module functionality from loading

Been chatting with @markdalgleish about this, but I thought I'd put my thoughts down into an issue that was a bit more async-friendly (since he has a day job and so chatrooms aren't ideal).

I love the module mode for css-loader, I love the local-by-default idea, as well as being able to import other files & extend classes. But I think those things are being all tied together in the current implementation, and could be broken out, which would mean more flexibility, reuse, and ease-of-contributions.

Here's my suggestion:

  • Define a series of PostCSS transform that take the currently-supported syntax and converts it. Taking the example off the home page.

Input:

:local(.continueButton) {
  extends: button from "library/button.css";
  background: red;
}

After parse-imports.js

:import("library/button.css") {
  button: __tmp_487387465fczSDGHSABb;
}
:local(.continueButton) {
  extends: __tmp_487387465fczSDGHSABb;
  background: red;
}

After localize-and-extend.js

:import("library/button.css") {
  button: __tmp_487387465fczSDGHSABb;
}
:export {
  continueButton: _13LGdX8RMStbBE9w-t0gZ1 __tmp_487387465fczSDGHSABb;
}
._13LGdX8RMStbBE9w-t0gZ1 {
  background: red;
}

These transformations each have a single responsibility, are easier to test & maintain, can operate on a single file at once and totally agnostic to Webpack/JSPM/Browserify. After this:

  • Automatically attach those two PostCSS transforms in the same way importLoaders can be used.
  • If css-loader?module is set and CSS Module mode is activated, add the plugin postcss-local-scope to translate .localName to :local(.localName), just as it was before.
  • The current localisation/extension logic is adapted to look for the :import and :export primitives, and look for usages of temporary imported symbols (e.g. __tmp_487387465fczSDGHSABb) and replace them with the exports of another file.

So, this achieves a couple of things. It reduces the complexity of this project in particular, yet still presents the same interface to users of the module (:local and extends are always available, local-by-default is there in "module mode"). I can implement :import and :export for JSPM, and then we can share the CSS Modules syntax & plugins. I think it increases the chances of making CSS Modules a specification, since we'll have multiple loaders using it (more users) & be able to solve spec-level issues at the same time for everyone.

I'm happy to build these PostCSS plugins, and I think I could write a PR to include them as importLoaders. Getting :import and :export to work might be a bit beyond me right now.

From the reaction to both this project & Mark's blog post last week, as well as the discussions at CampJS and in chat rooms, people are really excited about this kind of functionality. I think this would make a good next logical step for the life of CSS Modules, and give it the best chance of being adopted globally.

Thanks!

Using url(path) with resolve.alias

I have a few images in a shared location, which I import in a css file. This shared location has a lot of code shared between 5 webapps within the same project, and I have defined the alias common-assets in my config, which works great for every asset/module, except for css. The path is normalized by css-loader (I think?) to be relative, which breaks.

Is there any clean way to use the alias, or do I have to go url("../../../../../../../../common/assets/images/image.png") instead of the much cleaner url("common-assets/images/image.png")? If I do the latter, the actual import becomes url("./common-assets/images/image.png"), which is wrong, and fails the build.

Loader fails on SVG definition rules with URL values

This is an issue moved from less-loader after opening it there by mistake:
webpack-contrib/less-loader#25

The loader seems to break when styles include references to SVG definitions. I'm using the markers in the styles because I don't want to mess with the charting library I'm using but the loader breaks on the URL.

Marker definition:

<defs>
    <marker id="line-marker">
         <circle cx="6" cy="6" r="5"></circle>
    </marker>
</defs>

Marker use:

path.nv-line {
    marker-mid: url('#line-marker');
}

Is there a way of ignoring some URL values in these rules or another way to prevent the loader from failing?

Detect @font-face urls()

It seems like the css-loader doesn't detect url()s in @font-face declarations

@font-face {
    font-family: 'Museo300';
    src: url(../assets/fonts/Museo/museo300-regular.woff) format('woff'),
         url(../assets/fonts/Museo/museo300-regular.ttf) format('truetype'),
         url(../assets/fonts/Museo/museo300-regular.svg) format('svg');
    font-weight: normal;
    font-style: normal;
}

This declaration is pretty standard (actually generated by fontsquirrel) to support different font formats.

names in Module mode

The module mode local scope is amazing, but is there any way to name the classes other than picking up the file name of the import?

eg, given:

MyComponent /
   index.css
   index.js
/* index.css */
.root {
  /* styles */
}
// index.js
var styles = require('./index.css')

// react stuff etc..
return <div className={styles.root} />

will output to:

<div className="index__root__eofhi28o2"></div>

... And so will every other module I have (sans the hash appened) becase I like to keep my component folders named and my filenames generic.

So the desired result given the folder/files above would be:

<div className="MyComponent__root__eofhi28o2"></div>

Edited: for clarity

Getting optimisation issue with some CSS

When I use webpack -p, I'm getting a non helping error message

ERROR in ./~/css-loader!./~/cssnext-loader!./src/index.css
Module build failed: Error: Please check the validity of the CSS block starting from the line #1
    at throwError (/.../node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:399:15)
    at checkStylesheet (/.../node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:1921:22)
    at Object.CSSPRules.stylesheet (/.../node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:365:40)
    at _getAST (/.../node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:409:38)
    at exports.srcToCSSP (/.../node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:2287:16)
    at Object.exports.srcToCSSP (/.../node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:2292:16)
    at Object.exports.parse (/.../node_modules/css-loader/node_modules/csso/lib/cssoapi.js:7:21)
    at Object.module.exports (/.../node_modules/css-loader/index.js:18:18)
 @ ./src/index.css 4:14-293

In this index.css I just have some inlined @import, so this error is not really helping.
Is there any way to improve that?

My first import is normalize.css and after taking a look in the <style> element I saw some empty :root elements (due to the fact I use future proof CSS transformed via cssnext).
It seems the parser you are using is kind of outdated for some part.

If you are using csso for minification, would you consider switch to a more fresh tool (csswring) based on an parser with an active development (postcss)?

sourceMap css does not function for background-image (maybe stylus-loader issue)

So this issue is bizarre and I hope I can make an example that does this.

I successful got sourceMaps to work with stylus-loader with
{ test: /\.styl$/, loader: 'style!css?sourceMap!stylus' }

However when ?sourceMap is enabled all our background url('whatever/sprite.png') no longer work. When the ?sourceMap is removed all is well.

I will make an example repo when I get the chance. Also let me know if this should be an issue on stylus-loader instead.

As for more info the css produced are identical except that sourcemap css is redirected via @import some url. The computed CSS reported by Chrome Debugger is identical, but using (Chrome Extension) CSSViewer reports different processed CSS. Which shows the missing sprite.

Also this problem exists in Firefox as well so I do not think it is a chrome issue.

css loader chokes on valid CSS

https://gist.github.com/haf/a632962b86409b8c51e3

ERROR in ./~/css-loader?root=..!./css/front.css
Module build failed: Error: Please check the validity of the CSS block starting from the line #414
    at throwError (/node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:399:15)
    at getBlock (/node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:755:18)

As you can see, there's no line 414.

inline import duplication

If I require('sub1.css') and require('sub2.css') which both @import url("./base.css") then I'll get rules in bass.css applied twice in my page, which may cause some problem.

Any plan to solve this?

When extend child class, parent class is also extended

I have this piece of CSS:

/* test.css */

.topbar {
  /* blah */
}

.topbar .search {
  extends: iconMagnifier from "../../styles/icons.scss";
}

After running through css-loader with:

{
  test: /\.css$/,
  loaders: [
    'style',
    'css?module'
  ]
}

I got something like that with exported styles:

import styles from "./test.css";
console.log(styles);
// => { topbar: "topbar--hhDqN iconMagnifier--28gN4", search: "search--1hPrb iconMagnifier--28gN4" }

topbar should not be extended like that, right? Styles should be { topbar: "topbar--hhDqN", search: "search--1hPrb iconMagnifier--28gN4" }.

Though?

Option to turn off url() inlining

Would it be possible to turn off url() inlining/importing? I have looked throughout and cannot find a config option to disable this.

In a project, I am only using url() for fonts (supporting legacy browsers) and do not want all 4 fonts inlined into the CSS file. I can't seem to find an option to allow that code to get through the loader untouched.

Can't figure out how to enable `disableStructuralMinification` via loaders

Uglify is breaking all sorts of things with my CSS so I'm trying to enable disableStructuralMinification but I can't tell if it's working as nothing is changing. I've tried:

{test: /\.css$/, loader: 'style!css?disableStructuralMinification!'},
{test: /\.less$/, loaders: [
    "style-loader",
    "css-loader",
    "less-loader"
]}

And then I tried

{test: /\.css$/, loader: 'style!css},
{test: /\.less$/, loaders: [
    "style-loader",
    "css-loader?disableStructuralMinification!'",
    "less-loader"
]}

But it doesn't seem to resolve my issues. The minification process still moves CSS rules around in such a way that causes broken styling in my app.

What am I doing wrong?

loading fonts via url() only works in production mode

I observed some weird behavior when I was trying to use font-awesome in a webpack powered project.

I trimmed the code down as much as possible and put it into a gist: https://gist.github.com/Turbo87/e8e941e68308d3b40ef6

I installed font-awesome via npm and use require to import its CSS file through the style and css loaders. The CSS file has a @font-face which uses url() with a relative path to point to the font file(s). When I compile this with webpack in production mode everything works just as expected, but once I drop the -p parameter the code suddenly tries to load the font file from / for whatever reason and fails.

I observed that behavior with Google Chrome and Firefox, so it is probably not a browser issue.

Getting CSS validation error for valid css file (0.7.0).

I'm getting this error:

ERROR in ./~/css-loader!./src/main/webapp/js/modules/pages/styles/HelloWorld.css
Module build failed: Error: Please check the validity of the CSS block starting from the line #1
    at throwError (/Users/pairing/projects/alm/alm-webapp/node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:399:15)
    at checkStylesheet (/Users/pairing/projects/alm/alm-webapp/node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:1921:22)
    at Object.CSSPRules.stylesheet (/Users/pairing/projects/alm/alm-webapp/node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:365:40)
    at _getAST (/Users/pairing/projects/alm/alm-webapp/node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:409:38)
    at exports.srcToCSSP (/Users/pairing/projects/alm/alm-webapp/node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:2287:16)
    at Object.exports.srcToCSSP (/Users/pairing/projects/alm/alm-webapp/node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:2292:16)
    at Object.exports.parse (/Users/pairing/projects/alm/alm-webapp/node_modules/css-loader/node_modules/csso/lib/cssoapi.js:7:21)
    at Object.module.exports (/Users/pairing/projects/alm/alm-webapp/node_modules/css-loader/index.js:13:18)
 @ ./src/main/webapp/js/modules/pages/SynchronousCommonJsPage.jsx 11:0-38

Webpack config:

module: {
loaders: [
    {
      test: /\.jsx$/,
      loader: 'jsx-loader?insertPragma=React.DOM'
    },
    {
      test: /\.css$/,
      loader: "style-loader!css-loader"
    }
  ]
}

Require:

require("css!./styles/HelloWorld.css");

HelloWorld.css:

.hello {
  font-weight: bold;
  font-size: 24px;
  color: purple;
}

Use PostCSS

fastparse is awesome tool. But if you will move to PostCSS you will have these benefits:

  1. Most of source map code will be in PostCSS.
  2. You can replace url() and support @import with full CSS parsing. It is much safer. We are already have awesome plugins for url() and @import.
  3. PostCSS has “Safe Mode” to parse any legacy CSS (even broken).
  4. Right now @ben-eb creating awesome modular CSS minifier (it is much easier to fix and develop modular tool) cssnano. Right now it has better results that [clean-css] without advanced mode. So, when it became equal to clean-css, we can use it, because it is a PostCSS plugin with same source map support.

@markdalgleish what do you think as PostCSS plugin developer?

CSS Variables

It would be nice to have a simple way for defining variables.
Inheritance is a nice feature, but it doesn't cover every use case.

How about supporting the :root pseudo-class selector, so that we could have:

variables.css

.colors {
  --color-red: red;
  --color-blue: blue;
}

.fontSizes {
  --font-size-normal: 12px;
  --font-size-large: 14px;
}

component.css

:root {
  extends: colors from "shared/styles/variables.css";
}

.foo {
  color: var(--color-red);
}

transpiled to:

:root {
  --color-blue: blue;
  --color-red: red;
}

.foo {
  color: var(--color-red);
}

This works out of the box in Firefox and it can be transpiled back to CSS2 with postcss-custom-properties

woff2 failure

File seems to be valid, and:

ERROR in ./www/fonts/font.woff2?-p2dq1s
Module parse failed: [..]/fonts/font.woff2?-p2dq1s Line 1: Unexpected token ILLEGAL
You may need an appropriate loader to handle this file type.
(Source code omitted for this binary file)
 @ ./~/css-loader!./www/css/index.css 2:34960-34998

All other font files are fine.

Module require is case insenitive

Code that worked on my Mac failed when I used my Linux box, because of a failure (on my part) in casing.

Node.js require is case sensitive, would it be possible to copy that behavior? Not sure if it's this plugin er Webpack core.

Breaking change for something minor, but I think consistency is important.

@import url("~dataTables/media/css/jquery.datatables.css");

vs.

@import url("~datatables/media/css/jquery.dataTables.css");

First one failed, second is the correct one

Can npm-managed packages use local root-relative urls?

let's say I have ./node_modules/my-ui/src/style/main.css, and in this file I have
url("/images/my-image.png") as a reference to ./node_modules/my-ui/src/images/my-image.png

is there any way to allow each of the packages in node_modules use their own root-relative URL's?
when developing locally for my-ui, everything is fine since it defines ?root=src in its own webpack.config.js, but when my-ui is an npm dependency... how can it continue to use root-relative URL's in its CSS?

thanks!

css-loader parse fail on @font-face

I get this error when webpack tries to run:

ERROR in ./bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.eot
Module parse failed: 
./bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.eot Line 1: Unexpected token ILLEGAL
You may need an appropriate loader to handle this file type.
(Source code omitted for this binary file)
 @ ./~/css-loader?importLoaders=1!./bower_components/bootstrap/dist/css/bootstrap.css 2:4480-4532 2:4551-4603

Here's my configuration

 module: {
    loaders: [
      // Pass *.jsx files through jsx-loader transform
      { test: /\.js$/, loaders: ['react-hot','jsx?harmony'] },

      { test: /\.css$/, loader: "style-loader!css-loader?importLoaders=1" }
    ]
  }

Is it something in my config that's wrong or missing something?

Source maps

Is it possible to use CSS source maps in the generated style, so that developer tools could show the location of the styles? Right now it is non-obvious where a style was defined in the source code, especially when using @import to include other CSS files in the bundle.

@import handling should use the loader defined in the webpack config

I am currently developing a sass loader which uses the original ruby sass compiler. When the css-loader processes the output and handles @import directives currently calls the sass loader again (which fails, since ruby sass can't seem to handle normal css files properly).
I think it would be better to call the loader defined in the webpack config for that file pattern instead.

Module build failed: SyntaxError: Unexpected token h

The following CSS ia breaking my build

.class {
  filter: drop-shadow(0 1px 0 var(--vr-Color-white));
}

It's totally valid CSS. It seems related to the parser. Maybe you should consider using a better parser like postcss ?

Module build failed: Error: Please check the validity of the CSS block starting from the line #3288

I realise this error message has been reported before, but I'm not double chaining the css loader.

The css is the output from less-loader, specifically the less from www.material-ui.com.

webpack.config.js:

var webpack = require('webpack'),
    path    = require('path');

module.exports = {
    entry: './src/index.jsx',
    devtool: 'source-map',
    output: {
        path: path.join(__dirname, 'www'),
        filename: 'app.js'
    },
    resolve: {
        modulesDirectories: ['node_modules'],
    },
    module: {
        loaders: [
            { test: /\.css$/, loader: 'style!css' },
            { test: /\.less$/, loader: 'style!css!less' },
            { test: /\.jsx$/, loader: 'jsx-loader?harmony&insertPragma=React.DOM' },
            { test: /\.js$/, loader: '6to5-loader'},
            { test: /\.(eot|woff)$/, loader: 'file' },
        ]
    }
};

entry point (index.jsx):

require('./material-ui.less');
var React= require('react'),
    HelloMessage= require('./firstview.jsx')
React.render(<HelloMessage name="Hello" />, document.getElementById('app'));

material-ui.less:

@import "~material-ui/src/less/scaffolding.less";
@import "~material-ui/src/less/components.less";

Output:

ERROR in ./~/css-loader!./~/less-loader!./src/material-ui.less
Module build failed: Error: Please check the validity of the CSS block starting from the line #3288
    at throwError (/Users/mg/Documents/js/scaffold-web-rx/node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:399:15)
    at getBlock (/Users/mg/Documents/js/scaffold-web-rx/node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:755:18)
    at getAtruleb (/Users/mg/Documents/js/scaffold-web-rx/node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:632:34)
    at getAtrule (/Users/mg/Documents/js/scaffold-web-rx/node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:606:28)
    at getStylesheet (/Users/mg/Documents/js/scaffold-web-rx/node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:1937:60)
    at Object.CSSPRules.stylesheet (/Users/mg/Documents/js/scaffold-web-rx/node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:365:69)
    at _getAST (/Users/mg/Documents/js/scaffold-web-rx/node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:409:38)
    at exports.srcToCSSP (/Users/mg/Documents/js/scaffold-web-rx/node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:2287:16)
    at Object.exports.srcToCSSP (/Users/mg/Documents/js/scaffold-web-rx/node_modules/css-loader/node_modules/csso/lib/gonzales.cssp.node.js:2292:16)
    at Object.exports.parse (/Users/mg/Documents/js/scaffold-web-rx/node_modules/css-loader/node_modules/csso/lib/cssoapi.js:7:21)
 @ ./src/material-ui.less 4:14-231

Any ideas? Is there any way for me to see what's going on at line #3288? Please consider that this is my first attempt at using webpack so assume that Im capable of any newbie error possible.

Single or double quotes in comments causing failure in resolving url()

/*
 * a ' above
 */

.bg {
  background-image: url(bg.jpg);
}

/*
 * a ' below
 */

bg.jpg won't get resolved. A slice of the output :

exports.push([module.id, "/*\n * a ' above\n */\n\n.bg {\n  background-image: url(bg.jpg);\n}\n\n/*\n * a ' below\n */\n", ""]);

Both single and double quotes can cause this bug.

Local scopes

People seem to be overhyped with local scopes. Some even propose to make it local by default.
But for now the only features local scope allows are export and reuse of classes.

I import Web component. I want to restyle one of it's inner tags.
I make some CSS rule:

x-tabs /deep/ x-panel {
  ...
}

It can't be passed as HTML attribute it must be declared in a global space of CSS.
Did anyone think it out? It seems a dead-end to me. Why bother with local scopes at all?

@import rules in css doesn't look in node_modules folder

I have a file called base.css that has an import statement

@import "normalize.css/normalize.css"
body {
  background: red;
}

This is my app.js:

var css  = require('./styles/base.css');

module.exports = function Foo() {
    return {
        foo: 'bar',
        baz: 'gah'
    };
};

I've npm installed normalize but running the webpack command throws:

$ webpack
Hash: 2a64a4ac64b2026975fb
Version: webpack 1.1.8
Time: 82ms
    Asset  Size  Chunks             Chunk Names
bundle.js  2019       0  [emitted]  main
   [0] ./src/app.js 137 {0} [built]
   [1] ./src/styles/base.css 177 {0} [built] [1 error]

ERROR in ./src/styles/base.css
Module not found: Error: Cannot resolve file or directory ./normalize.css/normalize.css in /Users/Ryan/Git/webpack-demo/src/styles
 @ ./src/styles/base.css 2:1-116

What am I doing wrong? I understand that it's looking in styles dir but I thought it would scan node_modules first?

Root relative outputs relative URL in single page application

Hello, I noticed the root-relative option https://github.com/webpack/css-loader#root-relative-urls doesn't work well if you have a single page application that uses history.pushState.

Example:

I have the following structure:

/
--/src
  --/assets/images/hello.png
  --/css/style.css
--/build
  -- (here is where files go after compilation)

And I have an hello.css file with the following content:

#hello {
  background-image: url("/assets/images/hello.png")
}

Now, my config for CSS and PNG files will be something like:

{test: /\.css$/, loader: 'style-loader!css-loader?root=..}
{test: /\.(png)$/, loader: 'file-loader?name=[path][name].[ext]?[hash]&context=./src'}

This results in the output-ed css being (notice the missing / before the path):

#hello {
  background-image: url("assets/images/hello.png")
}

Which will work well as long as I access my application at /, but will fail for example if I share an URL like /hello/world because then the background image will be searched at /hello/world/assets/images/hello.png.

Should absoulte paths be translated? If I don't specify a root, then the file-loader doesn't kick in so I won't have my assets during build.

I see 2 options:

  • When you don't specify a root, css-loader requires the files anyway, just doesn't change the url.
  • If you specify a root, the loader is used but the path isn't translated.

What do you think?

Use 'Local scope' in isomorphics code

var styles = require('./index.css') raises obvious problem -- you can't use <div className={styles.myStyle} > in a component which renders server-side.

Up until now, when requiring css I used if (__BROWSER__) require('style.css') but to write <div className={( __BROWSER__ ? styles.myStyle : '')}> each time I think is too much.

This article suggests to use webpack to process backend but it suggests to use IgnorePlugin(/\.(css|less)$/) and I believe in case with Local scope won't work.

So is there any other option to use Local scope in isomorphic code without any weird hacks?

basscss like modules not supported?

Hi

I try to import the untransformed css of this:

https://github.com/jxnblk/basscss

but this:

@import '~basscss'

doesn't work. And also not:

@import '~basscss/src/basscss.css';

It has the following error:

ERROR in ../~/css-loader!../~/basscss/src/basscss.css
Module not found: Error: Cannot resolve 'file' or 'directory' ./basscss-base in /node_modules/basscss/src
 @ ../~/css-loader!../~/basscss/src/basscss.css 2:78-157

It doesn't correctly resolve dependencies.

How can I use this?

UPDATE: I found something similar: #12 . But resolve.alias is not a clean way to solve this.

Ignore images for loading

Is there a way I can tell the loader not to resolve a url to images in a url()

Would like:
background-image: url('../img/some-image.gif');
to output the same thing:
background-image: url('../img/some-image.gif');

When using local scope, `[name]` in `localIdentName` fails build

The local scope feature is working great for me so far, but if I use [name] in localIdentName, the CSS fails to compile. Other interpolated values work fine.

If I dig into loader-utils and change the pattern from [name] to [basename] it seems to work fine, but I'm too unfamiliar with webpack internals to figure out why that is significant.

I've reproduced this issue in a repo of mine, if you'd like to take a look. It's in the css-loader-with-debug-local-names branch: https://github.com/markdalgleish/react-progressive-component-starter/tree/css-loader-with-debug-local-names

Locals and ExtractTextPlugin

When I use local-scoped vars the require statement returns the selector names.

But when I use the ExtractTextPlugin, the selectors are no longer returned.

Should ExtractTextPlugin pass through the selectors hash from css-loader?

Unable to resolve `css-base.js` when using css-loader

When using the css-loader with a simple require("css!custom.css"); and an empty custom.css file, I receive the following error:

ERROR in ./~/css-loader!./app/css/custom.css
Module not found: Error: Cannot resolve 'file' or 'directory' ./../../node_modules/css-loader/lib/css-base.js in C:\Gnu\tmp\css-loader-webpack/app/css
 @ ./~/css-loader!./app/css/custom.css 1:27-85

This seems to be a Windows specific error as I tried the same thing on a Unix system and it works there. So, probably a path problem when trying to resolve this line in /lib/loader.js:

163: return "exports = module.exports = require(" + loaderUtils.stringifyRequest(this, require.resolve("./css-base.js")) + ")();\n" +

I'm looking into guide lines on how to debug and hunt this bug. Any code location or ideas is welcomed.

To replicate, here a simple test case (on a Windows system).

# Layout
$ tree
├── app
│   ├── css
│   │   └── custom.css
│   └── js
│       └── main.js
└── webpack.config.js

# Node Modules
$ npm install style-loader css-loader

# app/css/custom.css

# app/js/main.js
require("css!custom.css");

# webpack.config.js
module.exports = {
  entry: "main.js",
  output: { filename: "bundle.js" },
  resolve: { root: [__dirname + "/app/css", __dirname + "/app/js"] },
};

# Command
$ webpack
Hash: 9eb81684d5adc83ab296
Version: webpack 1.9.10
Time: 216ms
    Asset    Size  Chunks             Chunk Names
bundle.js  1.8 kB       0  [emitted]  main
   [0] ./app/js/main.js 26 bytes {0} [built]
    + 1 hidden modules

ERROR in ./~/css-loader!./app/css/custom.css
Module not found: Error: Cannot resolve 'file' or 'directory' ./../../node_modules/css-loader/lib/css-base.js in C:\Gnu\tmp\css-loader-webpack/app/css
 @ ./~/css-loader!./app/css/custom.css 1:27-85

Errors loading ionicons.css

ERROR in ./ionicons-1.5.2/fonts/ionicons.eot?v=1.5.2
Module parse failed: /***/ionicons-1.5.2/fonts/ionicons.eot?v=1.5.2 Line 1: Unexpected token ILLEGAL
You may need an appropriate loader to handle this file type.
(Source code omitted for this binary file)
@ ./~/css-loader!./ionicons-1.5.2/css/ionicons.css 2:300-340 2:356-396

ERROR in ./ionicons-1.5.2/fonts/ionicons.woff?v=1.5.2
Module parse failed: /***/ionicons-1.5.2/fonts/ionicons.woff?v=1.5.2 Line 1: Unexpected token ILLEGAL
You may need an appropriate loader to handle this file type.
(Source code omitted for this binary file)
@ ./~/css-loader!./ionicons-1.5.2/css/ionicons.css 2:515-556

etc...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.