rolldown-plugin-require-cjs 0.1.5 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,6 +18,44 @@ See more: https://x.com/sanxiaozhizi/status/1968580207322808812
18
18
  npm i rolldown-plugin-require-cjs
19
19
  ```
20
20
 
21
+ ## Options
22
+
23
+ ```ts
24
+ export interface Options {
25
+ include?: Array<string | RegExp> | string | RegExp
26
+ exclude?: Array<string | RegExp> | string | RegExp
27
+ order?: 'pre' | 'post' | undefined
28
+ /**
29
+ * A function to determine whether a module should be transformed.
30
+ * Return `true` to force transformation, `false` to skip transformation,
31
+ * or `undefined` to let the plugin decide automatically.
32
+ */
33
+ shouldTransform?: string[] | TransformFn
34
+ /**
35
+ * Whether to transform Node.js built-in modules (e.g., `fs`, `path`)
36
+ * to `process.getBuiltinModule()` calls, which has the best performance.
37
+ *
38
+ * Note: `process.getBuiltinModule` is available since Node.js 20.16.0 and 22.3.0.
39
+ */
40
+ builtinNodeModules?: boolean
41
+ }
42
+
43
+ /**
44
+ * @returns A boolean or a promise that resolves to a boolean,
45
+ * or `undefined` to let the plugin decide automatically.
46
+ */
47
+ export type TransformFn = (
48
+ /**
49
+ * The module ID (path) being imported.
50
+ */
51
+ id: string,
52
+ /**
53
+ * The module ID (path) of the importer.
54
+ */
55
+ importer: string,
56
+ ) => Awaitable<boolean | undefined | void>
57
+ ```
58
+
21
59
  ## Example
22
60
 
23
61
  ```ts
package/dist/index.d.ts CHANGED
@@ -3,6 +3,10 @@ import { Plugin } from "rolldown";
3
3
  //#region src/options.d.ts
4
4
  type FilterPattern = Array<string | RegExp> | string | RegExp;
5
5
  type Awaitable<T> = T | Promise<T>;
6
+ /**
7
+ * @returns A boolean or a promise that resolves to a boolean,
8
+ * or `undefined` to let the plugin decide automatically.
9
+ */
6
10
  type TransformFn = (id: string, importer: string) => Awaitable<boolean | undefined | void>;
7
11
  interface Options {
8
12
  include?: FilterPattern;
@@ -12,12 +16,15 @@ interface Options {
12
16
  * A function to determine whether a module should be transformed.
13
17
  * Return `true` to force transformation, `false` to skip transformation,
14
18
  * or `undefined` to let the plugin decide automatically.
15
- *
16
- * @param id The module ID (path) being imported.
17
- * @param importer The module ID (path) of the importer.
18
- * @returns A boolean or a promise that resolves to a boolean, or `undefined`.
19
19
  */
20
20
  shouldTransform?: string[] | TransformFn;
21
+ /**
22
+ * Whether to transform Node.js built-in modules (e.g., `fs`, `path`)
23
+ * to `process.getBuiltinModule()` calls, which has the best performance.
24
+ *
25
+ * Note: `process.getBuiltinModule` is available since Node.js 20.16.0 and 22.3.0.
26
+ */
27
+ builtinNodeModules?: boolean;
21
28
  }
22
29
  type Overwrite<T, U> = Pick<T, Exclude<keyof T, keyof U>> & U;
23
30
  type OptionsResolved = Overwrite<Required<Options>, Pick<Options, "order"> & {
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createRequire } from "node:module";
1
+ import { builtinModules, createRequire } from "node:module";
2
2
  import { readFile } from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { init, parse } from "cjs-module-lexer";
@@ -21,7 +21,8 @@ function resolveOptions(options) {
21
21
  include: options.include || [/\.[cm]?[jt]sx?$/],
22
22
  exclude: options.exclude || [/node_modules/, /\.d\.[cm]?ts$/],
23
23
  order: "order" in options ? options.order : "pre",
24
- shouldTransform: options.shouldTransform
24
+ shouldTransform: options.shouldTransform,
25
+ builtinNodeModules: !!options.builtinNodeModules
25
26
  };
26
27
  }
