@atlassian/webresource-webpack-plugin 7.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,801 @@
1
+ > **_NOTE:_** [@atlassian/webresource-webpack-plugin](https://www.npmjs.com/package/@atlassian/webresource-webpack-plugin) replaces the old [atlassian-webpack-webresource-plugin](https://www.npmjs.com/package/atlassian-webresource-webpack-plugin) package, which is now deprecated.
2
+
3
+ # Atlassian Web-Resource webpack Plugin
4
+
5
+ ![node](https://img.shields.io/badge/node-18%2B-blue.svg)
6
+ ![npm](https://img.shields.io/badge/npm-6.14%2B-blue.svg)
7
+ ![webpack](https://img.shields.io/badge/webpack-5%2B-blue.svg)
8
+
9
+ Auto-generates web-resource definitions from your webpacked code, for usage
10
+ in an Atlassian product or plugin.
11
+
12
+ ## Why?
13
+
14
+ [Atlassian's P2 plugin system][atlassian-p2] was shipped in 2008. At the time, the dependency management
15
+ system in P2 -- [the Web Resource Manager, or WRM][atlassian-wrm] -- was a godsend for managing the growing
16
+ complexity of the front-end resources. It offered, amongst other things:
17
+
18
+ - The ability to specify bundles of related resources, called a "web-resource".
19
+ - The ability to specify inter-dependencies of web-resources, so that
20
+ - Batching of necessary code in production could be achieved, and
21
+ - Source order could be maintained.
22
+
23
+ Fast-forward to 2017, and front-end development is drastically different from it was back then.
24
+ JavaScript module systems and webpack have solved many of the problems the WRM initially set
25
+ out to.
26
+
27
+ Unfortunately, Atlassian's plugin system doesn't speak webpack. Happily, though, we can teach
28
+ webpack to speak Atlassian-Plugin. That's what this plugin does.
29
+
30
+ ## What does it do?
31
+
32
+ When you add this plugin to your webpack configuration, it will generate an XML file
33
+ with the various WRM configuration necessary to make your code run in an Atlassian product.
34
+
35
+ You will be able to write your plugin's front-end code using any JavaScript module system.
36
+ This plugin will figure out how to turn all of it in to the correct `<web-resource>` declarations,
37
+ along with the appropriate `<dependency>` declarations so that your code ends up loading
38
+ in the right order at a product's runtime.
39
+
40
+ This plugin supports and generates correct WRM output for the following webpack behaviours:
41
+
42
+ - a `<web-resource>` per webpack entry point
43
+ - correct `<web-resource>`s for code-splitting / loading asynchronous chunks
44
+ - loading of non-JavaScript resources (via `ExtractTextPlugin` and friends).
45
+
46
+ ## How to use the plugin
47
+
48
+ ### Basic setup
49
+
50
+ Add this plugin to your webpack config. For every entry point webpack generates,
51
+ an appropriate `<web-resource>` definition will be generated in an XML file for you,
52
+ which can then be bundled in to your Atlassian product or plugin, ready to be served
53
+ to the browser at product runtime.
54
+
55
+ Given this webpack config:
56
+
57
+ ```js
58
+ const WrmPlugin = require('@atlassian/webresource-webpack-plugin');
59
+
60
+ module.exports = {
61
+ entry: {
62
+ 'my-feature': path.join(FRONTEND_SRC_DIR, 'simple.js'),
63
+ },
64
+ plugins: [
65
+ new WrmPlugin({
66
+ pluginKey: 'my.full.plugin.artifact-id',
67
+ contextMap: {
68
+ 'my-feature': ['atl.general'],
69
+ },
70
+ xmlDescriptors: path.resolve(OUTPUT_DIR, 'META-INF', 'plugin-descriptors', 'wr-defs.xml'),
71
+ }),
72
+ ],
73
+ output: {
74
+ filename: 'bundled.[name].js',
75
+ path: path.resolve(OUTPUT_DIR),
76
+ },
77
+ };
78
+ ```
79
+
80
+ The output will go to `<OUTPUT_DIR>/META-INF/plugin-descriptors/wr-defs.xml`, and look something like this:
81
+
82
+ ```xml
83
+ <bundles>
84
+
85
+ <web-resource key="entrypoint-my-feature">
86
+ <transformation extension="js">
87
+ <transformer key="jsI18n"/>
88
+ </transformation>
89
+ <context>atl.general</context>
90
+ <resource name="bundled.my-feature.js" type="download" location="bundled.my-feature.js" />
91
+ </web-resource>
92
+
93
+ </bundles>
94
+ ```
95
+
96
+ Also, `<OUTPUT_DIR>/META-INF/fe-manifest-associations/` will include list of resources created by this webpack build
97
+ and NPM package name for AMPs resource association feature.
98
+
99
+ Package name can be specified by passing `packageName` field to WrmPlugin directly, otherwise it is taken
100
+ automatically from the closest parent package.json of Webpack `context` directory.
101
+
102
+ Association is automatically detected by AMPs in P2 plugins and is expected to be in
103
+ `target/classes/META-INF/fe-manifest-associations` of plugin build.
104
+
105
+ #### Consuming the output in your P2 plugin
106
+
107
+ In your P2 plugin project's `pom.xml` file, add the
108
+ `META-INF/plugin-descriptors` directory as a value to an `<Atlassian-Scan-Folders>` tag
109
+ in the `<instruction>` section of the AMPS plugin's build configuration.
110
+
111
+ ```xml
112
+ <build>
113
+ <plugins>
114
+ <plugin>
115
+ <!-- START of a bunch of stuff that is probably different for your plugin, but is outside
116
+ the scope of this demonstration -->
117
+ <groupId>com.atlassian.maven.plugins</groupId>
118
+ <artifactId>maven-amps-plugin</artifactId>
119
+ <version>6.2.11</version>
120
+ <!-- END differences with your plugin -->
121
+ <configuration>
122
+ <instructions>
123
+ <Atlassian-Scan-Folders>META-INF/plugin-descriptors</Atlassian-Scan-Folders>
124
+ </instructions>
125
+ </configuration>
126
+ </plugin>
127
+ </plugins>
128
+ </build>
129
+ ```
130
+
131
+ ### Demonstration P2 plugin usage
132
+
133
+ You can see a demonstration P2 plugin using the webpack plugin here: [sao4fed-bundle-the-ui][101]
134
+
135
+ - Watch this AtlasCamp 2018 talk which uses this plugin amongst others to make your devloop super fast: https://youtu.be/VamdjcJCc0Y
136
+ - Watch this AtlasCamp 2017 talk about how to build and integrate your own front-end devtooling on top of P2, which introduced the alpha version of this plugin: https://youtu.be/2yf-TzKerVQ?t=537
137
+
138
+ ## Features
139
+
140
+ ### Code splitting
141
+
142
+ If you write your code using any of webpack's code-splitting techniques, such as calling `require.ensure`,
143
+ this plugin will automatically generate `<web-resource>` definitions for them, and
144
+ automatically translate them in to the appropriate calls to load them asynchronously at an Atlassian
145
+ product's runtime.
146
+
147
+ In other words, there's practically no effort on your part to make your critical path small :)
148
+
149
+ ### Flexible generation of `web-resource` definitions
150
+
151
+ By default, a generated web-resource will have:
152
+
153
+ - A key based on the name of your webpack entry-point, and
154
+ - Will be included in a `<context>` named after your entry-point.
155
+
156
+ For example, an entry point named "my-feature" will yield a web-resource like this:
157
+
158
+ ```xml
159
+ <web-resource key="entrypoint-my-feature">
160
+ <context>my-feature</context>
161
+ <!-- the resources for your entry-point -->
162
+ </web-resource>
163
+ ```
164
+
165
+ For new code, this should be enough to get your feature loading in to a place you want it to in your
166
+ plugin or product -- assuming the appropriate call on the server-side is made to include your web-resource.
167
+
168
+ Sometimes, in order to ensure your code loads when it's expected to, you will need to override
169
+ the values generated for you. To do this, when defining the `WrmPlugin`'s config, you can provide either:
170
+
171
+ - A `webresourceKeyMap` to change the web-resource's key or name to whatever you need it to be, or
172
+ - A `contextMap` to include the web-resource in any number of web-resource contexts you expect it to load in to.
173
+
174
+ It's most likely that you'll want to specify additional contexts for a web-resource to load in to. When
175
+ all of your web-resources are automatically generated and loaded via contexts, there is no need to know its key. You
176
+ would typically provide your own web-resource key when refactoring old code to webpack, in order to keep
177
+ the dependencies working in any pre-existing code.
178
+
179
+ ### Module-mapping to `web-resource`s
180
+
181
+ If you use a common library or module -- for example, 'jquery' or 'backbone' -- and you know
182
+ that this module is provided by a P2 plugin in the product's runtime, you can map your usage
183
+ of the module to the `web-resource` that provides it.
184
+
185
+ All you need to do is declare the appropriate webpack `external` for your module, and add an entry
186
+ for the external in the `providedDependencies` configuration of this plugin. When your code is
187
+ compiled, this plugin will automatically add an appropriate `web-resource` dependency that
188
+ will guarantee your code loads after its dependants, and will prevent your bundle from getting too large.
189
+
190
+ For details, check the `providedDependencies` section in the configuration section.
191
+
192
+ ### Legacy `web-resource` inclusion
193
+
194
+ 90% of the time, your JavaScript code should be declaring explicit dependencies on other modules.
195
+ In the remaining 10% of cases, you may need to lean on the WRM at runtime to ensure your code loads in
196
+ the right order. 9% of the time, the module-mapping feature should be enough for you. In the remaining
197
+ 1%, you may just need to add a `web-resource` dependency to force the ordering.
198
+
199
+ You can add import statements to your code that will add a `<dependency>` to your generated web-resource.
200
+
201
+ To include `web-resource`s from exported by _this_ plugin you can use short notation like:
202
+
203
+ ```js
204
+ // in AMD syntax
205
+ define(function (require) {
206
+ require('wr-dependency!my-webresource');
207
+ console.log('my-webresource will have been loaded synchronously with the page');
208
+ });
209
+
210
+ // in ES6
211
+ import 'wr-dependency!my-webresource';
212
+
213
+ console.log('my-webresource will have been loaded synchronously with the page');
214
+ ```
215
+
216
+ To include resources exported by _other_ plugins, provide full plugin key:
217
+
218
+ ```js
219
+ // in AMD syntax
220
+ define(function (require) {
221
+ require('wr-dependency!com.atlassian.auiplugin:dialog2');
222
+ console.log('webresource will have been loaded synchronously with the page');
223
+ });
224
+
225
+ // in ES6 syntax
226
+ import 'wr-dependency!com.atlassian.auiplugin:dialog2';
227
+
228
+ console.log('webresource will have been loaded synchronously with the page');
229
+ ```
230
+
231
+ ### Legacy runtime `resource` inclusion
232
+
233
+ 95% of the time, your application's non-JavaScript resources -- CSS, images, templates, etc. --
234
+ are possible to bundle and include via webpack loaders. Sometimes, though, you will have
235
+ resources that only work during an Atlassian product's runtime -- think things like
236
+ Atlassian Soy templates and a product's Less files for look-and-feel styles -- and
237
+ it isn't possible to make them work during ahead-of-time compilation.
238
+
239
+ In these cases, you can add import statements to your code that will add a `<resource>` to your
240
+ generated web-resource:
241
+
242
+ ```js
243
+ // in AMD syntax
244
+ define(function (require) {
245
+ require('wr-resource!my-runtime-styles.css!path/to/the/styles.less');
246
+ require('wr-resource!my-compiled-templates.js!path/to/the/templates.soy');
247
+
248
+ console.log('these styles and templates will be transformed to CSS and JS at product runtime.');
249
+ });
250
+
251
+ // in ES6 syntax
252
+ import 'wr-resource!my-runtime-styles.css!path/to/the/styles.less';
253
+ import 'wr-resource!my-compiled-templates.js!path/to/the/templates.soy';
254
+
255
+ console.log('these styles and templates will be transformed to CSS and JS at product runtime.');
256
+ ```
257
+
258
+ ## Configuring the plugin
259
+
260
+ The Atlassian Web-Resource webpack Plugin has a number of configuration options.
261
+
262
+ ### `pluginKey` (Required)
263
+
264
+ The fully-qualified groupId and artifactId of your P2 plugin. Due to the way the WRM works, this
265
+ value is necessary to provide in order to support loading of asynchronous chunks, as well as arbitrary
266
+ (non-JavaScript) resources.
267
+
268
+ ### `xmlDescriptors` (Required)
269
+
270
+ An absolute filepath to where the generated XML should be output to. This should point to a sub-directory
271
+ of the Maven project's `${project.build.outputDirectory}` (which evaluates to `target/classes` in a
272
+ standard Maven project).
273
+
274
+ The sub-directory part of this configuration value needs to be configured in the project's `pom.xml`, as
275
+ demonstrated in the basic usage section above.
276
+
277
+ ### `addEntrypointNameAsContext` (Optional)
278
+
279
+ Default is `false`.
280
+
281
+ When set to `true`, all generated web-resources will be added to
282
+ a context with the same name as the entrypoint.
283
+
284
+ ### `addAsyncNameAsContext` (Optional)
285
+
286
+ Default is `false`.
287
+
288
+ When set to `true`, all generated web-resources for async chunks that have a name (specified via `webpackChunkName` on import) will be added to
289
+ a context of the name "async-chunk-<name as specified in webpackChunkName>".
290
+
291
+ ### `contextMap` (Optional)
292
+
293
+ A set of key-value pairs that allows you to specify which webpack entry-points
294
+ should be present in what web-resource contexts at an Atlassian product runtime.
295
+
296
+ You can provide either a single web-resource context as a string, or an array of context strings.
297
+
298
+ ### `conditionMap` (Optional)
299
+
300
+ An object specifying what conditions should be applied to a certain entry-point.
301
+ Simple example:
302
+
303
+ ```json
304
+ conditionMap: {
305
+ "my-first-entry-point": {
306
+ "class": "foo.bar"
307
+ },
308
+ }
309
+ ```
310
+
311
+ will yield:
312
+
313
+ ```xml
314
+ <condition class="foo.bar" />
315
+ ```
316
+
317
+ Complex nested example with params:
318
+
319
+ ```json
320
+ conditionMap: {
321
+ "my-first-entry-point": {
322
+ "type": "AND",
323
+ "conditions": [
324
+ {
325
+ "type": "OR",
326
+ "conditions": [
327
+ {
328
+ "class": "foo.bar.baz",
329
+ "invert": true,
330
+ "params": [
331
+ {
332
+ "attributes": {
333
+ "name": "permission"
334
+ },
335
+ "value": "admin"
336
+ }
337
+ ]
338
+ },
339
+ {
340
+ "class": "foo.bar.baz2",
341
+ "params": [
342
+ {
343
+ "attributes": {
344
+ "name": "permission"
345
+ },
346
+ "value": "project"
347
+ }
348
+ ]
349
+ }
350
+ ]
351
+ },
352
+ {
353
+ "class": "foo.bar.baz3",
354
+ "params": [
355
+ {
356
+ "attributes": {
357
+ "name": "permission"
358
+ },
359
+ "value": "admin"
360
+ }
361
+ ]
362
+ }
363
+ ]
364
+ }
365
+ }
366
+ ```
367
+
368
+ will yield:
369
+
370
+ ```xml
371
+ <conditions type="AND">
372
+ <conditions type="OR">
373
+ <condition class="foo.bar.baz" invert="true">
374
+ <param name="permission">admin</param>
375
+ </condition>
376
+ <condition class="foo.bar.baz2" >
377
+ <param name="permission">project</param>
378
+ </condition>
379
+ </conditions>
380
+ <condition class="foo.bar.baz3" >
381
+ <param name="permission">admin</param>
382
+ </condition>
383
+ </conditions>
384
+ ```
385
+
386
+ ### `dataProvidersMap` (Optional)
387
+
388
+ The `dataProvidersMap` option allows configuring the association between entrypoint and a list of data providers.
389
+
390
+ Data providers can be used to provide a data from the server-side to the frontend, and claimed using `WRM.data.claim` API. To read more about data providers refer to [the official documentation](https://developer.atlassian.com/server/framework/atlassian-sdk/adding-data-providers-to-your-plugin/).
391
+
392
+ To associate the entrypoint with list of data providers you can configure the webpack configuration as follow:
393
+
394
+ ```js
395
+ module.exports = {
396
+ entrypoints: {
397
+ 'my-first-entry-point': './first-entry-point.js',
398
+ 'my-second-entry-point': './first-entry-point.js',
399
+ },
400
+
401
+ plugins: [
402
+ WrmPlugin({
403
+ pluginKey: 'my.full.plugin.artifact-id',
404
+ dataProvidersMap: {
405
+ 'my-first-entry-point': [
406
+ {
407
+ key: 'my-foo-data-provider',
408
+ class: 'com.example.myplugin.FooDataProvider',
409
+ },
410
+ ],
411
+
412
+ 'my-second-entry-point': [
413
+ {
414
+ key: 'my-bar-data-provider',
415
+ class: 'com.example.myplugin.BarDataProvider',
416
+ },
417
+
418
+ {
419
+ key: 'my-bizbaz-data-provider',
420
+ class: 'com.example.myplugin.BizBazDataProvider',
421
+ },
422
+ ],
423
+ },
424
+ }),
425
+ ],
426
+ };
427
+ ```
428
+
429
+ will yield:
430
+
431
+ ```xml
432
+ <atlassian-plugin>
433
+ <web-resource key="<<key-of-my-first-entry-point>>">
434
+ <resource />
435
+ <resource />
436
+
437
+ <data key="my-foo-data-provider" class="com.example.myplugin.FooDataProvider" />
438
+ </web-resource>
439
+
440
+ <web-resource key="<<key-of-my-first-entry-point>>">
441
+ <resource />
442
+ <resource />
443
+
444
+ <data key="my-bar-data-provider" class="com.example.myplugin.BarDataProvider" />
445
+ <data key="my-bizbaz-data-provider" class="com.example.myplugin.BizBazDataProvider" />
446
+ </web-resource>
447
+ </atlassian-plugin>
448
+ ```
449
+
450
+ ### `deprecatedEntrypoints` (Optional)
451
+
452
+ An object specifying which entry-points should be marked as being deprecated.
453
+
454
+ A `true` value may be used instead to simply mark an entry-point as being deprecated without providing any additional information.
455
+
456
+ Otherwise an object may be used to provide additional context as to when and why the entry-point was deprecated. For the `alternative` key,
457
+ the value should either be in the format of `plugin-key:web-resource`, or be a reference to another entry-point in the same plugin.
458
+
459
+ ```js
460
+ module.exports = {
461
+ entrypoints: {
462
+ 'my-first-entry-point': './first-entry-point.js',
463
+ 'my-second-entry-point': './second-entry-point.js',
464
+ 'my-third-entry-point': './third-entry-point.js',
465
+ },
466
+
467
+ plugins: [
468
+ WrmPlugin({
469
+ pluginKey: 'my.full.plugin.artifact-id',
470
+ deprecatedEntrypoints: {
471
+ 'my-first-entry-point': true,
472
+ 'my-second-entry-point': {
473
+ sinceVersion: '3.0',
474
+ removeInVersion: '4.0',
475
+ // alternative could also reference another entrypoint i.e. 'my-third-entry-point'
476
+ alternative: 'some.other.plugin:replacement-resource',
477
+ extraInfo: 'We moved all functionality to some.other.plugin',
478
+ },
479
+ },
480
+ }),
481
+ ],
482
+ };
483
+ ```
484
+
485
+ will yield:
486
+
487
+ ```xml
488
+ <atlassian-plugin>
489
+ <web-resource key="entrypoint-my-first-entry-point">
490
+ <!-- ... rest of definition ... -->
491
+ <deprecated />
492
+ </web-resource>
493
+ <web-resource key="entrypoint-my-second-entry-point">
494
+ <!-- ... rest of definition ... -->
495
+ <deprecated since="3.0"
496
+ remove="4.0"
497
+ alternative="some.other.plugin:replacement-resource"
498
+ >
499
+ We moved all functionality to some.other.plugin
500
+ </deprecated>
501
+ </web-resource>
502
+ </atlassian-plugin>
503
+ ```
504
+
505
+ ### `transformationMap` (Optional)
506
+
507
+ An object specifying transformations to be applied to file types.
508
+ The default transformations are:
509
+
510
+ - `*.js` files => `jsI18n`
511
+ - `*.soy` files => `soyTransformer`, `jsI18n`
512
+
513
+ Example configuration for custom transformations:
514
+
515
+ ```json
516
+ {
517
+ "transformationMap": {
518
+ "js": ["myOwnJsTransformer"],
519
+ "sass": ["myOwnSassTransformer"]
520
+ }
521
+ }
522
+ ```
523
+
524
+ This would set the following transformations to every generated web-resource:
525
+
526
+ ```xml
527
+ <web-resource key="...">
528
+ <transformation extension="js">
529
+ <transformer key="myOwnJsTransformer"/>
530
+ </transformation>
531
+ <transformation extension="sass">
532
+ <transformer key="myOwnSassTransformer"/>
533
+ </transformation>
534
+ </web-resource>
535
+ ```
536
+
537
+ If you wish to extend the default transformations you can use the build-in `extendTransformations` function provided by the plugin.
538
+ It will merge the default transformations with your custom config:
539
+
540
+ ```js
541
+ const WrmPlugin = require('@atlassian/webresource-webpack-plugin');
542
+
543
+ new WrmPlugin({
544
+ pluginKey: 'my.full.plugin.artifact-id',
545
+ transformationMap: WrmPlugin.extendTransformations({
546
+ js: ['myOwnJsTransformer'],
547
+ sass: ['myOwnSassTransformer'],
548
+ }),
549
+ });
550
+ ```
551
+
552
+ You can also completely disable the transformations by passing `false` value to the plugin configuration:
553
+
554
+ ```json
555
+ {
556
+ "transformationMap": false
557
+ }
558
+ ```
559
+
560
+ ### `webresourceKeyMap` (Optional)
561
+
562
+ Allows you to change the name of the web-resource that is generated for a given webpack entry-point.
563
+
564
+ This is useful when you expect other plugins will need to depend on your auto-generated web-resources directly, such
565
+ as when you refactor an existing feature (and its web-resource) to be generated via webpack.
566
+
567
+ This parameter can take either `string` or `object` with properties `key`, `name` and `state` which corresponds to
568
+ `key`, `name` and `state` attributes of `web-resource` XML element. `name` and `state` properties are optional.
569
+
570
+ Mapping as follows:
571
+
572
+ ```json
573
+ {
574
+ "webresourceKeyMap": {
575
+ "firstWebResource": "first-web-resource",
576
+ "secondWebResource": {
577
+ "key": "second-web-resource",
578
+ "name": "Second WebResource",
579
+ "state": "disabled"
580
+ }
581
+ }
582
+ }
583
+ ```
584
+
585
+ will result in the following web-resources:
586
+
587
+ ```xml
588
+ <atlassian-plugin>
589
+ <web-resource key="first-web-resource" name="" state="enabled">
590
+ <!-- your resources definitions -->
591
+ </web-resource>
592
+ <web-resource key="second-web-resource" name="Second WebResource" state="disabled">
593
+ <!-- your resources definitions -->
594
+ </web-resource>
595
+ </atlassian-plugin>
596
+ ```
597
+
598
+ ### `providedDependencies` (Optional)
599
+
600
+ A map of objects that let you associate what web-resources house particular external JS dependencies.
601
+
602
+ The format of an external dependency mapping is as follows:
603
+
604
+ ```json5
605
+ {
606
+ 'dependency-name': {
607
+ dependency: 'atlassian.plugin.key:webresource-key',
608
+ import: {
609
+ // externals configuration
610
+ },
611
+ },
612
+ }
613
+ ```
614
+
615
+ In this example, `externals` is a JSON object following the
616
+ [webpack externals format][webpack-externalobjects].
617
+
618
+ When your code is compiled through webpack, any occurrence of `dependency-name` found in a module import
619
+ statement will be replaced in the webpack output, and an appropriate web-resource `<dependency>` will be
620
+ added to the generated web-resource.
621
+
622
+ ### `wrmManifestPath` (Optional)
623
+
624
+ A path to a WRM manifest file where the plugin will store a map of objects.
625
+ Under the `providedDependencies` property is a map of dependencies, including the generated web-resource keys.
626
+ This map is the exact same format that is accepted with the `providedDependencies` option above,
627
+ so one can use this map as a source for `providedDependencies` in another build:
628
+
629
+ ```json
630
+ {
631
+ "providedDependencies": {
632
+ "dependency-name": {
633
+ "dependency": "atlassian.plugin.key:webresource-key",
634
+ "import": {
635
+ "var": "require('dependency-amd-module-name')",
636
+ "amd": "dependency-amd-module-name"
637
+ }
638
+ }
639
+ }
640
+ }
641
+ ```
642
+
643
+ #### Notes and limitations
644
+
645
+ - Both `output.library` and `output.libraryTarget` must be set for the WRM manifest file to be created.
646
+ - `output.library` must not contain \[chunk\] or \[hash\], however \[name\] is allowed
647
+ - `output.libraryTarget` must be set to `amd`
648
+ - More properties might be added to the WRM manifest file in future
649
+
650
+ #### Example configuration
651
+
652
+ ```json
653
+ {
654
+ "output": {
655
+ "library": "[name]",
656
+ "libraryTarget": "amd"
657
+ }
658
+ }
659
+ ```
660
+
661
+ ### `resourceParamMap` (Optional)
662
+
663
+ An object specifying additional parameters (`<param/>`) for `resource`s.
664
+
665
+ To specify for example content-types the server should respond with for a certain assets file-type (e.g. images/fonts):
666
+
667
+ ```json
668
+ {
669
+ "resourceParamMap": {
670
+ "svg": [
671
+ {
672
+ "name": "content-type",
673
+ "value": "image/svg+xml"
674
+ }
675
+ ]
676
+ }
677
+ }
678
+ ```
679
+
680
+ Setting specific content-types may be required by certain Atlassian products depending on the file-type to load.
681
+ _Contains content-type for svg as "image/svg+xml" by default_
682
+
683
+ ### `locationPrefix` (Optional)
684
+
685
+ Adds given prefix value to `location` attribute of `resource` node.
686
+ Use this option when your webpack output is placed in a subdirectory of the plugin's ultimate root folder.
687
+
688
+ ### `devAssetsHash` (Optional)
689
+
690
+ Uses provided value (instead of DEV_PSEUDO_HASH) in the webresource name that contains all of the assets needed in development mode.
691
+
692
+ ### `watch` and `watchPrepare` (Optional)
693
+
694
+ Activates "watch-mode". This must be run in conjunction with a webpack-dev-server.
695
+
696
+ #### `watchPrepare`
697
+
698
+ Creates "proxy"-Resources and references them in the XML-descriptor. These proxy-resources will redirect to a webpack-dev-server that has to be run too.
699
+ In order for this to work properly, ensure that the webpack-config "options.output.publicPath" points to the webpack-dev-server - including its port. (e.g. http://localhost:9000)
700
+
701
+ #### `watch` (Optional)
702
+
703
+ Use when running the process with a webpack-dev-server.
704
+
705
+ ### `useDocumentWriteInWatchMode` (Optional)
706
+
707
+ When set to `true`, the generated watch mode modules will add the script tags to the document synchronously with `document.write` while the document is loading, rather than always relying on asynchronously appended script tags (default behaviour).
708
+
709
+ This is useful when bundles are expected to be available on the page early, e.g. when code in a template relies on javascript to be loaded blockingly.
710
+
711
+ ### `noWRM` (Optional)
712
+
713
+ Will not add any WRM-specifics to the webpack-runtime or try to redirect async-chunk requests while still handling requests to `wr-dependency` and `wr-resource`.
714
+ This can be useful to develop frontend outside of a running product that provides the WRM functionality.
715
+
716
+ ### `singleRuntimeWebResourceKey` (Optional)
717
+
718
+ Set a specific web-resource key for the webpack runtime when using the webpack option `optimization.runtimeChunk` to `single` (see [runtimeChunk documentation](https://webpack.js.org/configuration/optimization/#optimizationruntimechunk)). Default is `common-runtime`.
719
+
720
+ ### `verbose` (Optional)
721
+
722
+ Indicate verbosity of log output. Default is `false`.
723
+
724
+ ## Minimum requirements
725
+
726
+ This plugin has been built to work with the following versions of the external build tools:
727
+
728
+ - Node 18 (at P2 plugin build-time)
729
+ - [Atlassian Maven Plugin Suite (AMPS)][atlassian-amps] 6.2.11+
730
+ - [Atlassian Web Resource Manager (WRM)][atlassian-wrm] 4.3.6+
731
+
732
+ This plugin is tested with webpack 5.0+.
733
+
734
+ ### Recommended with webpack 5
735
+
736
+ - To compile CSS, use `css-loader >= 5` along with `mini-css-extract-plugin >= 2`.
737
+ - When using `mini-css-extract-plugin` runtime option needs to be set to false. This will prevent `mini-css-extract-plugin` from injecting extracted css to document head, which is done by WRM.
738
+
739
+ ## Upgrade guides
740
+
741
+ - [Upgrade to 7.0.0](https://bitbucket.org/atlassianlabs/fe-server/src/master/packages/webresource-webpack-plugin/UPGRADE_700.md)
742
+
743
+ ## Troubleshooting and known problems
744
+
745
+ ### Self troubleshooting tool
746
+
747
+ We provide a tool that helps troubleshoot the configuration of webpack and Atlassian P2 projects.
748
+
749
+ To check if your project was configured correctly, open a terminal and navigate to the root directory of your project. Next, run the troubleshooting command:
750
+
751
+ ```shell
752
+ npx @atlassian/wrm-troubleshooting
753
+ ```
754
+
755
+ The tool will ask you a few questions and guide you if it finds issues with your projects' configuration.
756
+
757
+ You can read more about the troubleshooting tool on the [NPM page for the `@atlassian/wrm-troubleshooting` package][wrm-troubleshooting].
758
+
759
+ ### webpack-sources compatibility
760
+
761
+ If you install `webpack-sources@3` along with `webpack@4`, you'll likely get this error:
762
+
763
+ ```
764
+ /project/path/node_modules/webpack/node_modules/webpack-sources/lib/ConcatSource.js:59
765
+ return typeof item === "string" ? item : item.node(options);
766
+
767
+ TypeError: item.node is not a function
768
+ at /project/path/node_modules/webpack/node_modules/webpack-sources/lib/ConcatSource.js:59:50
769
+ at Array.map (<anonymous>)
770
+ at ConcatSource.node (/project/path/node_modules/webpack/node_modules/webpack-sources/lib/ConcatSource.js:58:63)
771
+ at proto.sourceAndMap (/project/path/node_modules/webpack/node_modules/webpack-sources/lib/SourceAndMapMixin.js:29:18)
772
+ at CachedSource.sourceAndMap (/project/path/node_modules/webpack/node_modules/webpack-sources/lib/CachedSource.js:58:31)
773
+ at getTaskForFile (/project/path/node_modules/webpack/lib/SourceMapDevToolPlugin.js:65:30)
774
+ at /project/path/node_modules/webpack/lib/SourceMapDevToolPlugin.js:215:20
775
+ at Array.forEach (<anonymous>)
776
+ at /project/path/node_modules/webpack/lib/SourceMapDevToolPlugin.js:186:12
777
+ at SyncHook.eval [as call] (eval at create (/project/path/node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:19:10), <anonymous>:7:1)
778
+
779
+ ```
780
+
781
+ A solution is to downgrade to `webpack-sources@2`
782
+
783
+ ### Other problems
784
+
785
+ Check that your build and bundle works as you expect without this plugin enabled. You can disable the WRM webpack plugin and bundle the code to verify no errors or warnings are present in the webpack output.
786
+
787
+ This plugin makes very few changes to what webpack ultimately outputs. If your bundles have content errors,
788
+ it may be due to version incompatibilities between webpack and the loader plugins in your build configuration.
789
+
790
+ Known problems with this plugin are listed in [the Atlassian Ecosystem issue tracker][issuetracker].
791
+ Our development team review all open issues and triage on a monthly basis.
792
+
793
+ [101]: https://bitbucket.org/serverecosystem/sao4fed-bundle-the-ui
794
+ [atlassian-sdk]: https://developer.atlassian.com/server/framework/atlassian-sdk
795
+ [atlassian-amps]: https://developer.atlassian.com/server/framework/atlassian-sdk/working-with-maven/#using-the-amps-maven-plugin-directly
796
+ [atlassian-p2]: https://bitbucket.org/atlassian/atlassian-plugins
797
+ [atlassian-wrm]: https://bitbucket.org/atlassian/atlassian-plugins-webresource
798
+ [webpack]: https://webpack.js.org/
799
+ [webpack-externalobjects]: https://webpack.js.org/configuration/externals/#object
800
+ [issuetracker]: https://ecosystem.atlassian.net/jira/software/c/projects/SPFE/issues/
801
+ [wrm-troubleshooting]: https://www.npmjs.com/package/@atlassian/wrm-troubleshooting