Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ jobs:
- run: pnpm playwright install --with-deps
- name: update overrides to use vite 8 and re-install
run: |
jq '.pnpm.overrides.vite = "8.0.1"' package.json > package.tmp.json
jq '.pnpm.overrides.vite = "8.0.1" | .pnpm.overrides.vitest = "^4.1.2"' package.json > package.tmp.json
mv package.tmp.json package.json
pnpm i --no-frozen-lockfile
- run: pnpm -r test:e2e
- run: pnpm -r test
test-unit:
runs-on: ubuntu-latest
steps:
Expand Down
86 changes: 64 additions & 22 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import esbuildPlugin from 'node-stdlib-browser/helpers/esbuild/plugin'
import type { Plugin } from 'vite'
import { compareModuleNames, isEnabled, isNodeProtocolImport, toRegExp, withoutNodeProtocol } from './utils'

type TransformHook = Extract<Plugin['transform'], Function>

export type BuildTarget = 'build' | 'dev'
export type BooleanOrBuildTarget = boolean | BuildTarget
export type ModuleName = keyof typeof stdLibBrowser
Expand Down Expand Up @@ -102,6 +104,10 @@ const globalShimBanners = {
],
}

const isModuleName = (name: string): name is ModuleName => {
return name in stdLibBrowser
}

