GithubHelp home page GithubHelp logo

webpack-contrib / style-loader Goto Github PK

View Code? Open in Web Editor NEW
1.6K 35.0 474.0 3.72 MB

Style Loader

License: MIT License

JavaScript 95.04% HTML 2.19% CSS 2.39% SCSS 0.37%
webpack-loader stylesheets loader webpack

style-loader's Introduction

Style Loader

npm node tests coverage discussion size

style-loader

Inject CSS into the DOM.

Getting Started

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

npm install --save-dev style-loader

or

yarn add -D style-loader

or

pnpm add -D style-loader

It's recommended to combine style-loader with the css-loader

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

style.css

body {
  background: green;
}

component.js

import "./style.css";

webpack.config.js

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

Security Warning

This loader is primarily meant for development. The default settings are not safe for production environments. See the recommended example configuration and the section on nonces for details.

Options

injectType

Type:

type injectType =
  | "styleTag"
  | "singletonStyleTag"
  | "autoStyleTag"
  | "lazyStyleTag"
  | "lazySingletonStyleTag"
  | "lazyAutoStyleTag"
  | "linkTag";

Default: styleTag

Allows to setup how styles will be injected into the DOM.

Possible values:

styleTag

Automatically injects styles into the DOM using multiple <style></style>. It is default behaviour.

component.js

import "./styles.css";

Example with Locals (CSS Modules):

component-with-css-modules.js

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

const divElement = document.createElement("div");
divElement.className = styles["my-class"];

All local variables (class names) are exported as named exports. To achieve this behaviour you also have to setup modules option for css-loader. For more information consult with css-loader documentation.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          // The `injectType`  option can be avoided because it is default behaviour
          { loader: "style-loader", options: { injectType: "styleTag" } },
          {
            loader: "css-loader",
            // Uncomment it if you want to use CSS modules
            // options: { modules: true }
          },
        ],
      },
    ],
  },
};

The loader inject styles like:

<style>
  .foo {
    color: red;
  }
</style>
<style>
  .bar {
    color: blue;
  }
</style>

singletonStyleTag

Automatically injects styles into the DOM using one <style></style>.

Warning

Source maps do not work.

component.js

import "./styles.css";

component-with-css-modules.js

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

const divElement = document.createElement("div");
divElement.className = styles["my-class"];

All local variables (class names) are exported as named exports. To achieve this behaviour you also have to setup modules option for css-loader. For more information consult with css-loader documentation.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: "style-loader",
            options: { injectType: "singletonStyleTag" },
          },
          {
            loader: "css-loader",
            // Uncomment it if you want to use CSS modules
            // options: { modules: true }
          },
        ],
      },
    ],
  },
};

The loader inject styles like:

<style>
  .foo {
    color: red;
  }
  .bar {
    color: blue;
  }
</style>

autoStyleTag

Works the same as a styleTag, but if the code is executed in IE6-9, turns on the singletonStyleTag mode.

lazyStyleTag

Injects styles into the DOM using multiple <style></style> on demand. We recommend following .lazy.css naming convention for lazy styles and the .css for basic style-loader usage (similar to other file types, i.e. .lazy.less and .less). When you lazyStyleTag value the style-loader injects the styles lazily making them useable on-demand via style.use() / style.unuse().

⚠️ Behavior is undefined when unuse is called more often than use. Don't do that.

component.js

import styles from "./styles.lazy.css";

styles.use();
// For removing styles you can use
// styles.unuse();

component-with-css-modules.js

import styles, { "my-class" as myClass } from "./styles.lazy.css";

styles.use();

const divElement = document.createElement("div");
divElement.className = myClass;

All local variables (class names) are exported as named exports. To achieve this behaviour you also have to setup modules option for css-loader. For more information consult with css-loader documentation.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        exclude: /\.lazy\.css$/i,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.lazy\.css$/i,
        use: [
          { loader: "style-loader", options: { injectType: "lazyStyleTag" } },
          {
            loader: "css-loader",
            // Uncomment it if you want to use CSS modules
            // options: { modules: true }
          },
        ],
      },
    ],
  },
};

The loader inject styles like:

<style>
  .foo {
    color: red;
  }
</style>
<style>
  .bar {
    color: blue;
  }
</style>

lazySingletonStyleTag

Injects styles into the DOM using one <style></style> on demand. We recommend following .lazy.css naming convention for lazy styles and the .css for basic style-loader usage (similar to other file types, i.e. .lazy.less and .less). When you lazySingletonStyleTag value the style-loader injects the styles lazily making them useable on-demand via style.use() / style.unuse().

⚠️ Source maps do not work.

⚠️ Behavior is undefined when unuse is called more often than use. Don't do that.

component.js

import styles from "./styles.css";

styles.use();
// For removing styles you can use
// styles.unuse();

component-with-css-modules.js

import styles, { "my-class" as myClass } from "./styles.lazy.css";

styles.use();

const divElement = document.createElement("div");
divElement.className = myClass;

All local variables (class names) are exported as named exports. To achieve this behaviour you also have to setup modules option for css-loader. For more information consult with css-loader documentation.

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        exclude: /\.lazy\.css$/i,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.lazy\.css$/i,
        use: [
          {
            loader: "style-loader",
            options: { injectType: "lazySingletonStyleTag" },
          },
          {
            loader: "css-loader",
            // Uncomment it if you want to use CSS modules
            // options: { modules: true }
          },
        ],
      },
    ],
  },
};

The loader generate this:

<style>
  .foo {
    color: red;
  }
  .bar {
    color: blue;
  }
</style>

lazyAutoStyleTag

Works the same as a lazyStyleTag, but if the code is executed in IE6-9, turns on the lazySingletonStyleTag mode.

linkTag

Injects styles into the DOM using multiple <link rel="stylesheet" href="path/to/file.css"> .

ℹ️ The loader will dynamically insert the <link href="path/to/file.css" rel="stylesheet"> tag at runtime via JavaScript. You should use MiniCssExtractPlugin if you want to include a static <link href="path/to/file.css" rel="stylesheet">.

import "./styles.css";
import "./other-styles.css";

webpack.config.js

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

The loader generate this:

