lightweight-charts icon indicating copy to clipboard operation
lightweight-charts copied to clipboard

Added CJS module to be able being usable in SSR (NodeJS) context

Open timocov opened this issue 4 years ago • 9 comments

Type of PR: enhancement

PR checklist:

  • [x] Addresses an existing issue: fixes #543, fixes #488
  • [x] Includes tests
  • [x] Documentation update

Overview of changes:

This PR includes a test in CI to make sure that you're able to import lightweight-charts package in NodeJS context, exports map in package.json (including different files for dev/prod builds 🎉 - now it should work out of the box almost for everybody), the published package.json file will have "type": "module".

timocov avatar Nov 12 '20 18:11 timocov

Hey @timocov Do you have any updates on this?

cipriancaba avatar Apr 08 '21 14:04 cipriancaba

@cipriancaba not yet, we're waiting for changes in fancy-canvas library so it will be able to be imported in SSR. cc @Nipheris

timocov avatar Apr 12 '21 16:04 timocov

Appreciate the update

cipriancaba avatar Apr 13 '21 07:04 cipriancaba

@timocov https://github.com/tradingview/fancy-canvas/pull/7 merged, can we merge this PR too?

zouxuoz avatar Sep 27 '21 09:09 zouxuoz

@zouxuoz this PR leads for breaking change in the package so we cannot merge right now since we're preparing the next minor update for the library. I think after this version we can start to prepare the next major version with all breaking change we're going to do.

timocov avatar Sep 28 '21 10:09 timocov

@timocov do you have ETA for it? 😔 can I help?

zouxuoz avatar Sep 28 '21 20:09 zouxuoz

Hey @timocov,

Hope all is well,

I saw your comment here: https://stackoverflow.com/a/65230044 in regards to the below error in a nodeJS context:

import { bindToDevicePixelRatio } from 'fancy-canvas/coordinate-space';
^^^^^^

SyntaxError: Cannot use import statement outside a module

I was wondering if there is any update to this at all? Specifically, being able to create charts and save image to file.

Thank you in advance,

Gabe

Zidious avatar Feb 26 '22 00:02 Zidious

@Zidious we're planning to fix the issue in v4. We didn't do it before because it might be a breaking change for users.

timocov avatar Mar 01 '22 09:03 timocov

It seems that in fancy-canvas we have a bug that it's impossible to import it in modules.

To merge this branch we're waiting for:

  • a fix for the issue above
  • upgrading fancy-canvas to the next major version

timocov avatar Mar 03 '22 15:03 timocov

I believe this PR is ready to be rebased and updated accordingly the latest changes regarding the docs (but I have no access to the branch anymore so fyi lwc maintainers).

timocov avatar Dec 29 '22 18:12 timocov

FYI: Results of running publint.

npm run prepare-release
npx publint

Master

lightweight-charts lint results:
Suggestions:
1. pkg.module is used to output ESM, but pkg.exports is not defined. As NodeJS doesn't read pkg.module, the ESM output may be skipped. Consider adding pkg.exports to export the ESM output. pkg.module can usually be removed alongside too. (This will be a breaking change)
Warnings:
1. /dist/lightweight-charts.esm.production.js is written in ESM, but is interpreted as CJS. Consider using the .mjs extension, e.g. /dist/lightweight-charts.esm.production.mjs
2. /dist/lightweight-charts.esm.development.js is written in ESM, but is interpreted as CJS. Consider using the .mjs extension, e.g. /dist/lightweight-charts.esm.development.mjs

This PR

lightweight-charts lint results:
All good!

🎉

SlicedSilver avatar Jan 15 '23 18:01 SlicedSilver

@Nipheris I've added back index.cjs. It's specified as the main key on the package.json as a fallback for older versions of node, and under the "require" sections of "exports". This prevent the PR being a breaking change for users of require.

SlicedSilver avatar Jan 23 '23 18:01 SlicedSilver

  • Added cjs builds (thanks @Nipheris), and added a standalone esm version.

The standalone esm version would allows users to use the import syntax directly in the browser without a build step. For example:

<script type="module">
    import { createChart } from './dist/lightweight-charts.standalone-esm.production.js';
    // or import { createChart } from 'https://unpkg.com/lightweight-charts/dist/lightweight-charts.standalone-esm.production.js';

    var chart = createChart(document.getElementById('container'));
   // ...
