amzn / style-dictionary

A build system for creating cross-platform styles.
https://styledictionary.com
Apache License 2.0
3.87k stars 543 forks source link

ESM/CJS interop #978

Closed azan-n closed 1 year ago

azan-n commented 1 year ago

I have style-dictionary project with the following configuration:

module.exports = {
  "source": [
    "tokens/**/*.js"
  ],
  "platforms": {
    "scss": {
      "transformGroup": "scss",
      "buildPath": "build/scss/",
      "files": [
        {
          "destination": "_variables.scss",
          "format": "scss/variables"
        }
      ]
    },
    "css": {
      "transformGroup": "css",
      "buildPath": "build/css/",
      "files": [
        {
          "format": "css/variables",
          "destination": "variables.css"
        }
      ]
    },
    "esm": {
      "transformGroup": "js",
      "buildPath": "build/esm/",
      "files": [
        {
          "format": "javascript/es6",
          "destination": "variables.mjs"
        },
        {
          "format": "typescript/es6-declarations",
          "destination": "variables.d.mts"
        }
      ]
    },
    "cjs": {
      "transformGroup": "js",
      "buildPath": "build/cjs/",
      "files": [
        {
          "format": "javascript/module",
          "destination": "variables.cjs"
        },
        {
          "format": "typescript/module-declarations",
          "destination": "variables.d.cts"
        }
      ]
    }
  }
}

Subsequently, I've set up the package.json as follows:

{
  ...
  "module": "build/esm/variables.mjs",
  "main": "build/cjs/variables.cjs",
  "exports": {
    ".": {
      "import": {
        "types": "./build/esm/variables.d.mts",
        "default": "./build/esm/variables.mjs"
      },
      "require": {
        "types": "./build/cjs/variables.d.cts",
        "default": "./build/cjs/variables.cjs"
      }
    }
  },
  "sass": "./build/scss/_variables.scss",
  "style": "./build/css/variables.css",
   ...
 }

I am exporting only for the web and will need to use the tokens in both CJS environments (like a tailwind.config.js), and within ESM code (like a component with dynamic colour changes).

Currently, I import the tokens in projects which are bound to using moduleResolution: "node" in the tsconfig.json which is probably why the packagejson.exports is not working correctly. Is there a way I could export a package with ESM/CJS interop?

chazzmoney commented 1 year ago

This isn't really an SD thing, but a challenge generally within the current JS world. Here are some relevant pages on the subject:

https://www.sensedeep.com/blog/posts/2021/how-to-create-single-source-npm-module.html https://antfu.me/posts/publish-esm-and-cjs https://github.com/johnloy/esm-commonjs-interop-manual