/**
* Returns a Vite plugin to polyfill Node's Core Modules for browser environments. Supports `node:` protocol imports.
*
Expand Down Expand Up @@ -130,7 +136,7 @@ const globalShimBanners = {
* })
* ```
*/
export const nodePolyfills = (options: PolyfillOptions = {}): Plugin => {
export const nodePolyfills = (options: PolyfillOptions = {}): Plugin[] => {
const optionsResolved: PolyfillOptionsResolved = {
include: [],
exclude: [],
Expand Down Expand Up @@ -192,14 +198,51 @@ export const nodePolyfills = (options: PolyfillOptions = {}): Plugin => {
...((isEnabled(optionsResolved.globals.process, 'dev')) ? [require.resolve('vite-plugin-node-polyfills/shims/process')] : []),
]

const resolvePlugin: Plugin = {
name: 'vite-plugin-node-polyfills:resolve',
enforce: 'pre',
resolveId: {
// @ts-expect-error -- hook filters are only supported in Vite 6.3.0+
filter: { id: new RegExp(Object.keys(stdLibBrowser).map((name) => `^${name}\/?$`).join('|')) },
async handler(source, importer, opts) {
if (!optionsResolved.protocolImports && isNodeProtocolImport(source)) {
return
}
source = source.endsWith('/') ? source.slice(0, -1) : source // strip trailing slash
if (!isModuleName(source) || isExcluded(source)) {
return
}
const aliased = toOverride(withoutNodeProtocol(source)) || stdLibBrowser[source]
const resolved = await this.resolve(aliased, importer, { skipSelf: true, ...opts })
return resolved
},
},
}

const globalShimsBanner = [
...((isEnabled(optionsResolved.globals.Buffer, 'dev')) ? globalShimBanners.buffer : []),
...((isEnabled(optionsResolved.globals.global, 'dev')) ? globalShimBanners.global : []),
...((isEnabled(optionsResolved.globals.process, 'dev')) ? globalShimBanners.process : []),
``,
].join('\n')

return {
let rawInjectPlugin: Plugin | false | undefined
function transform(this: ThisParameterType<TransformHook>, code: string, id: string, opts: Parameters<TransformHook>[2]) {
if (rawInjectPlugin === undefined) {
throw new Error('transform called before inject plugin initialization')
}
if (rawInjectPlugin === false) {
return
}
return (rawInjectPlugin.transform as TransformHook).call(this, code, id, opts)
}
const injectPlugin: Plugin = {
name: 'vite-plugin-node-polyfills:inject',
enforce: 'post',
transform,
}

const plugin: Plugin = {
name: 'vite-plugin-node-polyfills',
config(config, env) {
const isDev = env.command === 'serve'
Expand All @@ -220,6 +263,17 @@ export const nodePolyfills = (options: PolyfillOptions = {}): Plugin => {
...(isEnabled(optionsResolved.globals.process, 'build') ? { process: 'vite-plugin-node-polyfills/shims/process' } : {}),
}

const isNativeInjectAvailable = env.command === 'build' && isRolldownVite
rawInjectPlugin = (Object.keys(shimsToInject).length > 0 && !isNativeInjectAvailable) ? inject(shimsToInject) as Plugin : false
if (rawInjectPlugin === false) {
delete injectPlugin.transform
} else {
// hook filters are only supported in Vite 6.3.0+
(transform as any).filter = {
code: new RegExp(Object.keys(shimsToInject).join('|')),
}
}

return {
build: {
rollupOptions: {
Expand All @@ -232,34 +286,23 @@ export const nodePolyfills = (options: PolyfillOptions = {}): Plugin => {
rollupWarn(warning)
})
},
...Object.keys(shimsToInject).length > 0
? isRolldownVite
? { transform: { inject: shimsToInject } }
: { plugins: [inject(shimsToInject)] }
...(Object.keys(shimsToInject).length > 0 && isRolldownVite)
? { transform: { inject: shimsToInject } }
: {},
},
},
esbuild: {
// In dev, the global polyfills need to be injected as a banner in order for isolated scripts (such as Vue SFCs) to have access to them.
banner: isDev ? globalShimsBanner : undefined,
},
optimizeDeps: {
exclude: [
...globalShimPaths,
],
...isRolldownVite
? {
rolldownOptions: {
resolve: {
// https://github.com/niksy/node-stdlib-browser/blob/3e7cd7f3d115ac5c4593b550e7d8c4a82a0d4ac4/README.md?plain=1#L150
alias: {
...polyfills,
},
},
transform: {
define: defines,
},
plugins: [
resolvePlugin,
{
name: 'vite-plugin-node-polyfills:optimizer',
banner: isDev ? globalShimsBanner : undefined,
Expand Down Expand Up @@ -299,13 +342,12 @@ export const nodePolyfills = (options: PolyfillOptions = {}): Plugin => {
},
},
},
resolve: {
// https://github.com/niksy/node-stdlib-browser/blob/3e7cd7f3d115ac5c4593b550e7d8c4a82a0d4ac4/README.md?plain=1#L150
alias: {
...polyfills,
},
},
}
},
}
return [
resolvePlugin,
injectPlugin,
plugin,
]
}
30 changes: 6 additions & 24 deletions test/integration/global-references/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,7 @@ describe('import globals', () => {
const result = await transformDev(`Buffer.from('test')`)

expect(result?.code).toEqual(formatWhitespace(`
import __buffer_polyfill from "/shims/buffer/dist/index.js"
globalThis.Buffer = globalThis.Buffer || __buffer_polyfill
import __global_polyfill from "/shims/global/dist/index.js"
globalThis.global = globalThis.global || __global_polyfill
import __process_polyfill from "/shims/process/dist/index.js"
globalThis.process = globalThis.process || __process_polyfill
import { default as Buffer } from "/shims/buffer/dist/index.js";

Buffer.from("test");
`))
Expand All @@ -28,8 +23,7 @@ describe('import globals', () => {
})

expect(result?.code).toEqual(formatWhitespace(`
import __buffer_polyfill from "/shims/buffer/dist/index.js"
globalThis.Buffer = globalThis.Buffer || __buffer_polyfill
import { default as Buffer } from "/shims/buffer/dist/index.js";

Buffer.from("test");
`))
Expand All @@ -41,12 +35,7 @@ describe('import globals', () => {
const result = await transformDev(`console.log(global)`)

expect(result?.code).toEqual(formatWhitespace(`
import __buffer_polyfill from "/shims/buffer/dist/index.js"
globalThis.Buffer = globalThis.Buffer || __buffer_polyfill
import __global_polyfill from "/shims/global/dist/index.js"
globalThis.global = globalThis.global || __global_polyfill
import __process_polyfill from "/shims/process/dist/index.js"
globalThis.process = globalThis.process || __process_polyfill
import { default as global } from "/shims/global/dist/index.js";

console.log(global);
`))
Expand All @@ -62,8 +51,7 @@ describe('import globals', () => {
})

expect(result?.code).toEqual(formatWhitespace(`
import __global_polyfill from "/shims/global/dist/index.js"
globalThis.global = globalThis.global || __global_polyfill
import { default as global } from "/shims/global/dist/index.js";

console.log(global);
`))
Expand All @@ -75,12 +63,7 @@ describe('import globals', () => {
const result = await transformDev(`console.log(process)`)

expect(result?.code).toEqual(formatWhitespace(`
import __buffer_polyfill from "/shims/buffer/dist/index.js"
globalThis.Buffer = globalThis.Buffer || __buffer_polyfill
import __global_polyfill from "/shims/global/dist/index.js"
globalThis.global = globalThis.global || __global_polyfill
import __process_polyfill from "/shims/process/dist/index.js"
globalThis.process = globalThis.process || __process_polyfill
import { default as process } from "/shims/process/dist/index.js";

console.log(process);
`))
Expand All @@ -96,8 +79,7 @@ describe('import globals', () => {
})

expect(result?.code).toEqual(formatWhitespace(`
import __process_polyfill from "/shims/process/dist/index.js"
globalThis.process = globalThis.process || __process_polyfill
import { default as process } from "/shims/process/dist/index.js";

console.log(process);
`))
Expand Down
56 changes: 0 additions & 56 deletions test/integration/import-globals/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,6 @@ describe('import globals', () => {
`)

expect(result?.code).toEqual(formatWhitespace(`
import __buffer_polyfill from "/shims/buffer/dist/index.js"
globalThis.Buffer = globalThis.Buffer || __buffer_polyfill
import __global_polyfill from "/shims/global/dist/index.js"
globalThis.global = globalThis.global || __global_polyfill
import __process_polyfill from "/shims/process/dist/index.js"
globalThis.process = globalThis.process || __process_polyfill

import Buffer from "/shims/buffer/dist/index.js";
console.log(Buffer);
`))
Expand All @@ -29,13 +22,6 @@ describe('import globals', () => {
`)

expect(result?.code).toEqual(formatWhitespace(`
import __buffer_polyfill from "/shims/buffer/dist/index.js"
globalThis.Buffer = globalThis.Buffer || __buffer_polyfill
import __global_polyfill from "/shims/global/dist/index.js"
globalThis.global = globalThis.global || __global_polyfill
import __process_polyfill from "/shims/process/dist/index.js"
globalThis.process = globalThis.process || __process_polyfill

import Buffer from "/shims/buffer/dist/index.js";
console.log(Buffer);
`))
Expand All @@ -48,13 +34,6 @@ describe('import globals', () => {
`)

expect(result?.code).toEqual(formatWhitespace(`
import __buffer_polyfill from "/shims/buffer/dist/index.js"
globalThis.Buffer = globalThis.Buffer || __buffer_polyfill
import __global_polyfill from "/shims/global/dist/index.js"
globalThis.global = globalThis.global || __global_polyfill
import __process_polyfill from "/shims/process/dist/index.js"
globalThis.process = globalThis.process || __process_polyfill

import Buffer from "/shims/buffer/dist/index.js";
console.log(Buffer);
`))
Expand All @@ -67,13 +46,6 @@ describe('import globals', () => {
`)

expect(result?.code).toEqual(formatWhitespace(`
import __buffer_polyfill from "/shims/buffer/dist/index.js"
globalThis.Buffer = globalThis.Buffer || __buffer_polyfill
import __global_polyfill from "/shims/global/dist/index.js"
globalThis.global = globalThis.global || __global_polyfill
import __process_polyfill from "/shims/process/dist/index.js"
globalThis.process = globalThis.process || __process_polyfill

import Buffer from "/shims/buffer/dist/index.js";
console.log(Buffer);
`))
Expand All @@ -88,13 +60,6 @@ describe('import globals', () => {
`)

expect(result?.code).toEqual(formatWhitespace(`
import __buffer_polyfill from "/shims/buffer/dist/index.js"
globalThis.Buffer = globalThis.Buffer || __buffer_polyfill
import __global_polyfill from "/shims/global/dist/index.js"
globalThis.global = globalThis.global || __global_polyfill
import __process_polyfill from "/shims/process/dist/index.js"
globalThis.process = globalThis.process || __process_polyfill

import process from "/shims/process/dist/index.js";
console.log(process);
`))
Expand All @@ -107,13 +72,6 @@ describe('import globals', () => {
`)

expect(result?.code).toEqual(formatWhitespace(`
import __buffer_polyfill from "/shims/buffer/dist/index.js"
globalThis.Buffer = globalThis.Buffer || __buffer_polyfill
import __global_polyfill from "/shims/global/dist/index.js"
globalThis.global = globalThis.global || __global_polyfill
import __process_polyfill from "/shims/process/dist/index.js"
globalThis.process = globalThis.process || __process_polyfill

import process from "/shims/process/dist/index.js";
console.log(process);
`))
Expand All @@ -126,13 +84,6 @@ describe('import globals', () => {
`)

expect(result?.code).toEqual(formatWhitespace(`
import __buffer_polyfill from "/shims/buffer/dist/index.js"
globalThis.Buffer = globalThis.Buffer || __buffer_polyfill
import __global_polyfill from "/shims/global/dist/index.js"
globalThis.global = globalThis.global || __global_polyfill
import __process_polyfill from "/shims/process/dist/index.js"
globalThis.process = globalThis.process || __process_polyfill

import process from "/shims/process/dist/index.js";
console.log(process);
`))
Expand All @@ -145,13 +96,6 @@ describe('import globals', () => {
`)

expect(result?.code).toEqual(formatWhitespace(`
import __buffer_polyfill from "/shims/buffer/dist/index.js"
globalThis.Buffer = globalThis.Buffer || __buffer_polyfill
import __global_polyfill from "/shims/global/dist/index.js"
globalThis.global = globalThis.global || __global_polyfill
import __process_polyfill from "/shims/process/dist/index.js"
globalThis.process = globalThis.process || __process_polyfill

import process from "/shims/process/dist/index.js";
console.log(process);
`))
Expand Down