Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ const bundle: BundleFunction = async ({
mainFile: normalizedMainFile,
moduleFormat,
nativeNodeModules,
srcFiles: [...supportingSrcFiles, ...bundlePaths.keys()],
// We sort so that the archive's checksum is deterministic.
srcFiles: [...supportingSrcFiles, ...bundlePaths.keys()].sort(),
}
}

Expand Down
50 changes: 50 additions & 0 deletions packages/zip-it-and-ship-it/tests/esbuild.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@ import { ARCHIVE_FORMAT } from '../src/archive.js'
import { NODE_BUNDLER } from '../src/runtimes/node/bundlers/types.js'

import { zipFixture } from './helpers/main.js'
import { computeSha1 } from './helpers/sha.js'

import 'source-map-support/register'

// Shared state used by the `src_files` mock below to optionally reverse the
// order in which source files are discovered, simulating the run-to-run
// filesystem traversal variance that happens across build environments.
const { srcFilesOrder } = vi.hoisted(() => ({ srcFilesOrder: { reverse: false } }))

vi.mock('../src/utils/shell.js', () => ({ shellUtils: { runCommand: vi.fn() } }))

vi.mock('esbuild', async () => {
Expand All @@ -19,9 +25,27 @@ vi.mock('esbuild', async () => {
}
})

// Wraps the real `getSrcFiles` so a test can flip the discovery order without
// touching the filesystem. With `reverse` disabled (the default) the behaviour
// is identical to the real module, so other tests are unaffected.
vi.mock('../src/runtimes/node/bundlers/esbuild/src_files.js', async () => {
const actual = await vi.importActual<typeof import('../src/runtimes/node/bundlers/esbuild/src_files.js')>(
'../src/runtimes/node/bundlers/esbuild/src_files.js',
)

const getSrcFiles: typeof actual.getSrcFiles = async (options) => {
const result = await actual.getSrcFiles(options)

return srcFilesOrder.reverse ? { ...result, srcFiles: [...result.srcFiles].reverse() } : result
}

return { ...actual, getSrcFiles }
})

describe('esbuild', () => {
afterEach(() => {
vi.mocked(build).mockReset()
srcFilesOrder.reverse = false
})

test('Generates a bundle for the Node runtime version specified in the `nodeVersion` config property', async () => {
Expand All @@ -38,4 +62,30 @@ describe('esbuild', () => {

expect(build).toHaveBeenCalledWith(expect.objectContaining({ target: ['node22'] }))
})

// Netlify content-addresses function uploads, so an unchanged function should
// produce a byte-identical zip and skip re-uploading. The order in which
// source files are discovered on disk is not stable across build environments,
// so the bundler must emit them in a deterministic order — otherwise the zip
// checksum changes on every build and dedup never hits. The `zisi` and `nft`
// bundlers already sort their `srcFiles` for this reason; this asserts esbuild
// does too. See `getSrcFiles` in `runtimes/node/bundlers/esbuild/index.ts`.
test('Produces a byte-identical zip regardless of the order in which source files are discovered', async () => {
const opts = {
archiveFormat: ARCHIVE_FORMAT.ZIP,
config: { '*': { nodeBundler: NODE_BUNDLER.ESBUILD, externalNodeModules: ['test'] } },
}

srcFilesOrder.reverse = false
const {
files: [first],
} = await zipFixture('node-module-and-local-imports', { opts })

srcFilesOrder.reverse = true
const {
files: [second],
} = await zipFixture('node-module-and-local-imports', { opts })

expect(await computeSha1(first.path)).toBe(await computeSha1(second.path))
})
})
Loading