</script>

  • Removed "type": "module" from the generated package.json because we are using the cjs as the "main" entry point. Older versions of node and bundlers will use this as the fallback while the newer versions will use the values defined in the exports field.

SlicedSilver avatar Jan 27 '23 14:01 SlicedSilver

Older versions of node and bundlers will use this as the fallback while the newer versions will use the values defined in the exports field.

Tbh from my perspective I don't think you need to even handle this case - nodejs supports modules since v16 (right?) which is current LTS (nodejs 14 will shut down in 2 months https://nodejs.dev/en/about/releases/), all modern bundles should support exports map or some sort of. Looks like unnecessary work for you :) But it is up to you ofc 😉

timocov avatar Jan 28 '23 12:01 timocov

Older versions of node and bundlers will use this as the fallback while the newer versions will use the values defined in the exports field.

Tbh from my perspective I don't think you need to even handle this case - nodejs supports modules since v16 (right?) which is current LTS (nodejs 14 will shut down in 2 months https://nodejs.dev/en/about/releases/), all modern bundles should support exports map or some sort of. Looks like unnecessary work for you :) But it is up to you ofc 😉

In this case, it was very little effort to add the cjs support and there doesn't appear to any downside to providing the additional builds. The main concern was whether any of these changes would cause an unnecessary breaking change so we are perhaps erring on the side of caution here.

Whilst we do specify node 16 in the "engines" section of the package.json, it is advisory only and will only produce warnings so it is likely that some of the users of this package are actually on older versions of node and having this fallback might be a 'nice' thing and potentially allow more people to use the library (and maybe result in few issues raised).

@timocov Obviously we value your opinion and if you think it would be better to exclude these builds and fallback then we take another look at this.

SlicedSilver avatar Jan 29 '23 19:01 SlicedSilver

Whilst we do specify node 16 in the "engines" section of the package.json, it is advisory only and will only produce warnings

Afaik it is removed from published package.json file as the main purpose of lightweight-charts package is (was?) to be bundled or shipped for browsers i.e. it doesn't matter what nodejs version you use to build your app. But having engines in package.json in the repo specifies what nodejs should be used to build and ship this lightweight-charts package as there are dependencies with specific requirements and scripts that are using version-specific API (like in tests).

whether any of these changes would cause an unnecessary breaking change

Adding exports in package.json is a breaking change already as it will affect modules resolution in consumer's builds. My original idea for this PR "to make it right once" and not to maintain old redundant stuff (like module field which is not even part of standard) and forget about these bad days 😂 I noticed that some time ago lots of packages started to migrate from "commonjs only" or "dual esm+cjs" publishing towards "esm only" and it seems to work for them and probably it could help the whole ecosystem to migrate to esm quickly. I cannot provide examples of big enough packages (or even "widely used" ones) that are esm-only now, but you can take a look at https://github.com/ai/nanoid for instance.

Another thought was that this package was (still is?) unusable in nodejs context at all as it requires lots of browser-specific API. The only purpose of having it passing "being imported in nodejs" is to make SSR happy that is widely used by some frameworks. But they cannot use this package now in SSR because of issues anyway. And most likely these frameworks require modern-enough nodejs for work anyway or process imported files differently without relying on pure nodejs require/import mechanism (e.g. as they need to handle imports of css modules as well as others). And keep in mind that nodejs 14 is LTS for 2 months since now and I assume maintainers of other packages/frameworks might start to migrate their min nodejs versions to 16.

But obviously it requires having an understanding of your customers and whether you can or cannot drop cjs support for them in the next major release, which I cannot have unlike you.

having this fallback might be a 'nice' thing and potentially allow more people to use the library (and maybe result in few issues raised).

Yes, this is very fair point 👍


@SlicedSilver And please don't consider any of my words as nothing more as just an opinion of another random from the Internet. I'm not a maintainer anymore and out of context for a long time and I'm not in position to tell you what to do. And obviously I don't want you to change your mind 🙂 At the end you'll be maintaining this project after any merged changes 😂

At this point I'm shutting up in this thread 😂 🤐

timocov avatar Jan 29 '23 20:01 timocov