tslib icon indicating copy to clipboard operation
tslib copied to clipboard

modules/index.js should re-export tslib.es6.js instead of tslib.js

Open schickling opened this issue 4 years ago • 22 comments

Unless I'm misunderstanding something, I'd expect modules/index.js to re-export ../tslib.es6.js instead of ../tslib.js.

https://github.com/microsoft/tslib/blob/master/modules/index.js#L1

I'm basing my statement on the understanding that exports['.']['import'] should point to some "modern" code:

https://github.com/microsoft/tslib/blob/master/package.json#L29-L34

(The reason I'm opening this issue is that I'm facing some problem in combination with Vite which is based on ESM.)

schickling avatar Jan 14 '21 19:01 schickling

@DanielRosenwasser would love an eye on this.

From Vite resolver's perspective, module is a non-standard condition in exports, so it resolves to the import condition... which points to an ESM file that imports a UMD file (!!!). This does work in Node.js because Node allows ESM to import commonjs files... however for a native-ESM dev server like Vite, it assumes entries specified by the import condition to only contain valid ESM all the way through.

On the other hand, why doesn't the import condition simply point to tslib.es6.js? What is the point of having the modules/index.js indirection?

This can be fixed on Vite's front by also checking the module condition in exports field, but that is technically non-standard :/

yyx990803 avatar Jan 20 '21 02:01 yyx990803

Any updates to this?

I'm currently trying to understand whats wrong, but I have this error in my sveltekit project:

 > .svelte-kit/output/server/app.js:26097:14: warning: Using direct eval with a bundler is not recommended and may cause problems (more info: https://esbuild.github.io/link/direct-eval)
    26097 │     var mod = eval("quire".replace(/^/, "re"))(moduleName);
          ╵               ~~~~

 > .svelte-kit/output/server/app.js:41:7: error: No matching export in "node_modules/tslib/modules/index.js" for import "default"
    41 │ import require$$0$4, { __extends, __assign, __values, __read, __awaiter, __generator, __spreadArray, __rest } from "tslib";
       ╵        ~~~~~~~~~~~~

> Build failed with 1 error:
.svelte-kit/output/server/app.js:41:7: error: No matching export in "node_modules/tslib/modules/index.js" for import "default"
Error: Build failed with 1 error:

wiesson avatar Sep 07 '21 12:09 wiesson

@wiesson Have you been able to figure this out yet? I'm getting the same error. Haven't been able to find anything that fixes it, include aliasing in svelte.config.js to tslib/tslib.es6.js.

milky2028 avatar Sep 28 '21 00:09 milky2028

@wiesson Have you been able to figure this out yet? I'm getting the same error. Haven't been able to find anything that fixes it, include aliasing in svelte.config.js to tslib/tslib.es6.js.

Unfortunately not :/ I'm also not sure, if its tslib itself or another extension. Somehow deleting .svelte-kit, node_modules and the lock file "solved" my problem without understanding why. But it sometimes occurs every now and then.

wiesson avatar Sep 28 '21 06:09 wiesson

Have the same problem with sveltekit build in adapter-vercel phase. I was able to narrow it done to one import that is causing this: import { serverTimestamp } from "firebase/firestore"; (Firestore 9) @wiesson's delete procedure did not help.

I hack-fixed this by running this script before executing npm run build:

import fs from 'fs'
try {
    const filePath = "node_modules/@firebase/firestore/package.json"
    fs.writeFileSync(filePath, fs.readFileSync(filePath, 'utf8').replace(
        `"node": "./dist/index.node.cjs.js",`, 
        `"node": "./dist/index.esm2017.js",`
    ))
    console.log("fixed vercel adapter")
} catch (err) {
    console.error("error: fixing vercel adapter", err)
}

samuba avatar Oct 02 '21 15:10 samuba

Have the same problem with sveltekit build phase adapter-vercel. I was able to narrow it done to one import that is causing this: import { serverTimestamp } from "firebase/firestore"; (Firestore 9) @wiesson's delete procedure did not help.

I hack-fixed this by running this script before executing npm run build:

import fs from 'fs'
try {
    const filePath = "node_modules/@firebase/firestore/package.json"
    fs.writeFileSync(filePath, fs.readFileSync(filePath, 'utf8').replace(
        `"node": "./dist/index.node.cjs.js",`, 
        `"node": "./dist/index.esm2017.js",`
    ))
    console.log("fixed vercel adapter")
} catch (err) {
    console.error("error: fixing vercel adapter", err)
}

This worked for me as well, although would love to see this fixed for real.

benterova avatar Oct 05 '21 05:10 benterova

I think this issue is related, isn't it? -> https://github.com/firebase/firebase-js-sdk/issues/5499

@evil-su, could you share your findings so that the firebase team could fix it? :)

