diff --git a/packages/vite-plugin-commonjs/README.md b/packages/vite-plugin-commonjs/README.md index f4c4689..b8de688 100644 --- a/packages/vite-plugin-commonjs/README.md +++ b/packages/vite-plugin-commonjs/README.md @@ -30,6 +30,9 @@ export default { - `include: string[]` Dependencies that only need to be transform. +- `addNamedExports: boolean` + add named exports. + ### CommonJS module in node_modules ```js import { esbuildCommonjs } from '@originjs/vite-plugin-commonjs' diff --git a/packages/vite-plugin-commonjs/__tests__/__snapshots__/transform.spec.ts.snap b/packages/vite-plugin-commonjs/__tests__/__snapshots__/transform.spec.ts.snap new file mode 100644 index 0000000..40460dc --- /dev/null +++ b/packages/vite-plugin-commonjs/__tests__/__snapshots__/transform.spec.ts.snap @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`transform named exports 1`] = ` +"var __getOwnPropNames = Object.getOwnPropertyNames; +var __commonJS = (cb, mod) => function __require() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; +}; +var require_stdin = __commonJS({ + \\"\\"(exports, module) { + const a = \\"a\\"; + const obj = { + o1: 1, + o2: 2 + }; + module.exports = { + a, + b: \\"b\\", + ...obj + }; + exports.c = \\"c\\"; + } +}); + + var __named_exports_for_vite = require_stdin(); + + var __named_exports_for_vite__a = __named_exports_for_vite['a']; +var __named_exports_for_vite__b = __named_exports_for_vite['b']; +var __named_exports_for_vite__o1 = __named_exports_for_vite['o1']; +var __named_exports_for_vite__o2 = __named_exports_for_vite['o2']; +var __named_exports_for_vite__c = __named_exports_for_vite['c']; + + export {__named_exports_for_vite__a as a,__named_exports_for_vite__b as b,__named_exports_for_vite__o1 as o1,__named_exports_for_vite__o2 as o2,__named_exports_for_vite__c as c}; + + export default __named_exports_for_vite; + +" +`; diff --git a/packages/vite-plugin-commonjs/__tests__/transform.spec.ts b/packages/vite-plugin-commonjs/__tests__/transform.spec.ts index b83ee0c..9f7836b 100644 --- a/packages/vite-plugin-commonjs/__tests__/transform.spec.ts +++ b/packages/vite-plugin-commonjs/__tests__/transform.spec.ts @@ -1,4 +1,4 @@ -import { transformRequire, isCommonJS } from "../src/lib"; +import { transformRequire, isCommonJS, transformCommonJS } from "../src/lib"; test('transform require', () => { //general require @@ -67,6 +67,30 @@ test('isCommonJS', () => { expect(isCommonJS(`exports['some key'] = 1`)).toBeTruthy(); }); +test('transform named exports', () => { + + let code = ` + const a = 'a'; + + const obj = { + o1: 1, + o2: 2 + }; + + module.exports = { + a, + b: 'b', + ...obj + }; + + exports.c = 'c'; + `; + + const transformResult = transformCommonJS(code, true).code; + expect(transformResult).toMatch(/export {.*__named_exports_for_vite__a as a,.*}/); + expect(transformResult).toMatchSnapshot(); +}); + test('Both url and comments are present', () => { //singleline comments let code = `dosomething () { diff --git a/packages/vite-plugin-commonjs/package.json b/packages/vite-plugin-commonjs/package.json index f1815c7..ae1a1e4 100644 --- a/packages/vite-plugin-commonjs/package.json +++ b/packages/vite-plugin-commonjs/package.json @@ -24,6 +24,7 @@ }, "homepage": "https://github.com/originjs/vite-plugins/tree/main/packages/vite-plugin-commonjs", "dependencies": { + "cjs-esm-exports": "^0.6.1", "esbuild": "^0.14.14" }, "devDependencies": { diff --git a/packages/vite-plugin-commonjs/src/index.ts b/packages/vite-plugin-commonjs/src/index.ts index 0fba8e9..93557bc 100644 --- a/packages/vite-plugin-commonjs/src/index.ts +++ b/packages/vite-plugin-commonjs/src/index.ts @@ -1,5 +1,5 @@ -import { transformSync, TransformResult } from "esbuild"; -import { transformRequire, isCommonJS } from "./lib"; +import { TransformResult } from "esbuild"; +import { transformRequire, transformCommonJS, isCommonJS } from "./lib"; import * as fs from "fs"; import { Plugin } from "vite"; import createFilter from "./filter"; @@ -8,10 +8,11 @@ export type Options = { include?: string | string[] | undefined; exclude?: string | string[] | undefined; skipPreBuild?: boolean; + addNamedExports?: boolean; }; export function viteCommonjs( - options: Options = { skipPreBuild: false } + options: Options = { skipPreBuild: false, addNamedExports: false } ): Plugin { const filter = createFilter(options.include, options.exclude); return { @@ -28,7 +29,7 @@ export function viteCommonjs( let result = transformRequire(code, id); if (id.indexOf("/node_modules/.vite/") == -1 && isCommonJS(code)) { - return transformSync(result.code, { format: "esm" }); + return transformCommonJS(result.code, options.addNamedExports); } if (result.replaced) { diff --git a/packages/vite-plugin-commonjs/src/lib.ts b/packages/vite-plugin-commonjs/src/lib.ts index 83a3447..d431888 100644 --- a/packages/vite-plugin-commonjs/src/lib.ts +++ b/packages/vite-plugin-commonjs/src/lib.ts @@ -1,3 +1,6 @@ +import { parse as parseCjs } from 'cjs-esm-exports'; +import { transformSync } from 'esbuild'; + const commonJSRegex: RegExp = /\b(module\.exports|exports\.\w+|exports\s*=\s*|exports\s*\[.*\]\s*=\s*)/; const requireRegex: RegExp = /(? = exports.reduce( + (map: Record, key: string) => { + map[key] = `${namedKey}['${key}']`; + return map; + }, + {}, + ); + const namedKeys = Object.keys(namedExportsMap); + + const namedExportsCode = ` + var ${namedKey} = ${defaultExport}; + + ${namedKeys.map(key => { + return `var ${namedKey}__${key} = ${namedExportsMap[key]};` + }).join('\n')} + + export {${namedKeys.map(key => `${namedKey}__${key} as ${key}`).join(',')}}; + + export default ${namedKey}; + `; + + return { + ...transformResult, + code: esmCode.replace(defaultExportRegex, namedExportsCode), + }; +} + function removeComments( code: string, exp: RegExp, @@ -86,4 +137,4 @@ function isString(text: string) { } catch (err) { return false; } -} +} \ No newline at end of file