Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rule.issuer in Webpack. What properties belong to it?

Webpack's Rule option presents two things (in a full, not shortcut syntax): resource and issuer.

In a Rule the properties test, include, exclude and resource are matched with the resource and the property issuer is matched with the issuer.

So, it is somewhat clear what properties are related to a resource:

{
    resource: {
        test: ...,
        include: ...,
        exclude: ...,
    },
    issuer: { ...boom?? }
}

But what properties are matched with the issuer? There is just nothing for issuer in their docs:

A Condition matched with the issuer. See details in Rule conditions.

And details do not explain issuer.

Why? They have created an option, but haven't decided on its properties yet?

like image 796
Green Avatar asked Sep 19 '25 20:09

Green


1 Answers

They have created an option, but haven't decided on its properties yet?

The value of issuer is a Condition. The most common Condition is an object with test, include and/or exclude properties, which you have used for the resource. Everything you can use for resource, you can also use for issuer.

In fact, Rule.resource expects itself a Condition, excerpt from the docs:

Rule.resource

A Condition matched with the resource. You can either supply a Rule.resource option or use the shortcut options Rule.test, Rule.exclude, and Rule.include.

The only difference to the issuer is that there are shortcuts (Rule.test, Rule.exclude and Rule.include), because that's the majority of the use-cases. It roughly translates to:

resource: {
  test: Rule.test,
  exclude: Rule.exclude,
  include: Rule.include,
}

And details do not explain issuer.

Clicking on See details in Rule conditions leads to a description, which even contains an example. Excerpt:

Rule Conditions

There are two input values for the conditions:

  1. The resource: An absolute path to the file requested. It's already resolved according to the resolve rules.

  2. The issuer: An absolute path to the file of the module which requested the resource. It's the location of the import.

Example: When we import "./style.css" from app.js, the resource is /path/to/style.css and the issuer is /path/to/app.js.

That is definitely an explanation, but maybe it isn't good enough, so I'll explain it in more details.

To illustrate the purpose of issuer I will use a contrived example, which could potentially be a use-case for it. Let's assume that you have some JavaScript code, which you would like to show to the user (the actual code) and at the same time you want to run that code in another part of the application. The code in question will be a simple greeting function.

greeter.js

export default function greet(name) {
  console.log(`Hello ${name}!`);
}

If we want to show the source of greeter.js, we could read it from the file system, but because we'd like to run it in the browser, this is not an option. As we are using webpack, we can use the raw-loader to import the greeter.js file as a string instead of JavaScript. Assuming we have configured it, we can create a module that prints the source code.

printer.js

import greetSource from "./greeter";

export default function printSource() {
  console.log(greetSource);
}

In our entry point we want to use the greeter and the printer at the same time.

index.js

import greet from "./greeter";
import printSource from "./printer";

greet("World");

printSource();

Now we have a problem, because we've configured raw-loader for greeter.js, therefore greet will be a string, not a function and that will cause a runtime error. What we want is to import greeter.js in index.js as a regular JavaScript file, but we want to import it as a string in printer.js. We could use an inline loader definition, but that would be rather tedious.

This is where issuer comes in. Whichever JavaScript file is imported from printer.js should be passed through the raw-loader, and from any other file we'd like to use babel-loader.

We will define two webpack rules. Both rules target only JavaScript files, so we test for the .js file ending, for every file that is imported, this it the resource. We would like to know which file imported it (where the import statement was), this is the issuer.

printer.js

// Resource: greeter.js, Issuer: printer.js
import greetSource from "./greeter";

index.js

// Resource: greeter.js, Issuer: index.js
import greet from "./greeter";

For the rules, it means that we want to exclude printer.js as an issuer from the babel-loader rule, and include only printer.js for the raw-loader rule.

module: {
  rules: [
    {
      loader: "babel-loader",
      resource: {
        test: /\.js$/
      },
      issuer: {
        exclude: /printer\.js$/
      }
    },
    {
      loader: "raw-loader",
      resource: {
        test: /\.js$/
      },
      issuer: {
        include: /printer\.js$/
      }
    }
  ]
}

Note: It's not necessary to include the resource option for the raw-loader rule and if you leave it out, it would apply the raw-loader to everything that is being imported in printer.js, which may or may not be what you want (think of including CSS to style the output)

Bundling and running the above code will produce the following output:

Hello World!
export default function greet(name) {
  console.log(`Hello ${name}!`);
}
like image 148
Michael Jungo Avatar answered Sep 22 '25 08:09

Michael Jungo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!