Skip to content

Commit

Permalink
feat(commonjs): add named exports option
Browse files Browse the repository at this point in the history
  • Loading branch information
miomio-xiao committed May 16, 2022
1 parent 70ae949 commit db0990e
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 6 deletions.
3 changes: 3 additions & 0 deletions packages/vite-plugin-commonjs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// 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({
\\"<stdin>\\"(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();
export var a = __named_exports_for_vite['a'];
export var b = __named_exports_for_vite['b'];
export var o1 = __named_exports_for_vite['o1'];
export var o2 = __named_exports_for_vite['o2'];
export var c = __named_exports_for_vite['c'];
export default __named_exports_for_vite;
"
`;
26 changes: 25 additions & 1 deletion packages/vite-plugin-commonjs/__tests__/transform.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { transformRequire, isCommonJS } from "../src/lib";
import { transformRequire, isCommonJS, transformCommonJS } from "../src/lib";

test('transform require', () => {
//general require
Expand Down Expand Up @@ -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 var a = .*/);
expect(transformResult).toMatchSnapshot();
});

test('Both url and comments are present', () => {
//singleline comments
let code = `dosomething () {
Expand Down
1 change: 1 addition & 0 deletions packages/vite-plugin-commonjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
9 changes: 5 additions & 4 deletions packages/vite-plugin-commonjs/src/index.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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 {
Expand All @@ -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) {
Expand Down
42 changes: 41 additions & 1 deletion packages/vite-plugin-commonjs/src/lib.ts
Original file line number Diff line number Diff line change
@@ -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 = /(?<!\.)\b_{0,2}require\s*\(\s*(["'].*?["'])\s*\)/g;
const IMPORT_STRING_PREFIX: String = "__require_for_vite";
Expand Down Expand Up @@ -50,6 +53,43 @@ export function isCommonJS(code: string): boolean {
return commonJSRegex.test(code);
}

export function transformCommonJS(code: string, addNamedExports = false) {
const transformResult = transformSync(code, { format: "esm" });

if (!addNamedExports) {
return transformResult;
}

const esmCode = transformResult.code;
const defaultExportRegex = /export default (.*?);/;
const defaultExport = esmCode.match(defaultExportRegex)?.[1];

if (!defaultExport) {
return transformResult;
}

const { exports } = parseCjs('', code);
if (!exports || !exports.length) {
return transformResult;
}

const namedKey = '__named_exports_for_vite';
const namedExportsCode = `
var ${namedKey} = ${defaultExport};
${exports.map((key: string) => {
return `export var ${key} = ${namedKey}['${key}'];`;
}).join('\n')}
export default ${namedKey};
`;

return {
...transformResult,
code: esmCode.replace(defaultExportRegex, namedExportsCode),
};
}

function removeComments(
code: string,
exp: RegExp,
Expand Down Expand Up @@ -86,4 +126,4 @@ function isString(text: string) {
} catch (err) {
return false;
}
}
}

0 comments on commit db0990e

Please sign in to comment.