webpack loader to extract HTML and CSS from the bundle.
The extract-loader evaluates the given source code on the fly and returns the result as string. Its main use-case is to resolve urls within HTML and CSS coming from their respective loaders. Use the file-loader to emit the extract-loader's result as separate file.
import stylesheetUrl from "file-loader!extract-loader!css-loader!main.css"; // stylesheetUrl will now be the hashed url to the final stylesheetThe extract-loader works similar to the extract-text-webpack-plugin and the mini-css-extract-plugin and is meant as a lean alternative to it. When evaluating the source code, it provides a fake context which was especially designed to cope with the code generated by the html- or the css-loader. Thus it might not work in other situations.
$ npm install extract-loader --save-devBundling CSS with webpack has some nice advantages like referencing images and fonts with hashed urls or hot module replacement in development. In production, on the other hand, it's not a good idea to apply your stylesheets depending on JS execution. Rendering may be delayed or even a FOUC might be visible. Thus it's still better to have them as separate files in your final production build.
With the extract-loader, you are able to reference your main.css as regular entry. The following webpack.config.js shows how to load your styles with the style-loader in development and as separate file in production.
module.exports = ({ mode }) => { const pathToMainCss = require.resolve("./app/main.css"); const loaders = [{ loader: "css-loader", options: { sourceMap: true } }]; if (mode === "production") { loaders.unshift( "file-loader", "extract-loader" ); } else { loaders.unshift("style-loader"); } return { mode, entry: pathToMainCss, module: { rules: [ { test: pathToMainCss, loaders: loaders }, ] } }; };You can even add your index.html as entry and reference your stylesheets from there. In that case, tell the html-loader to also pick up link:href:
module.exports = ({ mode }) => { const pathToMainJs = require.resolve("./app/main.js"); const pathToIndexHtml = require.resolve("./app/index.html"); return { mode, entry: [ pathToMainJs, pathToIndexHtml ], module: { rules: [ { test: pathToIndexHtml, use: [ "file-loader", "extract-loader", { loader: "html-loader", options: { attrs: ["img:src", "link:href"] } } ] }, { test: /\.css$/, use: [ "file-loader", "extract-loader", { loader: "css-loader", options: { sourceMap: true } } ] }, { test: /\.jpg$/, use: "file-loader" } ] } }; }turns
<html> <head> <link href="main.css" type="text/css" rel="stylesheet"> </head> <body> <img src="hi.jpg"> </body> </html>into
<html> <head> <link href="7c57758b88216530ef48069c2a4c685a.css" type="text/css" rel="stylesheet"> </head> <body> <img src="6ac05174ae9b62257ff3aa8be43cf828.jpg"> </body> </html>If you want source maps in your extracted CSS files, you need to set the sourceMap option of the css-loader:
{ loader: "css-loader", options: { sourceMap: true } }There is currently exactly one option: publicPath. If you are using a relative publicPath in webpack's output options and extracting to a file with the file-loader, you might need this to account for the location of your extracted file. publicPath may be defined as a string or a function that accepts current loader context as single argument.
Example with publicPath option as a string:
module.exports = { output: { path: path.resolve("./dist"), publicPath: "dist/" }, module: { rules: [ { test: /\.css$/, use: [ { loader: "file-loader", options: { name: "assets/[name].[ext]", }, }, { loader: "extract-loader", options: { publicPath: "../", } }, { loader: "css-loader", }, ], } ] } };Example with publicPath option as a function:
module.exports = { output: { path: path.resolve("./dist"), publicPath: "dist/" }, module: { rules: [ { test: /\.css$/, use: [ { loader: "file-loader", options: { name: "assets/[name].[ext]", }, }, { loader: "extract-loader", options: { // dynamically return a relative publicPath based on how deep in directory structure the loaded file is in /src/ directory publicPath: (context) => '../'.repeat(path.relative(path.resolve('src'), context.context).split('/').length), } }, { loader: "css-loader", }, ], } ] } };You need another option? Then you should think about:
From opening a bug report to creating a pull request: every contribution is appreciated and welcome. If you're planning to implement a new feature or change the api please create an issue first. This way we can ensure that your precious work is not in vain.
All pull requests should have 100% test coverage (with notable exceptions) and need to pass all tests.
- Call
npm testto run the unit tests - Call
npm run coverageto check the test coverage (using istanbul)
Unlicense
