> ## Documentation Index
> Fetch the complete documentation index at: https://docs.webpack.js.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Loader System Overview

> Understand how webpack loaders transform module source code

## What is a Loader?

Loaders are transformations applied to the source code of a module. They allow you to pre-process files as you `import` or "load" them. Loaders can transform files from different languages (like TypeScript) to JavaScript, or inline images as data URLs.

## How Loaders Work

Loaders are executed from right to left (or bottom to top) in a chain. Each loader in the chain applies transformations to the processed resource. The final loader is expected to return JavaScript.

```javascript theme={null}
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',  // 3. Inject CSS into DOM
          'css-loader',    // 2. Turns CSS into JS
          'sass-loader'    // 1. Turns Sass into CSS
        ]
      }
    ]
  }
};
```

## Basic Loader Structure

A loader is a JavaScript module that exports a function:

```javascript theme={null}
module.exports = function(source) {
  // source is the content of the resource file
  // Transform the source and return it
  return source.replace(/const/g, 'var');
};
```

<Note>
  The `this` context in a loader is provided by webpack and contains useful methods and properties known as the [LoaderContext API](./api).
</Note>

## Loader Execution Phases

Loaders run in two phases:

### 1. Pitching Phase

Loaders are executed from **left to right** (or top to bottom) during the pitching phase. Pitching loaders can short-circuit the loader chain.

### 2. Normal Phase

Loaders are executed from **right to left** (or bottom to top) during the normal phase, processing the actual source code.

```
loader1.pitch → loader2.pitch → loader3.pitch
                                              ↓
loader1 ← loader2 ← loader3 ← resource content
```

See [Pitching Loaders](./pitching) for detailed information.

## Synchronous vs Asynchronous Loaders

### Synchronous Loaders

Return the transformed source directly:

```javascript theme={null}
module.exports = function(source) {
  const transformed = transform(source);
  return transformed;
};
```

### Asynchronous Loaders

Use `this.async()` for async operations:

```javascript theme={null}
module.exports = function(source) {
  const callback = this.async();
  
  someAsyncOperation(source, (err, result) => {
    if (err) return callback(err);
    callback(null, result);
  });
};
```

### Promise-based Loaders

Return a Promise for async operations:

```javascript theme={null}
module.exports = async function(source) {
  const result = await someAsyncOperation(source);
  return result;
};
```

## Raw Loaders

By default, loaders receive the resource file as a UTF-8 string. Set `raw` to `true` to receive raw `Buffer`:

```javascript theme={null}
module.exports = function(source) {
  // source is a Buffer
  assert(Buffer.isBuffer(source));
  return doSomething(source);
};

module.exports.raw = true;
```

<Warning>
  Raw loaders are useful for processing binary files like images, fonts, or other non-text assets.
</Warning>

## Returning Multiple Values

Loaders can return source maps and additional metadata using `this.callback()`:

```javascript theme={null}
module.exports = function(source, sourceMap, meta) {
  // Transform the source
  const result = transform(source);
  
  // Return result with source map
  this.callback(null, result, sourceMap, meta);
};
```

## Common Loader Patterns

### Basic Transformation

```javascript theme={null}
module.exports = function(source) {
  return source.replace(/foo/g, 'bar');
};
```

### With Options

```javascript theme={null}
module.exports = function(source) {
  const options = this.getOptions();
  
  return transform(source, options);
};
```

### With Validation

```javascript theme={null}
const schema = {
  type: 'object',
  properties: {
    test: {
      type: 'boolean'
    }
  }
};

module.exports = function(source) {
  const options = this.getOptions(schema);
  
  return transform(source, options);
};
```

### Emitting Files

```javascript theme={null}
module.exports = function(source) {
  const url = interpolateName(this, '[hash].[ext]', { source });
  
  this.emitFile(url, source);
  
  return `export default ${JSON.stringify(url)}`;
};
```

