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
16 changes: 13 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,21 @@ declare namespace NodePolyfillPlugin {
| "vm"
| "zlib"

export interface Options {
interface IncludeOptions {
/**
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, you can choose to only include certain aliases. For example, you can only have `console` polyfilled.
*/
includeAliases?: readonly Alias[]
}

interface ExcludeOptions {
/**
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
*/
excludeAliases?: readonly Alias[]
}

export type Options = MergeExclusive<IncludeOptions, ExcludeOptions>
}

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

const excludeObjectKeys = (object, excludeKeys) => filterObject(object, key => !excludeKeys.includes(key))
function createAliasFilter({ includeAliases, excludeAliases }) {
if (includeAliases.length > 0) {
return object => filterObject(object, key => includeAliases.includes(key))
}

return object => filterObject(object, key => !excludeAliases.includes(key))
}

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")
}
}

apply(compiler) {
compiler.options.plugins.push(new ProvidePlugin(excludeObjectKeys({
const filter = createAliasFilter(this.options)

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

compiler.options.resolve.fallback = {
...excludeObjectKeys({
...filter({
assert: require.resolve("assert/"),
buffer: require.resolve("buffer/"),
console: require.resolve("console-browserify"),
Expand Down Expand Up @@ -51,7 +64,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 })
})