Closed etrepum closed 2 months ago
The latest updates on your projects. Learn more about Vercel for Git ↗︎
Name | Status | Preview | Comments | Updated (UTC) |
---|---|---|---|---|
lexical | ✅ Ready (Inspect) | Visit Preview | 💬 Add feedback | Mar 14, 2024 0:17am |
lexical-playground | ✅ Ready (Inspect) | Visit Preview | 💬 Add feedback | Mar 14, 2024 0:17am |
but it seemed that terser was more popular for this use case so I gave that a shot and it compiled straight away.
Any noticeable impact on bundle size? Seems like the size check action failed on permissions maybe.
A possibly questionable move here was to do a small bit of automated refactoring of package.json files with npm run update-version to add the metadata so that bundlers can (hopefully) find the correct version to use.
This seems fine to me, if its neccessary and it works. Alternatively we could break it out into a separate script, but I dunno if I see the point.
The difference seems negligible, in total it's actually a few bytes smaller?
❯ for fn in packages/*/dist/*.esm.js; do printf "%s\t%s\t%s\n" $(cat "${fn%.esm.js}.js" | wc -c) $(cat "$fn" | wc -c) "$fn"; done | awk '{closure+=$1; esm+=$2;} END { print closure, esm, (100*esm/clos
ure) }'
335459 335412 99.986
4500 | 4518 | lexical-clipboard/dist/LexicalClipboard.esm.js |
14994 | 13823 | lexical-code/dist/LexicalCode.esm.js |
1053 | 1100 | lexical-dragon/dist/LexicalDragon.esm.js |
1142 | 1193 | lexical-file/dist/LexicalFile.esm.js |
894 | 891 | lexical-hashtag/dist/LexicalHashtag.esm.js |
541 | 547 | lexical-headless/dist/LexicalHeadless.esm.js |
3700 | 3662 | lexical-history/dist/LexicalHistory.esm.js |
2266 | 2360 | lexical-html/dist/LexicalHtml.esm.js |
4628 | 4681 | lexical-link/dist/LexicalLink.esm.js |
12921 | 12972 | lexical-list/dist/LexicalList.esm.js |
3083 | 3092 | lexical-mark/dist/LexicalMark.esm.js |
12071 | 12228 | lexical-markdown/dist/LexicalMarkdown.esm.js |
3874 | 4070 | lexical-offset/dist/LexicalOffset.esm.js |
908 | 900 | lexical-overflow/dist/LexicalOverflow.esm.js |
4923 | 3813 | lexical-plain-text/dist/LexicalPlainText.esm.js |
2256 | 2262 | lexical-react/dist/LexicalAutoEmbedPlugin.esm.js |
558 | 565 | lexical-react/dist/LexicalAutoFocusPlugin.esm.js |
4289 | 4415 | lexical-react/dist/LexicalAutoLinkPlugin.esm.js |
1581 | 1606 | lexical-react/dist/LexicalBlockWithAlignableContents.esm.js |
3539 | 3697 | lexical-react/dist/LexicalCharacterLimitPlugin.esm.js |
3252 | 3192 | lexical-react/dist/LexicalCheckListPlugin.esm.js |
791 | 801 | lexical-react/dist/LexicalClearEditorPlugin.esm.js |
1371 | 1514 | lexical-react/dist/LexicalClickableLinkPlugin.esm.js |
958 | 955 | lexical-react/dist/LexicalCollaborationContext.esm.js |
4285 | 4300 | lexical-react/dist/LexicalCollaborationPlugin.esm.js |
1452 | 1502 | lexical-react/dist/LexicalComposer.esm.js |
855 | 855 | lexical-react/dist/LexicalComposerContext.esm.js |
1587 | 1594 | lexical-react/dist/LexicalContentEditable.esm.js |
6641 | 6594 | lexical-react/dist/LexicalContextMenuPlugin.esm.js |
614 | 604 | lexical-react/dist/LexicalDecoratorBlockNode.esm.js |
420 | 413 | lexical-react/dist/LexicalEditorRefPlugin.esm.js |
1997 | 1962 | lexical-react/dist/LexicalErrorBoundary.esm.js |
6974 | 4154 | lexical-react/dist/LexicalHashtagPlugin.esm.js |
633 | 624 | lexical-react/dist/LexicalHistoryPlugin.esm.js |
1843 | 1895 | lexical-react/dist/LexicalHorizontalRuleNode.esm.js |
737 | 779 | lexical-react/dist/LexicalHorizontalRulePlugin.esm.js |
1234 | 1235 | lexical-react/dist/LexicalLinkPlugin.esm.js |
1074 | 1034 | lexical-react/dist/LexicalListPlugin.esm.js |
847 | 877 | lexical-react/dist/LexicalMarkdownShortcutPlugin.esm.js |
1810 | 1850 | lexical-react/dist/LexicalNestedComposer.esm.js |
849 | 900 | lexical-react/dist/LexicalNodeEventPlugin.esm.js |
6527 | 6497 | lexical-react/dist/LexicalNodeMenuPlugin.esm.js |
795 | 783 | lexical-react/dist/LexicalOnChangePlugin.esm.js |
1771 | 1782 | lexical-react/dist/LexicalPlainTextPlugin.esm.js |
1768 | 1779 | lexical-react/dist/LexicalRichTextPlugin.esm.js |
1181 | 1260 | lexical-react/dist/LexicalTabIndentationPlugin.esm.js |
1761 | 1883 | lexical-react/dist/LexicalTableOfContents.esm.js |
2720 | 2770 | lexical-react/dist/LexicalTablePlugin.esm.js |
8084 | 8253 | lexical-react/dist/LexicalTreeView.esm.js |
8262 | 8197 | lexical-react/dist/LexicalTypeaheadMenuPlugin.esm.js |
839 | 843 | lexical-react/dist/useLexicalEditable.esm.js |
695 | 662 | lexical-react/dist/useLexicalIsTextContentEmpty.esm.js |
935 | 919 | lexical-react/dist/useLexicalNodeSelection.esm.js |
715 | 722 | lexical-react/dist/useLexicalSubscription.esm.js |
501 | 514 | lexical-react/dist/useLexicalTextEntity.esm.js |
12336 | 10903 | lexical-rich-text/dist/LexicalRichText.esm.js |
10074 | 10075 | lexical-selection/dist/LexicalSelection.esm.js |
34008 | 33302 | lexical-table/dist/LexicalTable.esm.js |
2705 | 2778 | lexical-text/dist/LexicalText.esm.js |
7051 | 7182 | lexical-utils/dist/LexicalUtils.esm.js |
19079 | 19450 | lexical-yjs/dist/LexicalYjs.esm.js |
89707 | 94829 | lexical/dist/Lexical.esm.js |
I assume we'd want to have some way to test/demo this in the monorepo. What would be the best place to do that? I think we'd need to copy over the .esm.js files to some location (playground? website? some new package?) and have an html file with an importmap to use it.
Just for reference here's what some other popular JS libraries/frameworks are doing regarding esm browser builds:
Vue: https://vuejs.org/guide/quick-start.html#enabling-import-maps Preact: https://preactjs.com/guide/v10/getting-started/#using-preact-with-htm-and-importmaps three.js: https://github.com/mrdoob/three.js/blob/master/examples/webgl_animation_keyframes.html
I assume we'd want to have some way to test/demo this in the monorepo. What would be the best place to do that? I think we'd need to copy over the .esm.js files to some location (playground? website? some new package?) and have an html file with an importmap to use it.
Just for reference here's what some other popular JS libraries/frameworks are doing regarding esm browser builds:
Vue: https://vuejs.org/guide/quick-start.html#enabling-import-maps Preact: https://preactjs.com/guide/v10/getting-started/#using-preact-with-htm-and-importmaps three.js: https://github.com/mrdoob/three.js/blob/master/examples/webgl_animation_keyframes.html
finally got around to reviewing this in-depth. I think it all looks good, pending some testing.
I do think the playground is probably the right place to do that. Do you think we could make a PR that makes that commits the esm.js files and import map, then we could verify on the Vercel deployment?
Sure, I'll look into that. I did look into adding the esm files and a static html page to the playground but it seemed surprisingly complicated to get vite to just copy static files… so I was waiting for a response to make sure it was worth diving into that rabbit hole 😆
For more context about the rabbit hole: vite.config.js
can either be either commonjs or esm (based on file extension or whether package.json
has "type": "module"
or not). If it's commonjs it can't use packages that are only offered as esm, if it's esm it can't use require
. vite-plugin-static-copy
is only available in esm, and the vite config files as written today have commonjs dependencies (transform-error-messages.js
is the most obvious one, did not look for others). rollup-plugin-copy
works with commonjs though so I was able to use that instead.
The vercel playground deploy should be functional in this state (at /esm/. I'll need some guidance if there's more that should be done, the last time I worked on distributing an open source JS library it was a zip file on a website about 20 years ago before there was any module standard at all 😆
The feature that's not tested here is the esm fork modules, not sure what the best way to do that is.
I think I've sorted out how to test the fork modules (running the release script and then doing npm link from another project) and I will need to make a few changes to build.js to address some issues - please don't merge until that's sorted.
Still testing but this commit fixes what I've found so far
I think this is as far as I'm going to be able to get it today, would be great if someone else could test it to make sure it works how they expect both for existing packages and packages that had trouble building due to the lack of an esm version. I was able to stand up an astro build that works locally but I'd need more time to put it online somewhere.
I did notice that I have to configure vite/esbuild explicitly in order for this configuration to work. With a skeleton sveltekit app this is what the vite.config.ts looks like:
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vitest/config';
export default defineConfig({
plugins: [sveltekit()],
test: {
include: ['src/**/*.{test,spec}.{js,ts}']
},
ssr: {
noExternal: [/^(lexical|@lexical\/.*)$/]
},
build: {
target: 'esnext'
},
optimizeDeps: {
esbuildOptions: {
target: 'esnext'
}
}
});
I also couldn't get npm link
of the npm directories to work correctly, but copying them directly over did work. Maybe there is some special case for symlinked folders named npm?
# this does not work
npm link ~/src/lexical/packages/*/npm
# this works
for npmdir in ~/src/lexical/packages/*/npm; do pkg=$(jq -r '.name' "$npmdir/package.json"); rm -rf "./node_modules/$pkg"; cp -r "$npmdir" ."/node_modules/$pkg"; done
I changed the esm fork module approach to improve compatibility - it now imports both the dev and prod modules synchronously (no dynamic imports or await) and exports symbols from one of them. By adding a sideEffect: false to the package.json it seems that (some? at least vite) bundlers understand what to do with this. I created a minimal SvelteKit project with the vanilla editor and I only got symbols from prod in the build output.
I changed the esm fork module approach to improve compatibility - it now imports both the dev and prod modules synchronously (no dynamic imports or await) and exports symbols from one of them. By adding a sideEffect: false to the package.json it seems that (some? at least vite) bundlers understand what to do with this. I created a minimal SvelteKit project with the vanilla editor and I only got symbols from prod in the build output.
incredible. javascript ecosystem, amirite?
Hah yeah the ecosystem is pretty special, makes Python look good 🤣
I think this is in a good enough place. I have working examples for sveltekit and Astro which I think are the problem frameworks? Plus of course the vanilla esm importmap example with no bundler.
Just as a follow-up sanity check I went ahead and updated my astro and svelte examples to use the released 0.14.1 and they still work. Thanks for getting this through so quickly!
Just as a follow-up sanity check I went ahead and updated my astro and svelte examples to use the released 0.14.1 and they still work. Thanks for getting this through so quickly!
No, thank you for all the time you put into making this happen. The effort here is greatly appreciate and will definitely be a boon for the community.
Hi, using this version I get the following error:
error: 'import', and 'export' cannot be used outside of module code at file:///Users/Library/Caches/deno/npm/registry.npmjs.org/@lexical/react/0.14.2/LexicalErrorBoundary.esm.js:7:1
import * as modDev from './LexicalErrorBoundary.dev.esm.js';
It might be because the closest package.json does not have a type field specified, causing Deno to apply CommonJS module resolution ?
I think it's likely that this is fixed in the next release by #5737
This adds a parallel ESM build, in addition to the current CJS build.
Code was added to
npm run update-version
to maintain the package.json metadata for each package (declaring all of the exports & setting"sideEffect": false
).The deepest rabbit hole was the prod build, which uses @ampproject/rollup-plugin-closure-compiler. I could not find an obvious issue about it but when it tries to optimize
LexicalClickableLinkPlugin
it ends up transformingexport default function LexicalClickableLinkPlugin(…)
toexport function default(…)
which is an error. I couldn't figure out how to fix it without also fixing the upstream package, but it seemed that terser was more popular for this use case so I gave that a shot and it compiled straight away.The second deepest rabbit hole was figuring out how to do a fork module for the ESM build. It seems that a lot of the ecosystem is not ready for dynamic imports and top-level await, so it currently uses the pattern of importing both the dev and prod builds and exporting one of them based on
process.env.NODE_ENV
. This appears to work correctly with tree-shaking, at least with"sideEffect": false
in the package.json files using vite/esbuild.Adds an /esm/ endpoint to the playground to demonstrate an ESM native build using static html with an importmap and no bundler at all.
I did not add these to /examples/ because I have currently vendored release builds of lexical packages so they can use the esm build, but I have demonstrated that it works with SvelteKit and Astro (with some vite configuration):
The required vite configuration looks like this:
Resolves #1707.