wiesson avatar Oct 05 '21 18:10 wiesson

https://github.com/firebase/firebase-js-sdk/pull/5532/files

This looks promising 🎉

wiesson avatar Oct 05 '21 20:10 wiesson

Switching to use tslib.es6.js fails to run in the esm-node-native test case in the repo, happy to have a vite test case in here (we already have snowpack for example) but any changes should need to be backwards compatible .

orta avatar Oct 14 '21 07:10 orta

I had to do this for firestore/lite as well in order to get it to work.

import { readFile, writeFile } from 'fs/promises';

const importJson = async (path) => JSON.parse(await readFile(new URL(path, import.meta.url)));

const path = 'node_modules/@firebase/firestore/package.json';
const pkg = await importJson(path);
pkg.exports['.'].node = './dist/index.esm2017.js';
pkg.exports['./lite'].node = './dist/lite/index.browser.esm2017.js';

await writeFile(new URL(path, import.meta.url), JSON.stringify(pkg));

console.log('Successfully fixed imports.');

milky2028 avatar Oct 17 '21 15:10 milky2028

@orta,

Can we at least just change re-export to import * as tslib from '../tslib.js'; or smth like that? This fixes missed default export in esm mode (NODE_OPTIONS=--experimental-vm-modules)

SyntaxError: The requested module '../tslib.js' does not provide an export named 'default'

antongolub avatar Nov 03 '21 17:11 antongolub

same issue here: https://github.com/microsoft/tslib/issues/161

jogibear9988 avatar Nov 20 '21 16:11 jogibear9988

Have the same problem with sveltekit build in adapter-vercel phase. I was able to narrow it done to one import that is causing this: import { serverTimestamp } from "firebase/firestore"; (Firestore 9) @wiesson's delete procedure did not help.

I hack-fixed this by running this script before executing npm run build:

import fs from 'fs'
try {
    const filePath = "node_modules/@firebase/firestore/package.json"
    fs.writeFileSync(filePath, fs.readFileSync(filePath, 'utf8').replace(
        `"node": "./dist/index.node.cjs.js",`, 
        `"node": "./dist/index.esm2017.js",`
    ))
    console.log("fixed vercel adapter")
} catch (err) {
    console.error("error: fixing vercel adapter", err)
}

I've been getting the same issue with other packages when using sveltekit/vite - I've adapted your idea to fix it at the source by adding a default export to tslib.

This seems to fix things for me.

import fs from 'fs'
import path from 'path'

try {
  const filePath = path.resolve('./node_modules/tslib/modules/index.js')
  console.log('fixing tslib export', filePath)
  let file = fs.readFileSync(filePath, 'utf8')
  if (!file.includes('export default')) {
    file += '\nexport default tslib;\n'
  }
  fs.writeFileSync(filePath, file)
} catch (err) {
  console.error('error: fixing tslib export', err)
}

It's not ideal so I'd love to see this fixed on tslib's end or from sveltekit/vite (not too sure which one is causing the issue at hand)

noahbald avatar Nov 21 '21 01:11 noahbald

