extract-loader

extract-loader

webpack loader to extract HTML and CSS from the bundle.

extract-loader - 图1 extract-loader - 图2 Dependency Status Build Status Coverage Status

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.

  1. import stylesheetUrl from "file-loader!extract-loader!css-loader!main.css";
  2. // stylesheetUrl will now be the hashed url to the final stylesheet

The 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.

Installation

npm install extract-loader

Examples

#

Bundling 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.

  1. module.exports = ({ mode }) => {
  2. const pathToMainCss = require.resolve("./app/main.css");
  3. const loaders = [{
  4. loader: "css-loader",
  5. options: {
  6. sourceMap: true
  7. }
  8. }];
  9. if (mode === "production") {
  10. loaders.unshift(
  11. "file-loader",
  12. "extract-loader"
  13. );
  14. } else {
  15. loaders.unshift("style-loader");
  16. }
  17. return {
  18. mode,
  19. entry: pathToMainCss,
  20. module: {
  21. rules: [
  22. {
  23. test: pathToMainCss,
  24. loaders: loaders
  25. },
  26. ]
  27. }
  28. };
  29. };

Extracting the index.html Extracting the index.html” class=”icon-link” href=”#extracting-the-index-html”>

You can even add your index.html as entry and just reference your stylesheets from there. You just need to tell the html-loader to also pick up link:href:

  1. module.exports = ({ mode }) => {
  2. const pathToMainJs = require.resolve("./app/main.js");
  3. const pathToIndexHtml = require.resolve("./app/index.html");
  4. return {
  5. mode,
  6. entry: [
  7. pathToMainJs,
  8. pathToIndexHtml
  9. ],
  10. module: {
  11. rules: [
  12. {
  13. test: pathToIndexHtml,
  14. use: [
  15. "file-loader",
  16. "extract-loader",
  17. {
  18. loader: "html-loader",
  19. options: {
  20. attrs: ["img:src", "link:href"]
  21. }
  22. }
  23. ]
  24. },
  25. {
  26. test: /\.css$/,
  27. use: [
  28. "file-loader",
  29. "extract-loader",
  30. {
  31. loader: "css-loader",
  32. options: {
  33. sourceMap: true
  34. }
  35. }
  36. ]
  37. },
  38. {
  39. test: /\.jpg$/,
  40. use: "file-loader"
  41. }
  42. ]
  43. }
  44. };
  45. }

turns

  1. <html>
  2. <head>
  3. <link href="main.css" type="text/css" rel="stylesheet">
  4. </head>
  5. <body>
  6. <img src="hi.jpg">
  7. </body>
  8. </html>

into

  1. <html>
  2. <head>
  3. <link href="7c57758b88216530ef48069c2a4c685a.css" type="text/css" rel="stylesheet">
  4. </head>
  5. <body>
  6. <img src="6ac05174ae9b62257ff3aa8be43cf828.jpg">
  7. </body>
  8. </html>

Source Maps

If you want source maps in your extracted CSS files, you need to set the sourceMap option of the css-loader:

  1. {
  2. loader: "css-loader",
  3. options: {
  4. sourceMap: true
  5. }
  6. }

Options

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:

  1. module.exports = {
  2. output: {
  3. path: path.resolve("./dist"),
  4. publicPath: "dist/"
  5. },
  6. module: {
  7. rules: [
  8. {
  9. test: /\.css$/,
  10. use: [
  11. {
  12. loader: "file-loader",
  13. options: {
  14. name: "assets/[name].[ext]",
  15. },
  16. },
  17. {
  18. loader: "extract-loader",
  19. options: {
  20. publicPath: "../",
  21. }
  22. },
  23. {
  24. loader: "css-loader",
  25. },
  26. ],
  27. }
  28. ]
  29. }
  30. };

Example with publicPath option as a function:

  1. module.exports = {
  2. output: {
  3. path: path.resolve("./dist"),
  4. publicPath: "dist/"
  5. },
  6. module: {
  7. rules: [
  8. {
  9. test: /\.css$/,
  10. use: [
  11. {
  12. loader: "file-loader",
  13. options: {
  14. name: "assets/[name].[ext]",
  15. },
  16. },
  17. {
  18. loader: "extract-loader",
  19. options: {
  20. // dynamically return a relative publicPath based on how deep in directory structure the loaded file is in /src/ directory
  21. publicPath: (context) => '../'.repeat(path.relative(path.resolve('src'), context.context).split('/').length),
  22. }
  23. },
  24. {
  25. loader: "css-loader",
  26. },
  27. ],
  28. }
  29. ]
  30. }
  31. };

You need another option? Then you should think about:

Contributing

From opening a bug report to creating a pull request: every contribution is appreciated and welcome. If you’re planing 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 test to run the unit tests
  • Call npm run coverage to check the test coverage (using istanbul)

License

Unlicense

Sponsors

extract-loader - 图6