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
28 changes: 22 additions & 6 deletions src/date_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ export function __setDateFnsTzNull(): void {
dateFnsTzLoadAttempted = true;
}

// Declare webpack's special require function that bypasses bundling
// This is used to avoid webpack warnings for optional dependencies
declare const __non_webpack_require__: typeof require | undefined;

/**
* Attempts to load date-fns-tz module.
* Returns null if the module is not installed.
Expand All @@ -111,13 +115,25 @@ function getDateFnsTz(): DateFnsTz | null {
dateFnsTzLoadAttempted = true;

try {
// Dynamic require for date-fns-tz
// Use a variable to prevent webpack from statically analyzing the require
// and showing warnings when the optional dependency is not installed
// See: https://github.com/Hacker0x01/react-datepicker/issues/6154
const dateFnsTzModuleName = "date-fns-tz";
// Use __non_webpack_require__ to tell webpack to use native require
// and avoid bundling warnings for this optional dependency
// See: https://github.com/Hacker0x01/react-datepicker/issues/6181
//
// For Vite and other ESM-only bundlers, require is not available.
// In those environments, users need to configure their bundler to
// pre-bundle date-fns-tz or use the optimizeDeps option.
// See: https://github.com/Hacker0x01/react-datepicker/issues/6204
// eslint-disable-next-line @typescript-eslint/no-require-imports
dateFnsTz = require(dateFnsTzModuleName) as DateFnsTz;
const requireFn =
typeof __non_webpack_require__ !== "undefined"
? __non_webpack_require__
: typeof require !== "undefined"
? require
: /* istanbul ignore next - only executes in ESM-only environments like Vite */ null;

if (requireFn) {
dateFnsTz = requireFn("date-fns-tz") as DateFnsTz;
}
} catch {
/* istanbul ignore next - only executes when date-fns-tz is not installed */
dateFnsTz = null;
Expand Down
33 changes: 33 additions & 0 deletions src/test/timezone_test.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -761,3 +761,36 @@ describe("Timezone fallback behavior (when date-fns-tz is not installed)", () =>
consoleSpy.mockRestore();
});
});

describe("Webpack __non_webpack_require__ support", () => {
beforeEach(() => {
__resetDateFnsTzCache();
});

afterEach(() => {
// Clean up the global
// @ts-expect-error - cleaning up test global
delete globalThis.__non_webpack_require__;
__resetDateFnsTzCache();
});

it("should use __non_webpack_require__ when available in webpack environment", () => {
const testDate = new Date("2024-06-15T12:00:00Z");

// Simulate webpack environment by defining __non_webpack_require__
// @ts-expect-error - simulating webpack global
globalThis.__non_webpack_require__ = require;

// This should use __non_webpack_require__ and successfully load date-fns-tz
const result = toZonedTime(testDate, "America/New_York");

// Should convert the date (not return original), proving date-fns-tz loaded
expect(result).toBeInstanceOf(Date);
expect(result.getHours()).toBe(8); // 12:00 UTC = 08:00 EDT
});
});

// Note: The Vite ESM environment case (where require is not available) cannot be
// tested in Jest because require is always available in Node.js module scope.
// The code path is covered by an istanbul ignore comment and verified manually
// in actual Vite environments. See: https://github.com/Hacker0x01/react-datepicker/issues/6204
Loading