0
# Webpack Plugins
1
2
Custom webpack plugins designed specifically for JupyterLab extension building, including asset copying, license reporting, duplicate package detection, and watch mode optimizations.
3
4
## Capabilities
5
6
### Frontend Asset Plugin
7
8
Copies build assets from a build directory to a static directory, ensuring clean output on first run.
9
10
```typescript { .api }
11
/**
12
* A WebPack Plugin that copies the assets to the static directory
13
*/
14
class WPPlugin.FrontEndPlugin {
15
constructor(buildDir: string, staticDir: string);
16
apply(compiler: webpack.Compiler): void;
17
18
readonly buildDir: string;
19
readonly staticDir: string;
20
}
21
```
22
23
The `FrontEndPlugin` provides:
24
25
1. **Clean Static Directory**: Removes existing static directory on first emit
26
2. **Asset Copying**: Synchronously copies all assets from build to static directory
27
3. **Incremental Updates**: Only cleans on first run, preserves assets on subsequent builds
28
29
**Usage Example:**
30
31
```typescript
32
import { WPPlugin } from "@jupyterlab/builder";
33
import * as webpack from "webpack";
34
35
const config = {
36
plugins: [
37
new WPPlugin.FrontEndPlugin("./dist", "./static")
38
]
39
};
40
41
const compiler = webpack(config);
42
```
43
44
### JSON License Reporting Plugin
45
46
Creates comprehensive, machine-readable license reports for all bundled modules in SPDX-like format.
47
48
```typescript { .api }
49
/**
50
* A plugin that creates a predictable, machine-readable report of licenses for
51
* all modules included in this build
52
*/
53
class WPPlugin.JSONLicenseWebpackPlugin extends LicenseWebpackPlugin {
54
constructor(pluginOptions?: PluginOptions);
55
renderLicensesJSON(modules: LicenseIdentifiedModule[]): string;
56
}
57
58
const WPPlugin.DEFAULT_LICENSE_REPORT_FILENAME: "third-party-licenses.json";
59
60
interface WPPlugin.ILicenseReport {
61
packages: WPPlugin.IPackageLicenseInfo[];
62
}
63
64
interface WPPlugin.IPackageLicenseInfo {
65
/** the name of the package as it appears in node_modules */
66
name: string;
67
/** the version of the package, or an empty string if unknown */
68
versionInfo: string;
69
/** an SPDX license or LicenseRef, or an empty string if unknown */
70
licenseId: string;
71
/** the verbatim extracted text of the license, or an empty string if unknown */
72
extractedText: string;
73
}
74
```
75
76
The license plugin:
77
78
1. **Comprehensive Reporting**: Captures all bundled modules with license information
79
2. **SPDX-Compatible**: Uses SPDX-like format for license identification
80
3. **Predictable Output**: Always outputs to `third-party-licenses.json`
81
4. **Sorted Results**: Alphabetically sorts packages by name for consistency
82
83
**Usage Example:**
84
85
```typescript
86
import { WPPlugin } from "@jupyterlab/builder";
87
88
const config = {
89
plugins: [
90
new WPPlugin.JSONLicenseWebpackPlugin({
91
excludedPackageTest: packageName => packageName === "my-package"
92
})
93
]
94
};
95
```
96
97
### Watch Mode File Filtering Plugin
98
99
Ignores specific files during webpack watch mode based on a filter function, optimizing build performance.
100
101
```typescript { .api }
102
/**
103
* A WebPack Plugin that ignores files that are filtered
104
* by a callback during a `--watch` build
105
*/
106
class WPPlugin.FilterWatchIgnorePlugin {
107
constructor(ignored: (path: string) => boolean);
108
apply(compiler: webpack.Compiler): void;
109
110
readonly ignored: (path: string) => boolean;
111
}
112
```
113
114
The filter plugin provides:
115
116
1. **Custom Filtering**: Uses callback function to determine ignored files
117
2. **Watch Optimization**: Only affects watch mode, not regular builds
118
3. **Path-Based Logic**: Receives full file paths for filtering decisions
119
120
**Usage Example:**
121
122
```typescript
123
import { WPPlugin } from "@jupyterlab/builder";
124
125
const config = {
126
plugins: [
127
new WPPlugin.FilterWatchIgnorePlugin(
128
path => path.includes("node_modules") || path.endsWith(".test.js")
129
)
130
]
131
};
132
```
133
134
### Duplicate Package Checker Plugin
135
136
Extended version of the duplicate package checker plugin that only runs during non-watch builds to avoid performance issues.
137
138
```typescript { .api }
139
/**
140
* Extended duplicate package checker that only runs in non-watch mode
141
*/
142
class WPPlugin.NowatchDuplicatePackageCheckerPlugin extends DuplicatePackageCheckerPlugin {
143
constructor(options: DuplicatePackageCheckerPlugin.Options);
144
apply(compiler: webpack.Compiler): void;
145
options: DuplicatePackageCheckerPlugin.Options;
146
}
147
```
148
149
This plugin addresses performance concerns by:
150
151
1. **Watch Mode Skipping**: Only runs during regular builds, not watch mode
152
2. **Duplicate Detection**: Identifies packages with multiple versions in the bundle
153
3. **Build-Time Optimization**: Prevents watch mode slowdowns from duplicate checking
154
155
**Usage Example:**
156
157
```typescript
158
import { WPPlugin } from "@jupyterlab/builder";
159
160
const config = {
161
plugins: [
162
new WPPlugin.NowatchDuplicatePackageCheckerPlugin({
163
verbose: true,
164
emitError: false,
165
showHelp: true
166
})
167
]
168
};
169
```
170
171
## Plugin Integration Patterns
172
173
### Production Build Configuration
174
175
For production builds, combine plugins for optimal output:
176
177
```typescript
178
import { WPPlugin } from "@jupyterlab/builder";
179
180
const productionPlugins = [
181
new WPPlugin.FrontEndPlugin("./build", "./static"),
182
new WPPlugin.JSONLicenseWebpackPlugin({
183
excludedPackageTest: packageName => packageName === myPackageName
184
}),
185
new WPPlugin.NowatchDuplicatePackageCheckerPlugin({
186
emitError: true,
187
strict: true
188
})
189
];
190
```
191
192
### Development Build Configuration
193
194
For development builds, focus on performance:
195
196
```typescript
197
import { WPPlugin } from "@jupyterlab/builder";
198
199
const developmentPlugins = [
200
new WPPlugin.FrontEndPlugin("./build", "./static"),
201
new WPPlugin.FilterWatchIgnorePlugin(
202
path => path.includes("node_modules") && !path.includes("@jupyterlab")
203
)
204
];
205
```
206
207
## License Report Format
208
209
The JSON license plugin generates reports in this structure:
210
211
```json
212
{
213
"packages": [
214
{
215
"name": "@jupyterlab/application",
216
"versionInfo": "4.4.7",
217
"licenseId": "BSD-3-Clause",
218
"extractedText": "Copyright (c) 2015-2022, Jupyter Development Team..."
219
}
220
]
221
}
222
```
223
224
This format is consumed by `jupyterlab_server` for license compliance and can be processed by other tools in the JupyterLab ecosystem.