Description
Problem
When using gray-matter in an ESM project with Vite SSR (e.g., Astro), the module cannot be properly imported and called.
Environment
- Node.js version: v20+
- gray-matter version: 4.0.3
- Bundler: Vite 6.x (via Astro 5.16.0)
- Project type: ESM (
"type": "module" in package.json)
- TypeScript: 5.9.3
- tsconfig:
esModuleInterop: true, allowSyntheticDefaultImports: true
Error
TypeError: (0 , __vite_ssr_import_2__) is not a function
at parseFrontmatter (eval at runInlinedModule (.../vite/dist/node/module-runner.js:1062:11), <anonymous>:73:45)
Reproduction Steps
-
Create an ESM project with Vite or Astro:
-
Install gray-matter:
-
Import and use in a TypeScript file:
import * as matter from 'gray-matter';
// or
import matter from 'gray-matter';
const result = matter('---\ntitle: Test\n---\nContent');
console.log(result.data); // Expected: { title: 'Test' }
-
Run in Vite SSR mode:
Expected Behavior
The import should work and matter() should be callable as a function.
Actual Behavior
import matter from 'gray-matter' fails with TypeScript error: "module has no default export"
import * as matter from 'gray-matter' imports a namespace object where matter() is not callable at runtime
- The following workaround is required:
const fn = (matter as any).default || matter;
const result = fn(content);
Root Cause Analysis
The package only exports via CommonJS (module.exports = matter) with:
Missing:
- No
exports field for proper ESM support
- No
module field for bundlers
- No
.mjs entry point
The type definition uses export = matter which is the CommonJS-style export:
// gray-matter.d.ts line 114
export = matter
Suggested Fix
Add ESM support via the exports field in package.json:
{
"main": "index.js",
"module": "index.mjs",
"exports": {
".": {
"import": "./index.mjs",
"require": "./index.js",
"types": "./gray-matter.d.ts"
}
}
}
And create an ESM wrapper (index.mjs):
import matter from './index.js';
export default matter;
export const stringify = matter.stringify;
export const read = matter.read;
export const test = matter.test;
export const language = matter.language;
Update type definitions to support both:
// For ESM default import
declare const matter: MatterFunction;
export default matter;
// For named exports
export { stringify, read, test, language };
Current Workaround
import * as matter from 'gray-matter';
function parseFrontmatter(content: string) {
// With `import * as matter`, the function may be on matter.default
const parse = (matter as any).default || matter;
const result = parse(content);
return { meta: result.data, body: result.content };
}
Description
Problem
When using
gray-matterin an ESM project with Vite SSR (e.g., Astro), the module cannot be properly imported and called.Environment
"type": "module"in package.json)esModuleInterop: true,allowSyntheticDefaultImports: trueError
Reproduction Steps
Create an ESM project with Vite or Astro:
Install gray-matter:
Import and use in a TypeScript file:
Run in Vite SSR mode:
Expected Behavior
The import should work and
matter()should be callable as a function.Actual Behavior
import matter from 'gray-matter'fails with TypeScript error: "module has no default export"import * as matter from 'gray-matter'imports a namespace object wherematter()is not callable at runtimeRoot Cause Analysis
The package only exports via CommonJS (
module.exports = matter) with:{ "main": "index.js" }Missing:
exportsfield for proper ESM supportmodulefield for bundlers.mjsentry pointThe type definition uses
export = matterwhich is the CommonJS-style export:Suggested Fix
Add ESM support via the
exportsfield in package.json:{ "main": "index.js", "module": "index.mjs", "exports": { ".": { "import": "./index.mjs", "require": "./index.js", "types": "./gray-matter.d.ts" } } }And create an ESM wrapper (
index.mjs):Update type definitions to support both:
Current Workaround