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

Add exportmaps for lib/* entrypoints to allow for CDNs to use roughly what they need. #62

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

KonnorRogers
Copy link

It seems that Lowlight is written with Bundlers in mind to treeshake. However, if someone is using a CDN, or is using a bundler which does not support tree-shaking re-exported namespaces, then they have to pull in every single language from highlight.js

I would like to propose that the entrypoints in ./lib/*.js be exposed for consumption as a "quasi-treeshaking" mechanism as proposed in this PR.

I did try to use esm.sh 's treeshaking mechanism:

import { createLowlight, common } from "https://esm.sh/lowlight@3?exports=createLowlight,common";

But it made no difference in size. My guess is that this doesnt work because esm.sh uses ESBuild, and ESBuild will not treeshake re-exported namespaces:

evanw/esbuild#1420

Which is what ./index.js is doing.

Anyways, I hope you'll consider this PR so that more people can use lowlight :)

@wooorm
Copy link
Owner

wooorm commented Feb 12, 2025

Hi!

CDN

ESM is also made with this in mind right? Weren’t browsers supposed to lex files and exclude what is not imported?

ESBuild

a) it reads like that issue describes a “workaround” too? That is to say, ESBuild has problems with different levels, not with top-level?
b) “it made no difference in size” reads even more as if things or thoroughly broken in esbuild, as apparently it is including all grammars?

Hmm, but looking at https://github.com/wooorm/lowlight/blob/main/index.js, it does export symbols from places? And it does not seem to do what the linked esbuild issue is about? That Y is put into an object which is exposed but that the field on that object is later not used?


Sounds like you are running into some other bug? Is your problem perhaps esmsh specific?

@KonnorRogers
Copy link
Author

ESM is also made with this in mind right? Weren’t browsers supposed to lex files and exclude what is not imported?

To my knowledge, no browser actually does this, even though they could.

Sounds like you are running into some other bug? Is your problem perhaps esmsh specific?

Yes and no. ESM.sh offers a way to try to treeshake, but is unable to for some reason. I wouldnt consider it a bug because every bundler has different semantics for what's considered treeshakeable, and clearly ESBuild is determining it's not treeshakeable (I could probably put together a Vite / ESBuild project to see if it treeshakeable there or not)

however , every other CDN will not even attempt to treeshake, so for people not using esm.sh they will have to import the entire library no matter what and cannot use the "lib/" files to selectively import only what they need.

@wooorm
Copy link
Owner

wooorm commented Feb 14, 2025

I cannot reproduce the problems you describe with esbuild:

example.js

import {common} from 'lowlight'

console.log(common)

…then running:

./node_modules/.bin/esbuild example.mjs --bundle

…does not include abnf or zephir. This matches what I thought before: the referenced esbuild bug shows a pattern that is not present in the code here. That pattern is indeed complex, the code here is more simple.

Whereas, through esmsh:

index.html:

<!doctype html>
<html lang=en>
<title>Example</title>
<script type=module>
import {common} from 'https://esm.sh/lowlight@3?exports=common'

console.log(common)
</script>

…then opening that in a browser (Safari), does connect to the abnf and zephir grammars. Which is likely a bug in esmsh.

@ije do you think this is a bug in esmsh? That the index.html above does not pick only common but also includes all (and everything it needs)?

@ije
Copy link

ije commented Feb 14, 2025

it does only export the common var, however seems the tree-shaking is not applied. i will look into it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants