Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added proper support for ES module exports (with some fixes for NodeJS context) #613

Merged
merged 15 commits into from
Feb 6, 2023

Conversation

timocov
Copy link
Contributor

@timocov timocov commented Nov 12, 2020

Type of PR: enhancement

PR checklist:

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 timocov added the breaking change Changes the API in a non backwards compatible way. label Nov 12, 2020
@timocov timocov added this to the 4.0 milestone Nov 13, 2020
@cipriancaba
Copy link

Hey @timocov Do you have any updates on this?

@timocov
Copy link
Contributor Author

timocov commented Apr 12, 2021

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

@cipriancaba
Copy link

Appreciate the update

@timocov timocov mentioned this pull request May 21, 2021
3 tasks
@zouxuoz
Copy link

zouxuoz commented Sep 27, 2021

@timocov tradingview/fancy-canvas#7 merged, can we merge this PR too?

@timocov
Copy link
Contributor Author

timocov commented Sep 28, 2021

@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.

@zouxuoz
Copy link

zouxuoz commented Sep 28, 2021

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

@Zidious
Copy link

Zidious commented Feb 26, 2022

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

@timocov
Copy link
Contributor Author

timocov commented Mar 1, 2022

@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 timocov force-pushed the cjs-and-ssr branch 2 times, most recently from 02062bc to 8f200cc Compare March 3, 2022 15:17
…n nodejs context

It's the case to handle that the library might be used with SSR
@timocov
Copy link
Contributor Author

timocov commented Mar 3, 2022

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
Copy link
Contributor Author

timocov commented Dec 29, 2022

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 timocov marked this pull request as ready for review December 29, 2022 18:49
@SlicedSilver
Copy link
Contributor

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!

🎉

romfrancois
romfrancois previously approved these changes Jan 16, 2023
package.json Show resolved Hide resolved
BUILDING.md Show resolved Hide resolved
package.json Show resolved Hide resolved
`npm run verify` needed to be changed so that the build script is finished before eslint starts else there will be an error reported within `import-lightweight-charts-version.ts`
@Nipheris Nipheris changed the title Added CJS module to be able being usable in SSR (NodeJS) context Added proper support for ES module exports (with some fixes for NodeJS context) Jan 16, 2023
@SlicedSilver
Copy link
Contributor

@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
Copy link
Contributor

  • 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.

@timocov
Copy link
Contributor Author

timocov commented Jan 28, 2023

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 😉

@SlicedSilver
Copy link
Contributor

SlicedSilver commented Jan 29, 2023

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.

@timocov
Copy link
Contributor Author

timocov commented Jan 29, 2023

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 😂 🤐

.size-limit.js Outdated Show resolved Hide resolved
Copy link
Contributor

@Nipheris Nipheris left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! Maybe we could also improve Installing section in README.md, to be clear about available alternatives. To summarize, now we have the following:

ES module CommonJS IIFE (window.LightweightCharts)
Deps NOT included PROD production.mjs production.cjs N/A
Deps NOT included DEV development.mjs development.cjs N/A
Deps included (standalone) PROD standalone.production.mjs - standalone.production.js
Deps included (standalone) DEV standalone.development.mjs - standalone.development.js

@SlicedSilver SlicedSilver merged commit 4bd4ba5 into master Feb 6, 2023
@SlicedSilver SlicedSilver deleted the cjs-and-ssr branch February 6, 2023 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change Changes the API in a non backwards compatible way.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

DOCS: How to use in SSR context Added test to check that the library importable in server-side context
7 participants