## Adding Dependencies

Make webpack watch additional files:

```javascript theme={null}
module.exports = function(source) {
  // Watch this file for changes
  this.addDependency('./config.json');
  
  // Watch this directory
  this.addContextDependency('./templates');
  
  return transform(source);
};
```

## Caching

Loaders are cacheable by default. Opt out if your loader has external dependencies:

```javascript theme={null}
module.exports = function(source) {
  // Disable caching
  this.cacheable(false);
  
  const config = fs.readFileSync('./config.json');
  return transform(source, config);
};
```

<Warning>
  Instead of disabling caching, use `this.addDependency()` to add external files as dependencies.
</Warning>

## Error Handling

### Synchronous Errors

```javascript theme={null}
module.exports = function(source) {
  try {
    return transform(source);
  } catch (error) {
    throw error; // or this.callback(error)
  }
};
```

### Asynchronous Errors

```javascript theme={null}
module.exports = function(source) {
  const callback = this.async();
  
  someAsyncOperation(source, (err, result) => {
    if (err) return callback(err);
    callback(null, result);
  });
};
```

### Warnings

```javascript theme={null}
module.exports = function(source) {
  if (deprecated(source)) {
    this.emitWarning(new Error('Deprecated syntax detected'));
  }
  
  return transform(source);
};
```

## Loader Context

Loaders have access to many useful methods via `this`:

* `this.addDependency(file)` - Add a file dependency
* `this.async()` - Make the loader async
* `this.callback()` - Return multiple values
* `this.emitFile(name, content)` - Emit a file
* `this.emitWarning(warning)` - Emit a warning
* `this.emitError(error)` - Emit an error
* `this.getOptions()` - Get loader options
* `this.resolve()` - Resolve a request

See the complete [LoaderContext API](./api) reference.

## Real-World Example: Markdown Loader

```javascript theme={null}
const marked = require('marked');

const schema = {
  type: 'object',
  properties: {
    pedantic: { type: 'boolean' },
    gfm: { type: 'boolean' }
  }
};

module.exports = function(source) {
  const options = this.getOptions(schema);
  
  // Mark this loader as cacheable
  this.cacheable();
  
  // Configure marked
  marked.setOptions(options);
  
  // Transform markdown to HTML
  const html = marked.parse(source);
  
  // Return as JavaScript module
  return `export default ${JSON.stringify(html)}`;
};
```

## Guidelines

### 1. Keep Loaders Simple

Each loader should do one thing well. Chain multiple loaders for complex transformations.

### 2. Use Module Utilities

Leverage webpack's utilities like `this.resolve()` instead of Node.js `require.resolve()`.

### 3. Mark Dependencies

Always use `this.addDependency()` for external files to enable proper watching.

### 4. Resolve Modules Relatively

Use `this.resolve()` to resolve modules relative to the current module.

### 5. Extract Common Code

Extract common code into a runtime module using `this.emitFile()`.

### 6. Avoid Absolute Paths

Generate relative paths or use webpack's utilities to make loaders portable.

### 7. Use Peer Dependencies

If your loader depends on a library, list it as a `peerDependency`.

## Testing Loaders

```javascript theme={null}
const compiler = webpack({
  entry: './test-file.js',
  module: {
    rules: [
      {
        test: /\.txt$/,
        use: {
          loader: path.resolve(__dirname, './my-loader.js'),
          options: {
            /* options */
          }
        }
      }
    ]
  }
});

compiler.run((err, stats) => {
  // Test assertions
});
```

## Next Steps

* [LoaderContext API](./api) - Complete API reference
* [Pitching Loaders](./pitching) - Advanced loader execution
* [Writing a Loader](/api/loaders/api) - Step-by-step tutorial

## Further Reading

* [Official Loader API](https://webpack.js.org/api/loaders/)
* [loader-runner](https://github.com/webpack/loader-runner) - The loader execution engine
