Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow selectively including polyfills #30

Merged
merged 14 commits into from
Jun 24, 2022
15 changes: 12 additions & 3 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { MergeExclusive } from "type-fest"
import { Compiler } from "webpack"

declare namespace NodePolyfillPlugin {
Expand Down Expand Up @@ -34,12 +35,20 @@ declare namespace NodePolyfillPlugin {
| "vm"
| "zlib"

export interface Options {
interface Include {
rjerue marked this conversation as resolved.
Show resolved Hide resolved
/**
By default, the modules that were polyfilled in Webpack 4 are mirrored over. However, if you don't want a module like console to be polyfilled you can specify alises to be skipped here.
*/
By default, the modules that were polyfilled in Webpack 4 are mirrored over. However, if you don't want a module like console to be polyfilled you can specify alises to be skipped here.
rjerue marked this conversation as resolved.
Show resolved Hide resolved
*/
includeAliases?: readonly Alias[]
}

interface Exclude {
rjerue marked this conversation as resolved.
Show resolved Hide resolved
/**
By default, the modules that were polyfilled in Webpack 4 are mirrored over. However, you can choose to only include certain aliases. For example, you can only have `console` polyfilled.
*/
excludeAliases?: readonly Alias[]
}
export type Options = MergeExclusive<Include, Exclude>
rjerue marked this conversation as resolved.
Show resolved Hide resolved
}

declare class NodePolyfillPlugin {
Expand Down
21 changes: 16 additions & 5 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,36 @@
const { ProvidePlugin } = require("webpack")
const filterObject = require("filter-obj")

const excludeObjectKeys = (object, excludeKeys) => filterObject(object, key => !excludeKeys.includes(key))
const filterObjectKeys = (includeAliases, excludeAliases) => {
rjerue marked this conversation as resolved.
Show resolved Hide resolved
rjerue marked this conversation as resolved.
Show resolved Hide resolved
const isInclude = includeAliases.length > 0
const keys = isInclude ? includeAliases : excludeAliases
return object => filterObject(object, key => keys.includes(key) === isInclude)
}

module.exports = class NodePolyfillPlugin {
constructor(options = {}) {
this.options = {
excludeAliases: [],
includeAliases: [],
...options
}

if (this.options.includeAliases.length > 0 && this.options.excludeAliases.length > 0) {
throw new Error("excludeAliases and includeAliases are mutually exclusive!")
rjerue marked this conversation as resolved.
Show resolved Hide resolved
}
}

apply(compiler) {
compiler.options.plugins.push(new ProvidePlugin(excludeObjectKeys({
const filterFunc = filterObjectKeys(this.options.includeAliases, this.options.excludeAliases)
rjerue marked this conversation as resolved.
Show resolved Hide resolved

compiler.options.plugins.push(new ProvidePlugin(filterFunc({
Buffer: [require.resolve("buffer/"), "Buffer"],
console: require.resolve("console-browserify"),
process: require.resolve("process/browser")
}, this.options.excludeAliases)))
})))

compiler.options.resolve.fallback = {
...excludeObjectKeys({
...filterFunc({
assert: require.resolve("assert/"),
buffer: require.resolve("buffer/"),
console: require.resolve("console-browserify"),
Expand Down Expand Up @@ -51,7 +62,7 @@ module.exports = class NodePolyfillPlugin {
util: require.resolve("util/"),
vm: require.resolve("vm-browserify"),
zlib: require.resolve("browserify-zlib")
}, this.options.excludeAliases),
}),
...compiler.options.resolve.fallback
}
}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"string_decoder": "^1.3.0",
"timers-browserify": "^2.0.12",
"tty-browserify": "^0.0.1",
"type-fest": "^2.13.1",
"url": "^0.11.0",
"util": "^0.12.4",
"vm-browserify": "^1.1.2"
Expand Down
19 changes: 19 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ module.exports = {

Type: `object`

`excludeAliases` and `includeAliases` are mutually exclusive.

#### excludeAliases

By default, the modules that were polyfilled in Webpack 4 are mirrored over. However, if you don't want a module like `console` to be polyfilled you can specify alises to be skipped here.
Expand All @@ -52,6 +54,23 @@ module.exports = {
}
```

#### includeAliases
rjerue marked this conversation as resolved.
Show resolved Hide resolved

Alternatively, you can choose to only include certain aliases. For example, you can only have `console` polyfilled.

```js
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin")

module.exports = {
// Other rules...
plugins: [
new NodePolyfillPlugin({
includeAliases: ["console"]
})
]
}
```

## Aliases

### Globals
Expand Down
36 changes: 35 additions & 1 deletion test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const test = require("ava")
const webpack = require("p-webpack")
const NodePolyfillPlugin = require(".")

test("main", async t => {
test.serial("main", async t => {
await webpack({
entry: "./fixture",
output: {
Expand All @@ -22,4 +22,38 @@ test("main", async t => {

// https://github.com/browserify/console-browserify/blob/f7eefc7c908c29d2e94954e5c6c1098e8c1028b4/index.js#L63
t.false(fs.readFileSync("./dist/main.js").toString().includes("No such label: "))

// https://github.com/feross/buffer/blob/master/index.js#L80
t.true(fs.readFileSync("./dist/main.js").toString().includes("is invalid for option \"size\""))
})

test.serial("includeAliases", async t => {
await webpack({
entry: "./fixture",
output: {
library: {
type: "commonjs-module"
}
},
plugins: [
new NodePolyfillPlugin({
includeAliases: ["console"]
})
]
})

t.is(require("./dist/main.js"), "Hello World")

// https://github.com/browserify/console-browserify/blob/f7eefc7c908c29d2e94954e5c6c1098e8c1028b4/index.js#L63
t.true(fs.readFileSync("./dist/main.js").toString().includes("No such label: "))

// https://github.com/feross/buffer/blob/master/index.js#L80
t.false(fs.readFileSync("./dist/main.js").toString().includes("is invalid for option \"size\""))
})

test("includeAliases and excludeAliases used at the same time", t => {
t.throws(() => new NodePolyfillPlugin({
includeAliases: ["console"],
excludeAliases: ["crypto"]
}), { instanceOf: Error })
})