<link rel="stylesheet" href="path/to/style.css" />
<link rel="stylesheet" href="path/to/other-styles.css" />

attributes

Type:

type attributes = HTMLAttributes;

Default: {}

If defined, the style-loader will attach given attributes with their values on <style> / <link> element.

component.js

import "./file.css";

webpack.config.js

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

insert

Type:

type insert = string;

Default: head

By default, the style-loader appends <style>/<link> elements to the end of the style target, which is the <head> tag of the page unless specified by insert. This will cause CSS created by the loader to take priority over CSS already present in the target. You can use other values if the standard behavior is not suitable for you, but we do not recommend doing this. If you target an iframe make sure you have sufficient access rights, the styles will be injected into the content document head.

Selector

Allows to setup custom query selector where styles inject into the DOM.

webpack.config.js

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

Absolute path to function

Allows to setup absolute path to custom function that allows to override default behavior and insert styles at any position.

Warning

Do not forget that this code will be used in the browser and not all browsers support latest ECMA features like let, const, arrow function expression and etc. We recommend using babel-loader for support latest ECMA features.

Warning

Do not forget that some DOM methods may not be available in older browsers, we recommended use only DOM core level 2 properties, but it is depends what browsers you want to support

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: "style-loader",
            options: {
              insert: require.resolve("./path-to-insert-module"),
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};

A new <style>/<link> elements will be inserted into at bottom of body tag.

Examples:

Insert styles at top of head tag:

insert-function.js

function insertAtTop(element) {
  var parent = document.querySelector("head");
  // eslint-disable-next-line no-underscore-dangle
  var lastInsertedElement = window._lastElementInsertedByStyleLoader;

  if (!lastInsertedElement) {
    parent.insertBefore(element, parent.firstChild);
  } else if (lastInsertedElement.nextSibling) {
    parent.insertBefore(element, lastInsertedElement.nextSibling);
  } else {
    parent.appendChild(element);
  }

  // eslint-disable-next-line no-underscore-dangle
  window._lastElementInsertedByStyleLoader = element;
}

module.exports = insertAtTop;

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: "style-loader",
            options: {
              insert: require.resolve("./insert-function"),
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};

You can pass any parameters to style.use(options) and this value will be passed to insert and styleTagTransform functions.

insert-function.js

function insertIntoTarget(element, options) {
  var parent = options.target || document.head;

  parent.appendChild(element);
}

module.exports = insertIntoTarget;

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: "style-loader",
            options: {
              injectType: "lazyStyleTag",
              // Do not forget that this code will be used in the browser and
              // not all browsers support latest ECMA features like `let`, `const`, `arrow function expression` and etc,
              // we recommend use only ECMA 5 features,
              // but it depends what browsers you want to support
              insert: require.resolve("./insert-function.js"),
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};

Insert styles to the provided element or to the head tag if target isn't provided. Now you can inject styles into Shadow DOM (or any other element).

custom-square.css

div {
  width: 50px;
  height: 50px;
  background-color: red;
}

custom-square.js

import customSquareStyles from "./custom-square.css";

class CustomSquare extends HTMLElement {
  constructor() {
    super();

    this.attachShadow({ mode: "open" });

    const divElement = document.createElement("div");

    divElement.textContent = "Text content.";

    this.shadowRoot.appendChild(divElement);

    customSquareStyles.use({ target: this.shadowRoot });

    // You can override injected styles
    const bgPurple = new CSSStyleSheet();
    const width = this.getAttribute("w");
    const height = this.getAttribute("h");

    bgPurple.replace(`div { width: ${width}px; height: ${height}px; }`);

    this.shadowRoot.adoptedStyleSheets = [bgPurple];

    // `divElement` will have `100px` width, `100px` height and `red` background color
  }
}

customElements.define("custom-square", CustomSquare);

export default CustomSquare;

styleTagTransform

Type:

type styleTagTransform = string;

Default: undefined

string

Allows to setup absolute path to custom function that allows to override default behavior styleTagTransform.

Warning

Do not forget that this code will be used in the browser and not all browsers support latest ECMA features like let, const, arrow function expression and etc, we recommend use only ECMA 5 features, but it is depends what browsers you want to support

Warning

Do not forget that some DOM methods may not be available in older browsers, we recommended use only DOM core level 2 properties, but it depends what browsers you want to support

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: "style-loader",
            options: {
              injectType: "styleTag",
              styleTagTransform: require.resolve("style-tag-transform-code"),
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};

base

type base = number;

This setting is primarily used as a workaround for css clashes when using one or more DllPlugin's. base allows you to prevent either the app's css (or DllPlugin2's css) from overwriting DllPlugin1's css by specifying a css module id base which is greater than the range used by DllPlugin1 e.g.:

webpack.dll1.config.js

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

webpack.dll2.config.js

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

webpack.app.config.js

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

esModule

Type:

type esModule = boolean;

Default: true

By default, style-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: "style-loader",
        options: {
          esModule: false,
        },
      },
    ],
  },
};

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.

Warning

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

webpack.config.js

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

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

Named export for CSS Modules

Warning

It is not allowed to use JavaScript reserved words in css class names.

Warning

Options esModule and modules.namedExport in css-loader should be enabled (by default for css-loader@7 it is true).

styles.css

.fooBaz {
  color: red;
}
.bar {
  color: blue;
}
.my-class {
  color: green;
}

index.js

import { fooBaz, bar, "my-class" as myClass } from "./styles.css";

console.log(fooBaz, bar, myClass);

Or:

index.js

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

console.log(styles.fooBaz, styles.bar, styles["my-class"]);

You can enable a ES module named export using:

webpack.config.js

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

Source maps

The loader automatically inject source maps when previous loader emit them. Therefore, to generate source maps, set the sourceMap option to true for the previous loader.

webpack.config.js

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

Nonce

If you are using a Content Security Policy (CSP), the injected code will usually be blocked. A workaround is to use a nonce. Note, however, that using a nonce significantly reduces the protection provided by the CSP. You can read more about the security impact in the specification. The better solution is not to use this loader in production.

There are two ways to work with nonce:

  • using the attributes option
  • using the __webpack_nonce__ variable

Warning

