Skip to content
This repository was archived by the owner on Apr 5, 2021. It is now read-only.

Commit 72abb88

Browse files
committed
Add dist option for omitting 'dist' et al from output path
1 parent 03cbbb3 commit 72abb88

File tree

3 files changed

+94
-9
lines changed

3 files changed

+94
-9
lines changed

README.md

+44-1
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,17 @@ The constructor takes a configuration object with the following properties.
4343
| --- | --- | --- | --- |
4444
| `externals` | array<object> | An array of vendor modules that will be excluded from your Webpack bundle and added as `script` or `link` tags in your HTML output. | *None* |
4545
| `externals[].module` | string | The name of the vendor module. This should match the package name, e.g. if you are writing `import React from 'react'`, this would be `react`. | *None* |
46-
| `externals[].entry` | string \| array&lt;string&gt; \| object \| array&lt;object \| string&gt; | The path, relative to the vendor module directory, to its pre-bundled distro file. e.g. for React, use `dist/react.js`, since the file exists at `node_modules/react/dist/react.js`. Specify an array if there are multiple CSS/JS files to inject. To use a CDN instead, simply use a fully qualified URL beginning with `http://`, `https://`, or `//`.<br><br>For entries whose type (JS or CSS) cannot be inferred by file extension, pass an object such as `{ path: 'https://some/url', type: 'css' }` (or `type: 'js'`). | *None* |
46+
| `externals[].dist` | string | The relative path of the vendor distribution directory. All entry paths are resolved relative to this directory, but it is *not* included in the output path. | *None* |
47+
| `externals[].entry` | string \| array&lt;string&gt; \| object \| array&lt;object \| string&gt; | The path, relative to the vendor distribution directory, to its pre-bundled distro file. e.g. for React, use `dist/react.js` (or, if you have set `.dist: "dist"`, just use `react.js`), since the file exists at `node_modules/react/dist/react.js`. Specify an array if there are multiple CSS/JS files to inject. To use a CDN instead, simply use a fully qualified URL beginning with `http://`, `https://`, or `//`.<br><br>For entries whose type (JS or CSS) cannot be inferred by file extension, pass an object such as `{ path: 'https://some/url', type: 'css' }` (or `type: 'js'`). | *None* |
4748
| `externals[].entry.path` | string | If entry is an object, the path to the asset. | *None* |
49+
| `externals[].entry.dist` | string | The path of the vendor distribution directory, for this entry alone. | *Inherits from `externals[].dist`* |
4850
| `externals[].entry.type` | `'js'`\|`'css'` | The asset type, if it cannot be inferred. | *Inferred by extension when possible* |
4951
| `externals[].entry`<br>`  .cwpPatternConfig` | object | The properties to set on the [`copy-webpack-plugin` pattern object](https://github.com/webpack-contrib/copy-webpack-plugin#patterns). This object is merged in with the default `from` and `to` properties which are generated by the externals plugin. | `{}` |
5052
| `externals[].entry`<br>`  .attributes` | object.&lt;string,string&gt; | Additional attributes to add to the injected tag. | `{}` |
5153
| `externals[].global` | string \| null | For JavaScript modules, this is the name of the object globally exported by the vendor's dist file. e.g. for React, use `React`, since `react.js` creates a `window.React` global. For modules without an export (such as CSS), omit this property or use `null`. | `null` |
5254
| `externals[].supplements` | array&lt;string&gt; \| array&lt;object&gt; | For modules that require additional resources, specify globs of files to copy over to the output. e.g. for Bootstrap CSS, use `['dist/fonts/']`, since Glyphicon fonts are referenced in the CSS and exist at `node_modules/bootstrap/dist/fonts/`. Supplements can be specified as just an array of paths, or an array of objects with a path and copy plugin pattern object. | `[]` |
5355
| `externals[].supplements[]`<br>`  .path` | string | The glob path to copy assets from. | *None* |
56+
| `externals[].supplements[]`<br>`  .dist` | string | The path of the vendor distribution directory, for this entry alone. | *Inherits from `externals[].dist`* |
5457
| `externals[].supplements[]`<br>`  .cwpPatternConfig` | object | The properties to set on the [`copy-webpack-plugin` pattern object](https://github.com/webpack-contrib/copy-webpack-plugin#patterns). This object is merged in with the default `from` and `to` properties which are generated by the externals plugin. | `{}` |
5558
| `externals[].append` | boolean | Set to true to inject this module after your Webpack bundles. | `false` |
5659
| `hash` | boolean | Set to true to append the injected module distro paths with a unique hash for cache-busting. | `false` |
@@ -250,6 +253,46 @@ new HtmlWebpackExternalsPlugin({
250253
})
251254
```
252255

256+
### Omitting distribution path example
257+
258+
By default, the Webpack output directory includes the full relative path of all copied files relative to their module root, including top-level directories like `dist` or `build`. You can omit these top-level directories in your output.
259+
260+
Do not include a trailing slash or leading slash in the distribution path, they are concatenated automatically by the plugin.
261+
262+
This example assumes `bootstrap` is installed in the app. It:
263+
264+
1. copies `node_modules/bootstrap/dist/css/bootstrap.min.css` to `<output path>/vendor/bootstrap/css/bootstrap.min.css`
265+
1. copies `node_modules/bootstrap/dist/css/bootstrap-theme.min.css` to `<output path>/vendor/bootstrap/bootstrap-theme.min.css`
266+
1. copies all contents of `node_modules/bootstrap/dist/fonts/` to `<output path>/vendor/bootstrap/fonts/`
267+
1. copies `node_modules/bootstrap/js/dist/dropdown.js` to `<output path>/vendor/bootstrap/dropdown.js`
268+
1. adds `<link href="<public path>/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">` to your HTML file, before your chunks
269+
1. adds `<link href="<public path>/vendor/bootstrap/bootstrap-theme.min.css" rel="stylesheet">` to your HTML file, before your chunks
270+
271+
```js
272+
new HtmlWebpackExternalsPlugin({
273+
externals: [
274+
{
275+
module: 'bootstrap',
276+
dist: 'dist',
277+
entry: [
278+
'css/bootstrap.min.css',
279+
{
280+
dist: 'dist/css',
281+
path: 'bootstrap-theme.min.css',
282+
},
283+
],
284+
supplements: [
285+
'fonts/',
286+
{
287+
dist: 'js/dist',
288+
path: 'dropdown.js',
289+
},
290+
],
291+
},
292+
],
293+
})
294+
```
295+
253296
### Customizing public path example
254297

255298
By default, local externals are resolved from the same root path as your Webpack configuration file's `output.publicPath`, concatenated with the `outputPath` variable. This is configurable.

src/HtmlWebpackExternalsPlugin.js

+8-8
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export default class HtmlWebpackExternalsPlugin {
3333
this.enabled = enabled
3434
this.cwpOptions = cwpOptions
3535

36-
externals.forEach(({ module, entry, global, supplements, append }) => {
36+
externals.forEach(({ module, dist, entry, global, supplements, append }) => {
3737
this.externals.push(global ? { [module]: global } : module)
3838

3939
const localEntries = []
@@ -46,7 +46,7 @@ export default class HtmlWebpackExternalsPlugin {
4646
return entry
4747
}
4848

49-
const result = { ...entry, path: `${module}/${entry.path}` }
49+
const result = { module, dist, ...entry }
5050
localEntries.push(result)
5151
return result
5252
})
@@ -62,8 +62,8 @@ export default class HtmlWebpackExternalsPlugin {
6262
...localEntries,
6363
...supplements.map(asset =>
6464
typeof asset === 'string'
65-
? { path: `${module}/${asset}`, cwpPatternConfig: {} }
66-
: { ...asset, path: `${module}/${asset.path}` }
65+
? { module, dist, path: asset, cwpPatternConfig: {} }
66+
: { module, dist, ...asset }
6767
),
6868
]
6969
})
@@ -96,9 +96,9 @@ export default class HtmlWebpackExternalsPlugin {
9696

9797
pluginsToApply.push(
9898
new CopyWebpackPlugin(
99-
this.assetsToCopy.map(({ path, cwpPatternConfig }) => ({
100-
from: path,
101-
to: `${this.outputPath}/${path}`,
99+
this.assetsToCopy.map(({ module, path, dist, cwpPatternConfig }) => ({
100+
from: `${module}/${dist?`${dist}/`:''}${path}`,
101+
to: `${this.outputPath}/${module}/${path}`,
102102
...cwpPatternConfig,
103103
})),
104104
this.cwpOptions
@@ -115,7 +115,7 @@ export default class HtmlWebpackExternalsPlugin {
115115
? asset
116116
: {
117117
...asset,
118-
path: `${publicPath}${this.outputPath}/${asset.path}`,
118+
path: `${publicPath}${this.outputPath}/${asset.module}/${asset.path}`,
119119
}
120120
),
121121
append,

test/HtmlWebpackExternalsPlugin.spec.js

+42
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,48 @@ describe('HtmlWebpackExternalsPlugin', function() {
234234
)
235235
})
236236

237+
it('Omitting distribution path example', function() {
238+
return runWebpack(
239+
new HtmlWebpackPlugin(),
240+
new HtmlWebpackExternalsPlugin({
241+
externals: [
242+
{
243+
module: 'bootstrap',
244+
dist: 'dist',
245+
entry: [
246+
'css/bootstrap.min.css',
247+
{
248+
dist: 'dist/css',
249+
path: 'bootstrap-reboot.min.css',
250+
},
251+
],
252+
supplements: [
253+
'js/',
254+
{
255+
dist: 'js/dist',
256+
path: 'dropdown.js',
257+
},
258+
],
259+
},
260+
],
261+
})
262+
)
263+
.then(() => checkCopied('vendor/bootstrap/css/bootstrap.min.css'))
264+
.then(() => checkCopied('vendor/bootstrap/bootstrap-reboot.min.css'))
265+
.then(() => checkCopied('vendor/bootstrap/js/bootstrap.bundle.js'))
266+
.then(() => checkCopied('vendor/bootstrap/dropdown.js'))
267+
.then(() =>
268+
checkHtmlIncludes(
269+
'vendor/bootstrap/css/bootstrap.min.css',
270+
'css'
271+
))
272+
.then(() =>
273+
checkHtmlIncludes(
274+
'vendor/bootstrap/bootstrap-reboot.min.css',
275+
'css'
276+
))
277+
})
278+
237279
it('Customizing public path example', function() {
238280
return runWebpack(
239281
new HtmlWebpackPlugin(),

0 commit comments

Comments
 (0)