Introduction
A loader is a node module exported as a function. This function is called when transforming resources in the loader. The given function will utilize the Loader API
and can be accessed through the this
context.
Here is an official link on loader usage and examples, including local development and testing of custom loaders.
Simple Usage of Webpack Loader
When a loader is used in a resource, it can only take one parameter - a string containing the content of the resource file.
Synchronous loaders can return a single value representing the transformed module.
Loaders can return one or two values. The first value is a string or buffer containing JavaScript code. The optional second value is a SourceMap, which is a JavaScript object.
Here’s a simple example of using a loader. It matches all JavaScript files and processes them using loader.js
:
// webpack.config.js
const path = require('path');
module.exports = {
//...
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: path.resolve('path/to/loader.js'),
options: {
/* ... */
},
},
],
},
],
},
};
From the above, we can understand how loaders are used. But this only scratches the surface. What does a specific loader look like?
For example, a simple loader could be like this:
module.exports = function (content) {
// content is the source content string passed in
return content
}
A loader is just a node module exposing a function that can only receive one parameter: a string containing the content of the resource file. The function’s return value is the processed content.
Creating a Custom Webpack Loader
Guidelines for Using Custom Loaders
When writing loaders, you should follow these guidelines. They are listed in order of importance, and some apply only to specific scenarios. Please read the detailed sections below for more information.
- Keep it simple.
- Use chaining.
- Output should be modular.
- Ensure it’s stateless.
- Use loader utilities.
- Record loader dependencies.
- Resolve module dependencies.
- Extract common code.
- Avoid absolute paths.
- Use peer dependencies.
Step 1: Create Project Directory and Files
First, create the following files in a folder within your webpack project directory:
src/loader/custom-loader.js
: The source file for your custom loader.src/index.js
: JavaScript entry file for testing the custom loader.
Step 2: Write the Custom Loader
In the custom-loader.js
file, write your custom loader code. This loader adds a comment at the top of each loaded JavaScript file.
// src/loader/custom-loader.js
module.exports = function(source) {
// Add a custom comment at the top of the source code
const updatedSource = `/** Custom Comment added by Custom Loader */\n${source}`;
return updatedSource;
};
Step 3: Configure Webpack
Create a Webpack configuration file webpack.config.js
in the project root directory. Use the custom loader you just created in the configuration file.
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.js$/,
use: ['custom-loader'], // Use the custom loader to process .js files
exclude: /node_modules/,
},
],
},
};
This configuration achieves a simple functionality. Now let’s discuss how to test the local loader. There are two ways to do this: one is through Npm link
for testing, a convenient method where you can create a symbolic link for local testing. Here is a link to npm-link. Another way is to configure the path directly in the project:
Single Loader Configuration
// webpack.config.js
{
test: /\.js$/
use: [
{
loader: path.resolve('path/to/custom-loader.js'),
options: {/* ... */}
}
]
}
Multiple Loader Configuration
You can also configure it using an array:
// webpack.config.js
resolveLoader: {
// Look for loaders first in the node_modules directory; if not found, search in the loaders directory
modules: [
'node_modules',
path.resolve(__dirname, 'custom-loader')
]
}
Step 4: Test the Custom Loader
In the index.js
file, write some JavaScript code, for example:
// src/index.js
console.log('Hello, Webpack Loader!');
Step 5: Run Webpack Build
Run the following command to build your project:
npx webpack --config webpack.config.js
After the build is complete, you will find the generated bundle.js
file in the dist
folder. In this file, you can see JavaScript code with a custom comment added at the top.
## Simple Usage of Webpack Plugin
Plugins provide complete control over the webpack engine for third-party developers. By introducing custom behaviors into the webpack build process through stage-based build callbacks, developers can customize webpack's behavior.
Here's the simplest example:
```javascript
// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: __dirname + '/dist',
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html', // Specify the HTML template file
filename: 'index.html', // Generated HTML file name
}),
// You can add more plugins here
],
};
In this example, the HtmlWebpackPlugin
is used. It generates a new HTML file based on the specified HTML template and automatically adds the bundled JavaScript file to the generated HTML file.
A basic webpack plugin consists of the following components:
A JavaScript named function or JavaScript class.
Define an
apply
method on the plugin function’s prototype. Theapply
method is called when webpack loads the plugin and is passed thecompiler
object.Specify an event hook bound to webpack itself.
Process specific data from webpack’s internal instances.
Call the callback provided by webpack after the functionality is completed.
A plugin structure looks like this:
class HelloWorldPlugin {
apply(compiler) {
compiler.hooks.done.tap(
'Hello World Plugin',
(
stats /* After binding the done hook, stats is passed as a parameter. */
) => {
console.log('Hello World!');
}
);
}
}
module.exports = HelloWorldPlugin;
Compiler and Compilation
The two most important resources in plugin development are the compiler
and compilation
objects. Plugin development revolves around hooks on these objects.
The compiler
object is essentially bound to the entire webpack environment. It contains all the environment configurations, including options, loaders, and plugins. When webpack starts, this object is instantiated and it is globally unique
. The parameters passed into the apply
method are properties of this object.
The compilation
object is created each time resources are built. It represents the current module resources, compiled generated resources, changed files, and tracked dependency status. It also provides many hooks.
Creating a Custom Webpack Plugin
Step 1: Create Project Directory and Files
First, create the following file in a folder within your webpack project directory:
src/plugins/CustomPlugin.js
: Source file for your custom plugin.
Step 2: Write the Custom Plugin
In the CustomPlugin.js
file, write a plugin that outputs a message when the webpack build process is completed.
// src/plugins/CustomPlugin.js
class CustomPlugin {
apply(compiler) {
compiler.hooks.done.tap('CustomPlugin', () => {
console.log('CustomPlugin: Webpack build process is done!');
});
}
}
module.exports = CustomPlugin;
Step 3: Configure Webpack
In the configuration file, use the custom plugin you just created.
// webpack.config.js
const CustomPlugin = require('./src/plugins/CustomPlugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: __dirname + '/dist',
},
plugins: [
new CustomPlugin(),
// You can add more plugins here
],
};
Step 4: Run Webpack Build
Now, run the webpack build:
npx webpack --config webpack.config.js
Note: This article is a translated version of the original post. For the most accurate and up-to-date information, please refer to the original source.
```