the attributes option takes precedence over the __webpack_nonce__ variable

attributes

component.js

import "./style.css";

webpack.config.js

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

The loader generate:

<style nonce="12345678">
  .foo {
    color: red;
  }
</style>

__webpack_nonce__

create-nonce.js

__webpack_nonce__ = "12345678";

component.js

import "./create-nonce.js";
import "./style.css";

Alternative example for require:

component.js

__webpack_nonce__ = "12345678";

require("./style.css");

webpack.config.js

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

The loader generate:

<style nonce="12345678">
  .foo {
    color: red;
  }
</style>

Insert styles at top

Insert styles at top of head tag.

insert-function.js

function insertAtTop(element) {
  var parent = document.querySelector("head");
  var lastInsertedElement = window._lastElementInsertedByStyleLoader;

  if (!lastInsertedElement) {
    parent.insertBefore(element, parent.firstChild);
  } else if (lastInsertedElement.nextSibling) {
    parent.insertBefore(element, lastInsertedElement.nextSibling);
  } else {
    parent.appendChild(element);
  }

  window._lastElementInsertedByStyleLoader = element;
}

module.exports = insertAtTop;

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: "style-loader",
            options: {
              insert: require.resolve("./insert-function.js"),
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};

Insert styles before target element

Inserts styles before #id element.

insert-function.js

function insertBeforeAt(element) {
  const parent = document.querySelector("head");
  const target = document.querySelector("#id");

  const lastInsertedElement = window._lastElementInsertedByStyleLoader;

  if (!lastInsertedElement) {
    parent.insertBefore(element, target);
  } else if (lastInsertedElement.nextSibling) {
    parent.insertBefore(element, lastInsertedElement.nextSibling);
  } else {
    parent.appendChild(element);
  }

  window._lastElementInsertedByStyleLoader = element;
}

module.exports = insertBeforeAt;

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: "style-loader",
            options: {
              insert: require.resolve("./insert-function.js"),
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};

Custom Elements (Shadow DOM)

You can define custom target for your styles for the lazyStyleTag type.

insert-function.js

function insertIntoTarget(element, options) {
  var parent = options.target || document.head;

  parent.appendChild(element);
}

module.exports = insertIntoTarget;

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          {
            loader: "style-loader",
            options: {
              injectType: "lazyStyleTag",
              // Do not forget that this code will be used in the browser and
              // not all browsers support latest ECMA features like `let`, `const`, `arrow function expression` and etc,
              // we recommend use only ECMA 5 features,
              // but it is depends what browsers you want to support
              insert: require.resolve("./insert-function.js"),
            },
          },
          "css-loader",
        ],
      },
    ],
  },
};

Insert styles to the provided element or to the head tag if target isn't provided.

custom-square.css

div {
  width: 50px;
  height: 50px;
  background-color: red;
}

custom-square.js

import customSquareStyles from "./custom-square.css";

class CustomSquare extends HTMLElement {
  constructor() {
    super();

    this.attachShadow({ mode: "open" });

    const divElement = document.createElement("div");

    divElement.textContent = "Text content.";

    this.shadowRoot.appendChild(divElement);

    customSquareStyles.use({ target: this.shadowRoot });

    // You can override injected styles
    const bgPurple = new CSSStyleSheet();
    const width = this.getAttribute("w");
    const height = this.getAttribute("h");

    bgPurple.replace(`div { width: ${width}px; height: ${height}px; }`);

    this.shadowRoot.adoptedStyleSheets = [bgPurple];

    // `divElement` will have `100px` width, `100px` height and `red` background color
  }
}

customElements.define("custom-square", CustomSquare);

export default CustomSquare;

Contributing

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

CONTRIBUTING

License

MIT

style-loader's People

Contributors

alexander-akait avatar cap-bernardito avatar diurnalist avatar ekulabuhov avatar elsbree avatar erictheswift avatar ersachin3112 avatar evilebottnawi avatar gryzzly avatar jonathantneal avatar joshwiens avatar lydell avatar marcogrcr avatar mattgurney avatar mgol avatar michael-ciniawsky avatar nickdima avatar olegwock avatar oskarer avatar piperchester avatar pleunv avatar simenb avatar simon04 avatar sirlancelot avatar snitin315 avatar sokra avatar sontek avatar spacek33z avatar svenheden avatar tgriesser 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

style-loader's Issues

Enhancement: Allow customization of request URI to differ from source file's URI

I have the following loader expression:
style/url?limit=0!file?name=css/[name].css!sass

If, for example, I have a hello.sass file, it is compiled and written as a plain text/css file to css/hello.css. Finally, the style/url part yields the following javascript that I want which dynamically loads the css file:

/* 6 */
/***/ function(module, exports, __webpack_require__) {

    module.exports = __webpack_require__.p + "css/hello.css"

/***/ },
/* 7 */
/***/ function(module, exports, __webpack_require__) {

    /*
        MIT License http://www.opensource.org/licenses/mit-license.php
        Author Tobias Koppers @sokra
    */
    module.exports = function addStyleUrl(cssUrl) {
        if(false) {
            if(typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment");
        }
        var styleElement = document.createElement("link");
        styleElement.rel = "stylesheet";
        styleElement.type = "text/css";
        styleElement.href = cssUrl;
        var head = document.getElementsByTagName("head")[0];
        head.appendChild(styleElement);
        if(false) {
            return function(cssUrl) {
                if(typeof cssUrl === "string") {
                    styleElement.href = cssUrl;
                } else {
                    head.removeChild(styleElement);
                }
            };
        }
    }

/***/ }

I would like more control over module 6. Specifically, I'd like to be able to add the [hash] for the hello.css as a query string parameter to the end of the "css/hello.css" URI. Generating the javascript with the [hash] in the URI's query string will allow me to serve my .css with a never-expires cache header and maximize the user's browser cache.

Ideally, module 6 would look something like this:

/* 6 */
/***/ function(module, exports, __webpack_require__) {

    module.exports = __webpack_require__.p + "css/hello.css?09341d1ff67217aae4777cf9222efe5f"

/***/ },

I tried modifying name on the style/url, but this did not seem to have any effect:
style/url?limit=0&name=css/[name].css?[hash]!file?name=css/[name].css!sass

Is there a way that I can tailor the URI generated for the .css URL request? If not, may I request that as an enhancement for style-loader? Thanks!

styles.use need callback

hi i'm using webpack style-loader with React.js
i trying to load css with styles.use() like this

componentWillMount() {
      styles.use();
    }

But CSS file is injected after react's render() method.

how can I know inject state? or using with callback?

Generated image urls *must* be absolute for style!css?sourceMap to work?

Is there a way to make images load in browser when using style-loader/css-loader?sourceMap without specifying absolute url prefix as publicPath?

With this loader:

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

This works:

output = {
  path: 'build',
  publicPath: 'http://0.0.0.0:8080/'
  filename: 'bundle.js'
};

This doesn't:

output = {
  path: 'build',
  publicPath: '/'
  filename: 'bundle.js'
};

In the CSS modules generated as Blob the paths are relative to chrome:blob or chrome:devtools which doesn't refer to the correct assets.

If my assumption is correct and we always have to set absolute path in output.publicPath I will be happy to add a note about this to the docs.

Requiring multiple stylesheets with the same relative path doesn't work

As of b9fdff5, I'm running into an issue when requiring multiple stylesheets with the same relative path.

The easiest way to reproduce is to use https://github.com/lern/react-starter, which is a fork of https://github.com/webpack/react-starter that I slightly modified to use version 0.10.1 of style-loader and added an additional require of a stylesheet called style.css. If you do a npm run build, npm start, and navigate to localhost:8080, you will see this error:

Uncaught TypeError: Cannot read property 'call' of undefined

I'm not entirely sure how to debug further, but I've narrowed it down to b9fdff5 and also observed that the issue only happens if I have multiple require statements of the same relative path (eg. require("./style.css");), but in different directories (ie. the paths resolve to different files). I don't hit the issue if I run in HMR mode.

Loader expose filesystem paths

I use:
require("./design/style.css");
Part of config:

        loaders: [
          { test: /\.css$/, loader: 'style!css' }
        ]

Result somewhere in build/bundle.js:

    // style-loader: Adds some css to the DOM by adding a <style> tag

    // load the styles
    var content = __webpack_require__(7);
    if(typeof content === 'string') content = [[module.id, content, '']];
    // add the styles to the DOM
    var update = __webpack_require__(14)(content);
    // Hot Module Replacement
    if(false) {
        // When the styles change, update the <style> tags
        module.hot.accept("!!D:\\My\\Dev\\Project\\node_modules\\css-loader\\index.js!D:\\My\\Dev\\Project\\src\\design\\style.css", function() {
            var newContent = require("!!D:\\My\\Dev\\Project\\node_modules\\css-loader\\index.js!D:\\My\\Dev\\Project\\src\\design\\style.css");
            if(typeof newContent === 'string') newContent = [module.id, newContent, ''];
            update(newContent);
        });
        // When the module is disposed, remove the <style> tags
        module.hot.dispose(function() { update(); });
    }

Need to get rid of absolute paths!

singleton mode problems in IE9

cssText in IE does not supports media queries, i.e. does not return them (I think because of backwards compatibility). So when in single mode (which is by default) you use media queries and that stylesheet with media queries was required before some other -- then you loose your media queries.

Probably for IE you should store stylesheet in memory (i.e. object/array) and when new modification/addition comes just concatenate all entries and again apply original string to stylesheet.

For my case I just disabled singleton mode, but it's not obvious at first glance that you need to do it.

Passing document to .use

I need to be able to pass the document to the .use method in which it should attach the document, due to iFrame buster business. Any way of doing this currently or thought on perhaps adding as an added feature?

Thanks.

unuse/unref doesn't seem to working

I can't seem to be able to get unuse() to remove the style from the page. Calling use() correctly loads the style, but calling unuse() doesn't remove it.

My loaders are setup as such:

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

And my code looks like this:

var style = require('style/useable!./../less/themes/' + this.state.theme + '.less');
style.use(); // This works
style.unuse(); // This doesn't work

Any idea what could be going wrong?

0.8.2 breaks my tests running in the PhantomJS

Hi, just a little bug i found:

I'm using the style-loader (since 0.8.1) in the following manner (just this one line):
require('!style!css!sass!./someFile.scss');

The version 0.8.2 seems to work under IE11, latest FF and latest Chrome, but it breaks execution of several tests in the PhantomJS. For the moment I'm keeping "0.8.1" in my list of depenencies....

Cheers,
rb

Error with hot reloading and "-d": "SyntaxError: missing ) after argument list"

This is style-loader@~0.8.0. My *.styl loader looks like this: { test: /\.styl$/, loader: 'style!css!stylus' }.

The offending lines (specifically the one with module.hot.accept):

if(true) {
    // When the styles change, update the <style> tags
    module.hot.accept(/*! !../~/css-loader!../~/stylus-loader!./viewer.styl */ 2/*! !../~/css-loader!../~/stylus-loader!./viewer.styl */ 2, function() {
        var newContent = __webpack_require__(/*! !../~/css-loader!../~/stylus-loader!./viewer.styl */ 2);
        if(typeof newContent === 'string') newContent = [module.id, newContent, ''];
        update(newContent);
    });
    // When the module is disposed, remove the <style> tags
    module.hot.dispose(function() { update(); });
}

HMR only working for last instance

I currently have some style entry points with one module each. Each module goes through a loader that returns a URL, then goes through style/url to added a , but only the last entry point can accept and swap updates. The others say the page requires a reload. Weird setup, I know. There is also one commons chunk with the webpack runtime.

I can try testing this out in a more isolated environment, but let me know if anything looks wrong in the above that could cause this. Thanks!

sourcemaps are JS code

hello,

I activated the source maps options with the css-loader, and sourcemaps for my CSS files are JavaScript code, is there any way to fix this?

example sourcemap :

exports = module.exports = require("/Users/_mlb/dev/app/node_modules/css-loader/cssToString.js")();
exports.push([module.id, ".Carousel {\n  position: relative;\n}\n\n  .Carousel-container {\n    font-size: 0;\n  }\n\n    .Carousel-item {\n      font-size: 16px;\n      font-size: 1rem;\n      display: inline-block;\n      vertical-align: top;\n    }\n\n  .Carousel-dots {\n    position: absolute;\n    bottom: 1em;\n    left: 0;\n    right: 0;\n    text-align: center;\n  }\n\n  .Carousel-dot {\n    display: inline-block;\n    vertical-align: middle;\n    margin: 0 .5em;\n    height: .625em;\n    width: .625em;\n    background: #002d5f;\n    box-shadow: 0 0 0 .15em #fff;\n    border-radius: 100%;\n    cursor: pointer;\n  }\n\n    .Carousel-dot--active {\n      background: #fff;\n      box-shadow: 0 0 0 .25em #002d5f;\n    }\n", ""]);


/*****************
 ** WEBPACK FOOTER
 ** ./~/css-loader?sourceMap?minimize!./~/cssnext-loader!./src/stylesheets/Carousel/Carousel.css
 ** module id = 205
 ** module chunks = 0
 **/

Idea: Debounce adding of styles for better performance

I'm thinking about this issue quite a while but haven't found the time to write it down.

My co-worker was working on an app (without webpack) where he wanted to define style rules per component. These styles should only be applied if the component is currently in use, so he added and removed the style nodes accordingly.

While the theory is very nice, it has a serious performance impact. Because when a style node is added or removed the browser needs to recalculate all styles and to reflow the whole document. So when a page changed, the browser needed to recalculate and to reflow several times.

I was wondering if this problem could be solved by the style-loader. I was thinking about debouncing the call where the <style> node is actually added to the DOM.

This feature needs to be tested carefully to avoid FOUTs (Flash of Unstyled Text) or other ugly problems when unstyled content is added to the DOM.

Add sourceURL to inline styles

Hey, I've been looking for a way to use CSS sourcemaps in dev with watch or dev-server, which unfortunately means extract-text-webpack-plugins can't be used.

However, I did find out that sourceURL works for inline <style> tags so I'm creating a temporary loader to add that to the end of CSS modules. Could this be done automatically through style-loader? I'd be happy to make a pull request, just let me know if you have any specifics regarding URL naming. Thanks!

(FYI this only seems to work in Chrome, but good enough for now)

If you're only requiring a single stylesheet, the loader breaks

As far as I can tell, if you require a stylesheet, and the return is a string, it sets

content = [module.id, content, '']; here

Then it loops over list.length here, but it seems it should be looping over a list of modules rather than the array above.

Setting the following seems to fix it, but i wanted to make sure I wasn't overlooking something:
content = [[module.id, content, '']];

HotModules addStyles update listToStyles destroying all css on update

In my single entry I have one require for CSS

require('../app_common.scss')

Everything works great on initial load but when update in addStyles is called it gets called with

[
module_id,
css,
sourceMap
]

instead of

[
[
module_id,
css,
sourceMap
]
]

It seems to be missing the outer array wrapper. So when this gets passed to listToStyles call it blows away all CSS.
Just to confirm I changed the call to listToStyles([newList]) and it worked fine but I don't know enough about hot module swapping and the packages that get passed around to understand why the dev-server is not serving up the correct structure to the update call or if this is addStyles fault.

Current versions

    "webpack": "^1.4.13",
    "webpack-dev-server": "^1.7.0",

Using style/raw/sass loaders

    processedLoaders.push({ test: /\.scss/, loader: "style-loader!raw-loader!sass-loader?outputStyle=expanded&includePaths[]=" +(path.join(__dirname, "../node_modules/compass-mixins/lib"))});

npm script run

    "hot-dev-server": "webpack-dev-server --content-base cjs/ --config webpack-dev.config.js --hot --progress --colors --port 2992 --inline --debug"

style-loader generates `if (false)` code

I get a lot of warnings if I combine style-loader and the uglify plugin. The generated if (false) results in "Condition always false" and "Dropping unreachable code" warnings from uglify. Why not just skip that part entirely when emitting the code?

Why does "hot" code get included by default?

I have a bundle that I'm creating that leverages style-loader. When I was looking at the source I noticed the following:

...
/* 2 */
/***/ function(module, exports, __webpack_require__) {

    // style-loader: Adds some css to the DOM by adding a <style> tag
    var dispose = __webpack_require__(4)
        // The css code:
        (__webpack_require__(3))
    if(false) {
        module.hot.accept();
        module.hot.dispose(dispose);
    }

/***/ },
...

As you can see there is a weird if statement and module.hot code included out of the box.

I thought it was something that I was doing wrong, so I ran through the getting started tute you have on the site, and it produced the same output.

Any reasons for this, to me it seems to confuse the issue.

Error: Style loader do not work as pre or post loader

I'm using the mocha-loader for my tests. My webpack config looks like this:

module.exports = {
    entry: "mocha!" + __dirname + "/main.js",
    devtool: "eval",
    define: {
        /**
         * These variables need to be defined in order to resolve conditional requires because of
         * internal code coverage tests of chai modules
         */
        "process.env.eql_COV": false,
        "process.env.type_COV": false
    }
};

This config is consumed by the webpack-dev-server via this command:

node node_modules/webpack-dev-server/bin/webpack-dev-server.js --config ./test/test.config.js

Now webpack gives me (randomly) this error message:

ERROR in ./~/mocha-loader/~/style-loader!./~/mocha-loader/~/css-loader!./~/mocha/mocha.css
Module build failed: Error: style-loader do not work as pre or post loader
    at Object.module.exports (c:\Users\jhnns\dev\alamid-view\node_modules\mocha-loader\node_modules\style-loader\index.js:9:40)

A console.log(this.loaderType); in index.js:9 returns undefined

When composed with css loader and optimized with -p, uglify strips out code...

Source Code

import React from 'react';
import Style from 'utilities/Style';
import CSS from './InputWithIcon.css';

class InputWithIcon extends React.Component {
  render() {
    return (
      <div className={CSS.InputWithIcon}>
        <div className={CSS.InputWithIcon__Icon}>{this.props.icon}</div>
        <input type="text" {...this.props} className={CSS.InputWithIcon__Input} />
      </div>
    );
  }
}

export default InputWithIcon;

Webpack Configuration

var webpack = require('webpack');
var autoprefixer = require('autoprefixer-core');
var env = new webpack.DefinePlugin({
  __DEVELOPMENT__: JSON.stringify(JSON.parse(process.env.DEVELOPMENT || 'true'))
});


module.exports = {
  entry: './src/bootstrap',

  output: {
    filename: '[name].js',
    path: 'compiled',
    publicPath: '/m/'
  },

  module: {
    loaders: [
      { test: /(src|test)(.+)\.js$/, loader: 'babel-loader?stage=0&optional=runtime'},
      { test: /\.css$/, exclude: /\.global\.css$/, loader: 'style-loader!css-loader?modules!postcss-loader' },
      { test: /\.global\.css$/, loader: 'style!css!postcss-loader' },
      { test: require.resolve('react'), loader: 'expose?React' },
      { test: /(\.svg|\.png)$/, loader: 'file'},
      { test: /traceur-runtime/, loader: 'imports?this=>window' }
    ],
    noParse: /traceur/
  },

  plugins: [
    env,
    new webpack.optimize.UglifyJsPlugin()
  ],

  resolve: {
    modulesDirectories: ['web_modules', 'node_modules', 'src']
  },

  postcss: [ autoprefixer({ browsers: ['last 2 version'] }) ]

};

Error

Condition always false [./~/style-loader!./~/css-loader?modules!./~/postcss-loader!./src/components/InputWithIcon.css:10,0]
Dropping unreachable code [./~/style-loader!./~/css-loader?modules!./~/postcss-loader!./src/components/InputWithIcon.css:12,0]
Side effects in initialization of unused variable update [./~/style-loader!./~/css-loader?modules!./~/postcss-loader!./src/components/InputWithIcon.css:7,0]

IE8 (and below): Replacing CSS containing @font-face results in "invisible" page

I've been having issues with style-loader and IE8, which I've narrowed down to this line:
https://github.com/webpack/style-loader/blob/master/addStyles.js#L169

When a stylesheet containing @font-face is applied, a subsequent stylesheet causes the page to be rendered as "invisible". The page appears completely blank, but everything is there (you can see that the elements are there when using IE's DOM inspector).

This issue goes away when I do something like:

    if (!/@font-face/.test(css)) {
      styleElement.styleSheet.cssText = replaceText(index, css);
    }

But, of course, the stylesheet with @font-face isn't applied.

Googling the symptoms, I found:
keithclark/selectivizr#30
http://stiankarlsen.me/blog/how-to-fix-selectivizr-in-ie8/

Which gives me a couple of things that I can try. I'll attempt to:

  1. load @font-face into a separate stylesheet (not in the <head>)
  2. parse the font URL and load it with a <link> (in the <head>)

I'll give this a shot and submit a PR if any of this works. Otherwise, if there is anything else I try or fallback to, I'd like to know.

webpack build does not progress when using style/useable

Hi @sokra

when I try to swap the themes by using style/useable loader and it somehow cause webpack build to stand still.
I have two .useable.scss to swap between each others as follow:

  1. defaut.useable.scss
$icon-font-path:        "../../../bower_components/bootstrap/fonts/" ;
$fa-font-path:          "../../../bower_components/font-awesome/fonts/" ;



@import "../../../bower_components/angular-block-ui/dist/angular-block-ui";
@import "../../../bower_components/toastr/toastr";
@import "../../../bower_components/font-awesome/scss/font-awesome";
@import "../../components/bootstrap-dialog/dist/scss/bootstrap-dialog";

// Override bootstrap variables
@import "app/variables";

// Bootstrap
@import "bootstrap/bootstrap";
..... /// remaining styles
  1. red.useable.scss
$brand-primary:          #d12929;
$brand-info:             #a52d2d;



$icon-font-path:        "../../../bower_components/bootstrap/fonts/" ;
$fa-font-path:          "../../../bower_components/font-awesome/fonts/" ;



@import "../../../bower_components/angular-block-ui/dist/angular-block-ui";
@import "../../../bower_components/toastr/toastr";
@import "../../../bower_components/font-awesome/scss/font-awesome";
@import "../../components/bootstrap-dialog/dist/scss/bootstrap-dialog";

// Override bootstrap variables
@import "app/variables";

// Bootstrap
@import "bootstrap/bootstrap";
....... /// rest of the styles

the only difference between the two scss files is change in value for $brand-primary: #d12929 *
*$brand-info: #a52d2d;

  1. webpack.config
{ test: /\.scss/, exclude: /\.useable\.scss/, loader: "style!css!autoprefixer!sass" },
 { test: /\.useable\.scss/, loader: "style/useable!css!autoprefixer!sass" },
  1. App module
        require("./kendo-ui/kendo.less");
        require("./kendo-ui/kendo.ui.master");

        var blueTheme = require("content/styles/default.useable");
        blueTheme.use();
  1. Setting module
switchTheme() {

        this.toggleRedTheme = !this.toggleRedTheme;

        var oldTheme = require("content/styles/default.useable");
        var redTheme = require("content/styles/red.useable");


        if (this.toggleRedTheme) {
            oldTheme.unuse();
            redTheme.use();
        } else {
            redTheme.unuse();
            oldTheme.use();

        }

    }

when webpack run, it does not progress any further than what you can see in the attached image.
webpackbuild

It does not fail, it just hanging there without further progress. If I go and comment out the codes in switchTheme() then I can build again. Any idea where the issue might be?

Brief paragraph describing what the style-loader does?

Steps to reproduce:

  1. Forget everything you know about webpack
  2. See style loader be used in a webpack config file
  3. Desire to know what it does
  4. Google style-loader and go to github project

Expected Result

Find some brief documentation describing what the style loader does and its role in the webpack pipeline.

Actual Result

Find description of usage but no reference to what it does.

Notes

I'm new to webpack and trying to understand how best to manage my CSS/SASS code. At the moment I'm requiring it into my JS code and using the style-loader and then extracting it out with the ExtractTextPlugin. I'm looking for other approaches and so want to better understand what is currently going on and so would love to understand the exact role that the style-loader plays.

Cheers,
Michael

webpack-dev-server not watching changes in my imports

I just setup webpack-dev-server below are some of my configs

assets/entry.js

require('./styles/style')

assets/styles/style.scss

@imports ('utilities/other_style.scss')
  • Changes to style.scss get detected and rebuilds
  • Changes to imported file other_style do not get detected

Is this supposed to work? What's the solution for this with webpack-dev-server and hot module replacement setup?

As a work around what I could do is have all my imports be required from my entry.js file (that works) the issue is what about my global SCSS variables and mixins, I would have to import them in each file, wouldn't that slow things down alot? What is the right way to go about this?

Bug when using style-loader through node

Hi there,

We are using a node instance that runs webpack-dev-server with style-loader. I have narrowed down the issue which you can test on this test repo: https://github.com/christianalfoni/style-loader-bug. As stated in the README:

  1. npm install
  2. node server
  3. Go to localhost:3000
  4. The background color should be red
  5. If it is white, do a file change in app/main.js, just a lineshift, save and refresh... it works
  6. If it is red, please restart server until the problem occurs

When increasing number of chunks you will also start to get random errors in those chunks.

When I do not use style-loader but manually create style tags using the css loader it does not give this error.

Disabling loaders does not work inside url()

background-image(!url!./file) emits Module not found: Error: Cannot resolve directory '.' because it resolves to ./!url!./file. Putting require('!url!./file') inside JS works just fine though, so I can only assume this is something wrong with style-loader?

Does actually `use/ref` and 'unuse/unref` work?

I have no luck in making this API work:

import css from './list.css';
import React from 'react';

class ListContainer extends React.Component {
    constructor() {
        super();
    }

    componentDidMount() {
        css.use(); // no luck (function is undefined)
    }

    componentWillUnmount() {
        css.unuse();
    }

    render() {
        return ...
    }
}

usable and hmr issues

I'm seeing an issue with style-loader usable and HMR when the usable refs count is > 1. In this scenario, when a style module is updated the style disappears from the DOM but is never reinserted/updated. In the case where refs === 1, everything works as expected.

Looking at the code, I'm a little confused by how the refs in usable.js interacts with the refs count inside addStyles. But from a little debugging, it looks like the dispose callback in usable.js is getting called but exports.ref is not because refs > 0.

Allow to specify the position to insert new link/style tag

i want to be able to specify where to insert new link/style nodes. in my project bower deps. css should go before custom css, witch is built in one bundle and included in head tag.

having query option like insertAt: 'top' / 'bottom would do the trick

'Syntax error: unexpected number' with hot reload

I have this kind of configuration for less files

{ test: /\.less$/, loader: 'style-loader!css-loader!less-loader'},

It works fine if I run it without hot-reload, but turning on hot reload results in webpack-dev-server

Uncaught SyntaxError: Unexpected number

in resulting compiled file. The error is in 'module.hot.accept'.

I've tried different options, loading as url, loading just css file (just to check), but they all fail in the same way.

Error when using style loader

This is the output:

ERROR in ./~/css-loader!./ts/styles.css
Module build failed: CssSyntaxError: /Users/pdeva/code/dsgui/node_modules/style-loader/index.js!/Users/pdeva/code/dsgui/node_modules/css-loader/index.js!/Users/pdeva/code/dsgui/ts/styles.css:1:4: Unknown word
// style-loader: Adds some css to the DOM by adding a <style> tag
   ^

    at Input.error (/Users/pdeva/code/dsgui/node_modules/css-loader/node_modules/postcss/lib/input.js:61:21)
    at Parser.unknownDecl (/Users/pdeva/code/dsgui/node_modules/css-loader/node_modules/postcss/lib/parser.js:472:26)
    at Parser.decl (/Users/pdeva/code/dsgui/node_modules/css-loader/node_modules/postcss/lib/parser.js:227:22)
    at Parser.word (/Users/pdeva/code/dsgui/node_modules/css-loader/node_modules/postcss/lib/parser.js:135:30)
    at Parser.loop (/Users/pdeva/code/dsgui/node_modules/css-loader/node_modules/postcss/lib/parser.js:60:26)
    at parse (/Users/pdeva/code/dsgui/node_modules/css-loader/node_modules/postcss/lib/parse.js:25:12)
    at new LazyResult (/Users/pdeva/code/dsgui/node_modules/css-loader/node_modules/postcss/lib/lazy-result.js:57:24)
    at Processor.process (/Users/pdeva/code/dsgui/node_modules/css-loader/node_modules/postcss/lib/processor.js:36:16)
    at processCss (/Users/pdeva/code/dsgui/node_modules/css-loader/lib/processCss.js:186:11)
    at Object.module.exports (/Users/pdeva/code/dsgui/node_modules/css-loader/lib/loader.js:22:2)
 @ ./ts/main.js 7:10-37

This is the command I used to run webpack:

webpack-dev-server --progress --colors -hot      

This is my webpack.config.js:

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

module.exports = {
  devServer: {
        hot: true,
        progress: true,
        colors: true,
        historyApiFallback: true
    },
    entry: [
      'webpack-dev-server/client?http://localhost:8080', // WebpackDevServer host and port
      'webpack/hot/only-dev-server', // "only" prevents reload on syntax errors
      "./ts/main.js"
    ],
    output: {
        path: '.',
        filename: "bundle.js"
    },
    module: {
      loaders: [
          { test: /\.css$/, loader: "style!css" },
          {
            test: /components\\(.*)\.js$/,
            loaders: ['react-hot'],
            include: path.join(__dirname, 'ts')
          }
    ]

    }
};

What am i doing wrong?

IE8 Support?

Thanks so much for webpack! Though I've just started using it, my workflow is infinitely simpler. For the style-loader, do you plan to support IE8? ... if so, could the ES6 bind functions in the addStyle function be altered so I don't have to fork the library or use a polyfill?

Do something after styles have been updated

I want to apply viewport units polyfill on iOS 7 as soon as styles are added dynamically.

It's important I want to do this at runtime because it's optional — and I use ExtractTextPlugin so can't post-process all CSS on client side.

What would be the easiest way to do something after styles have been flushed?
I don't really care about reflows here because it's only for iOS 7.

IE throws "Not enough storage is available to complete this operation."

I'm seeing this exception in our production app with IE10 and 11. Here is what I've found so far:

Did you know that there is a JavaScript method createStyleSheet that you can call only 31 times.

Source: http://krasimirtsonev.com/blog/article/CKEditor-Not-enough-storage-is-available-to-complete-this-operation

Not sure if this can be fixed though but I think it should be reported here as well. I'll also try to create a test-case later and submit it to IE team.

style/useable not working with bundle loader and ExtractTextPlugin

The following config works:

{
    test: /theme\.[a-z]+\.less/,
    loader: "style/useable!css!less"
},

but I would like to force all themes in separate bundles.

The following configs do not work:

{
    test: /theme\.[a-z]+\.less/,
    loader: "bundle!style/useable!css!less"
},
{
    test: /theme\.[a-z]+\.less/,
    loader: ExtractTextPlugin.extract("style/useable", "css!less")
},

use/unuse is perfect for loading/unloading themes. Is there any way to benefit from this feature while forcing themes into separate bundles loaded on demand because it does not make sense to load many themes that a user won't use in the same common bundle?

0.12.0 throws "Cannot call method 'split' of undefined" errors

After upgrading to 0.12.0 (from 0.11.0) I am now getting the following errors when building my app:

WARNING in ./html/less/themes/black.less
Module build failed: TypeError: Cannot call method 'split' of undefined
    at Object.exports.stringifyRequest (/Users/me/Git/web-platform/node_modules/style-loader/node_modules/loader-utils/index.js:80:25)
    at Object.module.exports.pitch (/Users/me/Git/web-platform/node_modules/style-loader/useable.js:18:40)
 @ ./html/less/themes ^\.\/.*\.less$

WARNING in ./html/less/themes/white.less
Module build failed: TypeError: Cannot call method 'split' of undefined
    at Object.exports.stringifyRequest (/Users/me/Git/web-platform/node_modules/style-loader/node_modules/loader-utils/index.js:80:25)
    at Object.module.exports.pitch (/Users/me/Git/web-platform/node_modules/style-loader/useable.js:18:40)
 @ ./html/less/themes ^\.\/.*\.less$

ERROR in ./html/extensions/Alerts/less/main.less
Module build failed: TypeError: Cannot call method 'split' of undefined
    at Object.exports.stringifyRequest (/Users/me/Git/web-platform/node_modules/style-loader/node_modules/loader-utils/index.js:80:25)
    at Object.module.exports.pitch (/Users/me/Git/web-platform/node_modules/style-loader/useable.js:18:40)
 @ ./html/extensions/Alerts/js/view.js 15:0-30

ERROR in ./html/extensions/CommonComponents/less/main.less
Module build failed: TypeError: Cannot call method 'split' of undefined
    at Object.exports.stringifyRequest (/Users/me/Git/web-platform/node_modules/style-loader/node_modules/loader-utils/index.js:80:25)
    at Object.module.exports.pitch (/Users/me/Git/web-platform/node_modules/style-loader/useable.js:18:40)
 @ ./html/extensions/CommonComponents/js/components/NavBar.js 15:0-33

My LESS loader is configured as:

{test: /\.less$/, loaders: ["style/useable", "css?-restructuring", "less"]},

The issue does not occur when using 0.11.0.

Adding styles with @font-face crashes IE8

I noticed that the style-loader can crash IE 8 forcing it to close. I used the IE8 - XP virtual machine from modern.ie (IE 8.0.6001.18702) to test an application that adds a stylesheet containing a @font-face declaration.

The problem seems to be that the cssCode is added to the styleElement before the styleElement is appended to head. Changing the order so that the styleElement is part of the DOM-tree when setting the cssCode fixes the crash:

var styleElement = document.createElement("style");
styleElement.type = "text/css";
var head = document.getElementsByTagName("head")[0];
head.appendChild(styleElement);
if (styleElement.styleSheet) {
    styleElement.styleSheet.cssText = cssCode;
} else {
    styleElement.appendChild(document.createTextNode(cssCode));
}

Maybe this is caused by IE security checks (also see related issue) applied to @font-face, because adding other styles without @font-face works with the existing implementation.

Example

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
</head>
<body>

    <script type="text/javascript">
        (function() {
            // webpack output with urls replaced
            var cssCode = "@font-face {\n  font-family: \"Example\";\n  src: url("+"Example.eot"+"#iefix) format(\"eot\"), url("+"Example.woff"+") format(\"woff\"), url("+"Example.otf"+") format(\"opentype\"); }"
            var otherCssCode = "body{ background-color: red;}";

            // works
            // addStyle(otherCssCode);
            // addStyleFixed(otherCssCode);

            // crashes
            addStyle(cssCode);
            // works
            // addStyleFixed(cssCode);

            function addStyle(cssCode) {
                if(true) {
                    if(typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment");
                }
                var styleElement = document.createElement("style");
                styleElement.type = "text/css";
                if (styleElement.styleSheet) {
                    styleElement.styleSheet.cssText = cssCode;
                } else {
                    styleElement.appendChild(document.createTextNode(cssCode));
                }
                var head = document.getElementsByTagName("head")[0];
                head.appendChild(styleElement);
                return function() {
                    head.removeChild(styleElement);
                };
            }

            function addStyleFixed(cssCode) {
                if(true) {
                    if(typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment");
                }
                var styleElement = document.createElement("style");
                styleElement.type = "text/css";
                var head = document.getElementsByTagName("head")[0];
                head.appendChild(styleElement);
                if (styleElement.styleSheet) {
                    styleElement.styleSheet.cssText = cssCode;
                } else {
                    styleElement.appendChild(document.createTextNode(cssCode));
                }
                return function() {
                    head.removeChild(styleElement);
                };
            }
        }());
    </script>
</body>
</html>

The page is not hot reloaded after an error.

I use this loader with react-hot-loader and when an error is thrown the page will not hot reload even when the error is fixed.

Example:

  1. Make error in style
  2. Hot Reload and throw error
  3. Fix error in style
  4. Page not reloaded

This can be fixed by adding the remainingRequest argument to module.hot.accept.

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.