NodeJS does not consider tslib.es6.js to be an ES Module because it has a .js extension. tslib.es6.js predates NodeJS's ESM support and wasn't really designed for it. NodeJS does treat modules/index.js as an ES Module due to the package.json in that folder containing { "type": "module" }.

Rather than have modules/index.js contain a third copy of the helpers that we need to maintain, we chose to have it re-export an existing set of helpers. We can't re-export tslib.es6.js, since that would still be treated as a CommonJS module by Node and would error on the use of the export keyword. Instead we chose to re-export tslib.js, which is a valid CommonJS module.

The only alternative I can think of is to move the contents of tslib.es6.js into modules/index.js, and change tslib.es6.js to just export * from "./modules/index.js";. That keeps the duplication to a minimum as its still only two copies to maintain.

rbuckton avatar Feb 08 '22 18:02 rbuckton

Is this still an issue in Vite? I added a test locally using vite and it seems to import tslib just fine as is.

rbuckton avatar Feb 10 '22 20:02 rbuckton

I've added a test for [email protected] in #172 and I'm not seeing the error that's being described in this issue. @schickling (or anyone else experiencing this), can you review the PR and let me know if I'm missing something in that test that would help me reproduce the issue you are describing?

rbuckton avatar Feb 10 '22 20:02 rbuckton

If it helps, the use case that led me here was trying to work with Material Web Components, in my case was just testing out @material/mwc-button and using ESM from the browser via import map.

The dependency chain is pretty short:

  1. @material/mwc-button has a direct dependency on tslib
  2. To resolve tslib for ESM, you hit the issue here, either resolving exports or module in package.json (in my case I am following the export map)

thescientist13 avatar Feb 10 '22 20:02 thescientist13

If it helps, the use case that led me here was trying to work with Material Web Components, in my case was just testing out @material/mwc-button and using ESM from the browser via import map.

Would import maps give you the ability to remap tslib as well?

rbuckton avatar Feb 11 '22 18:02 rbuckton

Would import maps give you the ability to remap tslib as well?

Yes, if hand rolling the import map as the 1st party, this would be doable.

But similar to the Vite use case, the files to resolve (and the import map) are being determined programmatically, and so is entirely based on what the dependencies themselves define via their package.json. So this fix would be very useful to all ecosystem tools looking to operate against the spec in NodeJS.

thescientist13 avatar Feb 11 '22 20:02 thescientist13

If it helps, the use case that led me here was trying to work with Material Web Components, in my case was just testing out @material/mwc-button and using ESM from the browser via import map.

The dependency chain is pretty short:

  1. @material/mwc-button has a direct dependency on tslib
  2. To resolve tslib for ESM, you hit the issue here, either resolving exports or module in package.json (in my case I am following the export map)

Can you provide a more detailed repro?

rbuckton avatar Feb 18 '22 21:02 rbuckton

Yeah, you can see this branch where I am trying to integrate MWC and hitting this issue. Following the ESM spec would be great here, so thanks in advance for taking a look. 🙏

thescientist13 avatar Feb 20 '22 17:02 thescientist13

I had a related issue. In my case, my site is deployed on Netlify and I have a transient dependency on tslib from "@azure/ai-form-recognizer": "^5.0.0",.

After trying a bunch of different things that didn't work, I found this worked.

  1. Added an explicit import for tslib "tslib": "^2.6.2",

  2. added a fix (hack) script in my repo build_scripts/fix_tslib_node.mjs

import fs from 'fs'
try {
  const filePath = "node_modules/tslib/package.json"
  fs.writeFileSync(filePath, fs.readFileSync(filePath, 'utf8').replace(
    `"node": "./modules/index.js",`,
    `"node": "./tslib.es6.mjs",`
  ))
  console.log("node setting for tslib fixed (hacked)")
} catch (err) {
  console.error("error: fixing node setting for tslib", err)
}
  1. changed Build and Deployment -> Continuous Deployment -> Build Settings -> Build command node build_scripts/fix_tslib_node.mjs && npm run build

JavascriptMick avatar Dec 11 '23 13:12 JavascriptMick