Skip to content

Update Writing plugin and Plugin pattern page #2200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Sep 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 61 additions & 57 deletions src/content/contribute/plugin-patterns.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
---
title: Plugin Patterns
sort: 5
contributors:
- nveenjain
---

Plugins grant unlimited opportunity to perform customizations within the webpack build system. This allows you to create custom asset types, perform unique build modifications, or even enhance the webpack runtime while using middleware. The following are some features of webpack that become useful while writing plugins.
Expand All @@ -10,63 +12,66 @@ Plugins grant unlimited opportunity to perform customizations within the webpack
After a compilation is sealed, all structures within the compilation may be traversed.

```javascript
function MyPlugin() {}

MyPlugin.prototype.apply = function(compiler) {
compiler.plugin('emit', function(compilation, callback) {

// Explore each chunk (build output):
compilation.chunks.forEach(function(chunk) {
// Explore each module within the chunk (built inputs):
chunk.modules.forEach(function(module) {
// Explore each source file path that was included into the module:
module.fileDependencies.forEach(function(filepath) {
// we've learned a lot about the source structure now...
class MyPlugin {
apply(compiler) {
compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => {
// Explore each chunk (build output):
compilation.chunks.forEach(chunk => {
// Explore each module within the chunk (built inputs):
chunk.modules.forEach(module => {
// Explore each source file path that was included into the module:
module.fileDependencies.forEach(filepath => {
// we've learned a lot about the source structure now...
});
});
});

// Explore each asset filename generated by the chunk:
chunk.files.forEach(function(filename) {
// Get the asset source for each file generated by the chunk:
var source = compilation.assets[filename].source();
// Explore each asset filename generated by the chunk:
chunk.files.forEach(filename => {
// Get the asset source for each file generated by the chunk:
var source = compilation.assets[filename].source();
});
});
});

callback();
});
};

callback();
});
}
}
module.exports = MyPlugin;
```

- `compilation.modules`: An array of modules (built inputs) in the compilation. Each module manages the build of a raw file from your source library.
- `module.fileDependencies`: An array of source file paths included into a module. This includes the source JavaScript file itself (ex: `index.js`), and all dependency asset files (stylesheets, images, etc) that it has required. Reviewing dependencies is useful for seeing what source files belong to a module.
- `compilation.chunks`: An array of chunks (build outputs) in the compilation. Each chunk manages the composition of a final rendered assets.
- `chunk.modules`: An array of modules that are included into a chunk. By extension, you may look through each module's dependencies to see what raw source files fed into a chunk.
- `chunk.files`: An array of output filenames generated by the chunk. You may access these asset sources from the `compilation.assets` table.
* `compilation.modules`: An array of modules (built inputs) in the compilation. Each module manages the build of a raw file from your source library.
* `module.fileDependencies`: An array of source file paths included into a module. This includes the source JavaScript file itself (ex: `index.js`), and all dependency asset files (stylesheets, images, etc) that it has required. Reviewing dependencies is useful for seeing what source files belong to a module.
* `compilation.chunks`: An array of chunks (build outputs) in the compilation. Each chunk manages the composition of a final rendered assets.
* `chunk.modules`: An array of modules that are included into a chunk. By extension, you may look through each module's dependencies to see what raw source files fed into a chunk.
* `chunk.files`: An array of output filenames generated by the chunk. You may access these asset sources from the `compilation.assets` table.

### Monitoring the watch graph

While running webpack middleware, each compilation includes a `fileDependencies` array (what files are being watched) and a `fileTimestamps` hash that maps watched file paths to a timestamp. These are extremely useful for detecting what files have changed within the compilation:

```javascript
function MyPlugin() {
this.startTime = Date.now();
this.prevTimestamps = {};
class MyPlugin {
constructor() {
this.startTime = Date.now();
this.prevTimestamps = {};
}
apply(compiler) {
compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => {
var changedFiles = Object.keys(compilation.fileTimestamps).filter(
watchfile => {
return (
(this.prevTimestamps[watchfile] || this.startTime) <
(compilation.fileTimestamps[watchfile] || Infinity)
);
}
);

this.prevTimestamps = compilation.fileTimestamps;
callback();
});
}
}

MyPlugin.prototype.apply = function(compiler) {
compiler.plugin('emit', function(compilation, callback) {

var changedFiles = Object.keys(compilation.fileTimestamps).filter(function(watchfile) {
return (this.prevTimestamps[watchfile] || this.startTime) < (compilation.fileTimestamps[watchfile] || Infinity);
}.bind(this));

this.prevTimestamps = compilation.fileTimestamps;
callback();
}.bind(this));
};

module.exports = MyPlugin;
```

Expand All @@ -77,22 +82,21 @@ You may also feed new file paths into the watch graph to receive compilation tri
Similar to the watch graph, it's fairly simple to monitor changed chunks (or modules, for that matter) within a compilation by tracking their hashes.

```javascript
function MyPlugin() {
this.chunkVersions = {};
class MyPlugin {
constructor() {
this.chunkVersions = {};
}
apply(compiler) {
compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => {
var changedChunks = compilation.chunks.filter(chunk => {
var oldVersion = this.chunkVersions[chunk.name];
this.chunkVersions[chunk.name] = chunk.hash;
return chunk.hash !== oldVersion;
});
callback();
});
}
}

MyPlugin.prototype.apply = function(compiler) {
compiler.plugin('emit', function(compilation, callback) {

var changedChunks = compilation.chunks.filter(function(chunk) {
var oldVersion = this.chunkVersions[chunk.name];
this.chunkVersions[chunk.name] = chunk.hash;
return chunk.hash !== oldVersion;
}.bind(this));

callback();
}.bind(this));
};

module.exports = MyPlugin;
```
Loading