This repository was archived by the owner on Apr 5, 2021. It is now read-only.
v3.1.0
What's New in v3.1.0
This is a summary of the differences between v3.1.0 and v3.0.0.
Commits
Show commits
| SHA | Author | Message |
|---|---|---|
09bfaec |
mmiller42 | Adding roadmap |
ec84b02 |
mmiller42 | Allow publicPath to be overridden |
76a32fc |
mmiller42 | Allow URLs to be specified |
bbfb624 |
mmiller42 | Clean up validateConfig |
781cc65 |
mmiller42 | 3.1.0 |
Changed files
README.md
Show changes
@@ -43,12 +43,13 @@ 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<string> | 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. | *None* |
+| \`externals[].entry\` | string \| array<string> | 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 \`//\`. | *None* |
| \`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<string> | 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/\`. | \`[]\` |
| \`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\` |
| \`outputPath\` | string | The path (relative to your Webpack \`outputPath\`) to store externals copied over by this plugin. | \`vendor\` |
+| \`publicPath\` | string \| null | Override Webpack config's \`publicPath\` for the externals files, or \`null\` to use the default \`output.publicPath\` value. | \`null\` |
## Example
➕ ROADMAP.md
Show changes
@@ -0,0 +1,7 @@
+# v3.0.0 Roadmap
+
+* [ ] Support CDNs in addition to copying local modules to the build
+* [ ] Support ways to manually specify asset type (e.g. for when URLs don't end in \`.css\` or \`.js\`) -- may be dependent on html-webpack-include-assets-plugin
+* [ ] Allow more flexibility in how files are copied to the public output via copy-webpack-plugin
+* [x] Allow overriding of output \`publicPath\`
+* [ ] Support specifying which HTML files are affected by the plugin in the case of multiple instances of html-webpack-pluginpackage-lock.json
Inline diff not displayed. View the whole file
package.json
Show changes
@@ -1,6 +1,6 @@
{
"name": "html-webpack-externals-plugin",
- "version": "3.0.0",
+ "version": "3.1.0",
"description": "Webpack plugin that works alongside html-webpack-plugin to use pre-packaged vendor bundles.",
"keywords": [
"htmlwebpackplugin",
@@ -13,7 +13,7 @@
"prepack": "npm run build",
"precommit": "lint-staged",
"build": "rm -rf lib && babel src --out-dir lib --source-maps --copy-files",
- "watch": "babel src --out-dir lib --source-maps --copy-files --watch"
+ "watch": "npm run build -- --watch"
},
"lint-staged": {
"*.js": [src/HtmlWebpackExternalsPlugin.js
Show changes
@@ -2,44 +2,49 @@ import CopyWebpackPlugin from 'copy-webpack-plugin'
import HtmlWebpackIncludeAssetsPlugin from 'html-webpack-include-assets-plugin'
import Ajv from 'ajv'
-const ajv = new Ajv()
-const validateConfig = ajv.compile({
- type: 'object',
- properties: {
- externals: {
- type: 'array',
- items: {
- type: 'object',
- properties: {
- module: { type: 'string' },
- entry: {
- type: ['string', 'array'],
- items: { type: 'string' },
- minItems: 1,
- },
- global: { type: ['string', 'null'] },
- supplements: {
- type: 'array',
- items: { type: 'string' },
+export default class HtmlWebpackExternalsPlugin {
+ static validateArguments = (() => {
+ const ajv = new Ajv()
+ const validateConfig = ajv.compile({
+ type: 'object',
+ properties: {
+ externals: {
+ type: 'array',
+ items: {
+ type: 'object',
+ properties: {
+ module: { type: 'string' },
+ entry: {
+ type: ['string', 'array'],
+ items: { type: 'string' },
+ minItems: 1,
+ },
+ global: { type: ['string', 'null'] },
+ supplements: {
+ type: 'array',
+ items: { type: 'string' },
+ },
+ append: { type: 'boolean' },
+ },
+ required: ['module', 'entry'],
},
- append: { type: 'boolean' },
+ minItems: 1,
},
- required: ['module', 'entry'],
+ hash: { type: 'boolean' },
+ outputPath: { type: 'string' },
+ publicPath: { type: ['string', 'null'] },
},
- minItems: 1,
- },
- hash: { type: 'boolean' },
- outputPath: { type: 'string' },
- },
- required: ['externals'],
-})
+ required: ['externals'],
+ })
-export default class HtmlWebpackExternalsPlugin {
- static validateArguments(config) {
- if (!validateConfig(config)) {
- throw new TypeError(ajv.errorsText(validateConfig.errors))
+ return config => {
+ if (!validateConfig(config)) {
+ throw new TypeError(ajv.errorsText(validateConfig.errors))
+ }
}
- }
+ })()
+
+ static URL_ENTRY = /^(http:|https:)?\/\//
constructor(config) {
HtmlWebpackExternalsPlugin.validateArguments(config)
@@ -49,17 +54,30 @@ export default class HtmlWebpackExternalsPlugin {
this.assetsToCopy = []
this.externals = {}
- const { externals, hash = false, outputPath = 'vendor' } = config
+ const {
+ externals,
+ hash = false,
+ outputPath = 'vendor',
+ publicPath = null,
+ } = config
this.hash = hash
this.outputPath = outputPath
+ this.publicPath = publicPath
externals.forEach(
({ module, entry, global = null, supplements = [], append = false }) => {
this.externals[module] = global
- const entries = (Array.isArray(entry) ? entry : [entry]).map(
- entry => \`${module}/${entry}\`
- )
+ const localEntries = []
+
+ const entries = (Array.isArray(entry) ? entry : [entry]).map(entry => {
+ if (HtmlWebpackExternalsPlugin.URL_ENTRY.test(entry)) {
+ return entry
+ }
+ const localEntry = \`${module}/${entry}\`
+ localEntries.push(localEntry)
+ return localEntry
+ })
if (append) {
this.assetsToAppend = [...this.assetsToAppend, ...entries]
@@ -69,7 +87,7 @@ export default class HtmlWebpackExternalsPlugin {
this.assetsToCopy = [
...this.assetsToCopy,
- ...entries,
+ ...localEntries,
...supplements.map(asset => \`${module}/${asset}\`),
]
}
@@ -88,6 +106,11 @@ export default class HtmlWebpackExternalsPlugin {
}
}
+ const publicPath =
+ this.publicPath == null
+ ? compiler.options.output.publicPath
+ : this.publicPath
+
const pluginsToApply = []
pluginsToApply.push(
@@ -99,29 +122,26 @@ export default class HtmlWebpackExternalsPlugin {
)
)
- if (this.assetsToPrepend.length) {
- pluginsToApply.push(
- new HtmlWebpackIncludeAssetsPlugin({
- assets: this.assetsToPrepend.map(
- asset => \`${this.outputPath}/${asset}\`
- ),
- append: false,
- hash: this.hash,
- })
- )
+ const createAssetsPlugin = (assets, append) => {
+ if (assets.length) {
+ pluginsToApply.push(
+ new HtmlWebpackIncludeAssetsPlugin({
+ assets: assets.map(
+ asset =>
+ HtmlWebpackExternalsPlugin.URL_ENTRY.test(asset)
+ ? asset
+ : \`${publicPath}${this.outputPath}/${asset}\`
+ ),
+ append,
+ hash: this.hash,
+ publicPath: '',
+ })
+ )
+ }
}
- if (this.assetsToAppend.length) {
- pluginsToApply.push(
- new HtmlWebpackIncludeAssetsPlugin({
- assets: this.assetsToAppend.map(
- asset => \`${this.outputPath}/${asset}\`
- ),
- append: true,
- hash: this.hash,
- })
- )
- }
+ createAssetsPlugin(this.assetsToPrepend, false)
+ createAssetsPlugin(this.assetsToAppend, true)
pluginsToApply.forEach(plugin => plugin.apply(compiler))
}