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

Commit

Permalink
Add dist option for omitting 'dist' et al from output path
Browse files Browse the repository at this point in the history
  • Loading branch information
dmchurch committed Oct 12, 2019
1 parent 03cbbb3 commit 72abb88
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 9 deletions.
45 changes: 44 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,17 @@ The constructor takes a configuration object with the following properties.
| --- | --- | --- | --- |
| `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* |
| `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* |
| `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* |
| `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* |
| `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* |
| `externals[].entry.path` | string | If entry is an object, the path to the asset. | *None* |
| `externals[].entry.dist` | string | The path of the vendor distribution directory, for this entry alone. | *Inherits from `externals[].dist`* |
| `externals[].entry.type` | `'js'`\|`'css'` | The asset type, if it cannot be inferred. | *Inferred by extension when possible* |
| `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. | `{}` |
| `externals[].entry`<br>`  .attributes` | object.&lt;string,string&gt; | Additional attributes to add to the injected tag. | `{}` |
| `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` |
| `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. | `[]` |
| `externals[].supplements[]`<br>`  .path` | string | The glob path to copy assets from. | *None* |
| `externals[].supplements[]`<br>`  .dist` | string | The path of the vendor distribution directory, for this entry alone. | *Inherits from `externals[].dist`* |
| `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. | `{}` |
| `externals[].append` | boolean | Set to true to inject this module after your Webpack bundles. | `false` |
| `hash` | boolean | Set to true to append the injected module distro paths with a unique hash for cache-busting. | `false` |
Expand Down Expand Up @@ -250,6 +253,46 @@ new HtmlWebpackExternalsPlugin({
})
```

### Omitting distribution path example

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.

Do not include a trailing slash or leading slash in the distribution path, they are concatenated automatically by the plugin.

This example assumes `bootstrap` is installed in the app. It:

1. copies `node_modules/bootstrap/dist/css/bootstrap.min.css` to `<output path>/vendor/bootstrap/css/bootstrap.min.css`
1. copies `node_modules/bootstrap/dist/css/bootstrap-theme.min.css` to `<output path>/vendor/bootstrap/bootstrap-theme.min.css`
1. copies all contents of `node_modules/bootstrap/dist/fonts/` to `<output path>/vendor/bootstrap/fonts/`
1. copies `node_modules/bootstrap/js/dist/dropdown.js` to `<output path>/vendor/bootstrap/dropdown.js`
1. adds `<link href="<public path>/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">` to your HTML file, before your chunks
1. adds `<link href="<public path>/vendor/bootstrap/bootstrap-theme.min.css" rel="stylesheet">` to your HTML file, before your chunks

```js
new HtmlWebpackExternalsPlugin({
externals: [
{
module: 'bootstrap',
dist: 'dist',
entry: [
'css/bootstrap.min.css',
{
dist: 'dist/css',
path: 'bootstrap-theme.min.css',
},
],
supplements: [
'fonts/',
{
dist: 'js/dist',
path: 'dropdown.js',
},
],
},
],
})
```

### Customizing public path example

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.
Expand Down
16 changes: 8 additions & 8 deletions src/HtmlWebpackExternalsPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export default class HtmlWebpackExternalsPlugin {
this.enabled = enabled
this.cwpOptions = cwpOptions

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

const localEntries = []
Expand All @@ -46,7 +46,7 @@ export default class HtmlWebpackExternalsPlugin {
return entry
}

const result = { ...entry, path: `${module}/${entry.path}` }
const result = { module, dist, ...entry }
localEntries.push(result)
return result
})
Expand All @@ -62,8 +62,8 @@ export default class HtmlWebpackExternalsPlugin {
...localEntries,
...supplements.map(asset =>
typeof asset === 'string'
? { path: `${module}/${asset}`, cwpPatternConfig: {} }
: { ...asset, path: `${module}/${asset.path}` }
? { module, dist, path: asset, cwpPatternConfig: {} }
: { module, dist, ...asset }
),
]
})
Expand Down Expand Up @@ -96,9 +96,9 @@ export default class HtmlWebpackExternalsPlugin {

pluginsToApply.push(
new CopyWebpackPlugin(
this.assetsToCopy.map(({ path, cwpPatternConfig }) => ({
from: path,
to: `${this.outputPath}/${path}`,
this.assetsToCopy.map(({ module, path, dist, cwpPatternConfig }) => ({
from: `${module}/${dist?`${dist}/`:''}${path}`,
to: `${this.outputPath}/${module}/${path}`,
...cwpPatternConfig,
})),
this.cwpOptions
Expand All @@ -115,7 +115,7 @@ export default class HtmlWebpackExternalsPlugin {
? asset
: {
...asset,
path: `${publicPath}${this.outputPath}/${asset.path}`,
path: `${publicPath}${this.outputPath}/${asset.module}/${asset.path}`,
}
),
append,
Expand Down
42 changes: 42 additions & 0 deletions test/HtmlWebpackExternalsPlugin.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,48 @@ describe('HtmlWebpackExternalsPlugin', function() {
)
})

it('Omitting distribution path example', function() {
return runWebpack(
new HtmlWebpackPlugin(),
new HtmlWebpackExternalsPlugin({
externals: [
{
module: 'bootstrap',
dist: 'dist',
entry: [
'css/bootstrap.min.css',
{
dist: 'dist/css',
path: 'bootstrap-reboot.min.css',
},
],
supplements: [
'js/',
{
dist: 'js/dist',
path: 'dropdown.js',
},
],
},
],
})
)
.then(() => checkCopied('vendor/bootstrap/css/bootstrap.min.css'))
.then(() => checkCopied('vendor/bootstrap/bootstrap-reboot.min.css'))
.then(() => checkCopied('vendor/bootstrap/js/bootstrap.bundle.js'))
.then(() => checkCopied('vendor/bootstrap/dropdown.js'))
.then(() =>
checkHtmlIncludes(
'vendor/bootstrap/css/bootstrap.min.css',
'css'
))
.then(() =>
checkHtmlIncludes(
'vendor/bootstrap/bootstrap-reboot.min.css',
'css'
))
})

it('Customizing public path example', function() {
return runWebpack(
new HtmlWebpackPlugin(),
Expand Down

0 comments on commit 72abb88

Please sign in to comment.