27
28
 
@@ -29,12 +30,14 @@ function resolveOptions(options) {
29
30
  //#region src/index.ts
30
31
  let initted = false;
31
32
  function RequireCJS(userOptions = {}) {
32
- const { include, exclude, order, shouldTransform } = resolveOptions(userOptions);
33
+ const { include, exclude, order, shouldTransform, builtinNodeModules } = resolveOptions(userOptions);
33
34
  return {
34
35
  name: "rolldown-plugin-require-cjs",
35
36
  async buildStart() {
36
- await init();
37
- initted = true;
37
+ if (!initted) {
38
+ await init();
39
+ initted = true;
40
+ }
38
41
  },
39
42
  options(options) {
40
43
  if (options.platform !== "node") this.error("`rolldown-plugin-require-cjs` plugin is designed only for the Node.js environment. Please make sure to set `platform: \"node\"` in the options.");
@@ -58,11 +61,13 @@ function RequireCJS(userOptions = {}) {
58
61
  for (const stmt of body) if (stmt.type === "ImportDeclaration") {
59
62
  if (stmt.importKind === "type") continue;
60
63
  const source = stmt.source.value;
61
- const resolution = await this.resolve(source, id);
64
+ const isBuiltinModule = builtinNodeModules && (builtinModules.includes(source) || source.startsWith("node:"));
65
+ const resolution = isBuiltinModule ? null : await this.resolve(source, id);
62
66
  if (resolution && resolution.external === false) continue;
63
- if (!(await shouldTransform?.(source, id) ?? await isPureCJS(source, id))) continue;
67
+ if (!(isBuiltinModule || (await shouldTransform?.(source, id) ?? await isPureCJS(source, id)))) continue;
64
68
  if (stmt.specifiers.length === 0) {
65
- s.overwriteNode(stmt, `require(${s.sliceNode(stmt.source)});`);
69
+ if (isBuiltinModule) s.removeNode(stmt);
70
+ else s.overwriteNode(stmt, `require(${s.sliceNode(stmt.source)});`);
66
71
  continue;
67
72
  }
68
73
  const mapping = {};
@@ -73,7 +78,7 @@ function RequireCJS(userOptions = {}) {
73
78
  if (specifier.importKind === "type") continue;
74
79
  mapping[s.sliceNode(specifier.imported)] = s.sliceNode(specifier.local);
75
80
  } else defaultId = s.sliceNode(specifier.local);
76
- const requireCode = `require(${s.sliceNode(stmt.source)})`;
81
+ const requireCode = isBuiltinModule ? `process.getBuiltinModule(${s.sliceNode(stmt.source)})` : `require(${s.sliceNode(stmt.source)})`;
77
82
  let str = "";
78
83
  if (namespaceId) defaultId ||= `_cjs_${namespaceId}_default`;
79
84
  if (defaultId) str += `const ${defaultId} = ${requireCode};`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rolldown-plugin-require-cjs",
3
- "version": "0.1.5",
3
+ "version": "0.2.0",
4
4
  "description": "Transform ESM imports to CJS requires when the imported module is pure CJS.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -38,16 +38,16 @@
38
38
  },
39
39
  "devDependencies": {
40
40
  "@babel/parser": "^7.28.4",
41
- "@sxzz/eslint-config": "^7.1.4",
41
+ "@sxzz/eslint-config": "^7.2.1",
42
42
  "@sxzz/prettier-config": "^2.2.4",
43
43
  "@sxzz/test-utils": "^0.5.11",
44
- "@types/node": "^24.4.0",
44
+ "@types/node": "^24.5.2",
45
45
  "bumpp": "^10.2.3",
46
- "eslint": "^9.35.0",
46
+ "eslint": "^9.36.0",
47
47
  "eslint-plugin-vue": "^10.5.0",
48
48
  "prettier": "^3.6.2",
49
- "rolldown": "1.0.0-beta.38",
50
- "tsdown": "^0.15.1",
49
+ "rolldown": "1.0.0-beta.39",
50
+ "tsdown": "^0.15.4",
51
51
  "typescript": "^5.9.2",
52
52
  "vitest": "^3.2.4"
53
53
  },