Skip to content

fix: fix error with <Prism /> component in Cloudflare Workers#15723

Open
rururux wants to merge 16 commits intowithastro:mainfrom
rururux:v6-cf-prism
Open

fix: fix error with <Prism /> component in Cloudflare Workers#15723
rururux wants to merge 16 commits intowithastro:mainfrom
rururux:v6-cf-prism

Conversation

@rururux
Copy link
Copy Markdown
Contributor

@rururux rururux commented Mar 2, 2026

fixes: #15722

Changes

  • Ported loadLanguages from prismjs, rewrote them as ESM, and configured them to be loaded in Cloudflare Workers environments.
  • Accordingly, changed the runHighlighterWithAstro function to an async function.
  • Updated files that depended on runHighlighterWithAstro to also handle it as an async function.

Fixes a CommonJS-related error that occurred when using the Cloudflare Workers integration with the <Prism /> component in the latest beta of Astro.
The root cause was that the loadLanguages function exported from prismjs used require() and require.resolve() internally.
To work around this, i ported loadLanguages and its dependencies from the prismjs repository, rewrote them as ESM, and configured them to be loaded only in Cloudflare Workers environments.
Initially, i considered simply adding 'prismjs/components/index.js' to optimizeDeps.include in @astrojs/cloudflare, but this approach was abandoned because while require() was replaced, require.resolve() remained as-is and still caused an error.

As mentioned in this comment, I encountered an interesting phenomenon while investigating this issue.
Specifically, statically importing the prismjs module in the workerd environment caused the tests to become flaky, while switching to dynamic import made them stable.
This pull request therefore takes that approach. I've left an explanatory comment in the workerd-specific file.

Reference

loadLanguages: https://github.com/PrismJS/prism/blob/76dde18a575831c91491895193f56081ac08b0c5/components/index.js

Testing

Added a test to verify that the component works without errors in a workerd environment.

Docs

N/A, bug fix

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 2, 2026

🦋 Changeset detected

Latest commit: df376c0

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions bot added feat: markdown Related to Markdown (scope) pkg: integration Related to any renderer integration (scope) labels Mar 2, 2026
"rootDir": "./src",
"outDir": "./dist"
"outDir": "./dist",
"types": ["vite/client"]
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This line is required to load the type definitions for import.meta.glob().

@rururux
Copy link
Copy Markdown
Contributor Author

rururux commented Mar 2, 2026

🤔

@rururux rururux marked this pull request as draft March 2, 2026 19:21
@rururux

This comment was marked as outdated.

@rururux rururux marked this pull request as ready for review March 3, 2026 14:39
@ematipico
Copy link
Copy Markdown
Member

@rururux if the code that we're attempting to load is CJS, we should use vite.resolve.optimiseDeps and add the file to it, that should work

@rururux
Copy link
Copy Markdown
Contributor Author

rururux commented Mar 17, 2026

@ematipico

Thank you for the suggestion! I tried the approach you proposed, and while it does improve stability, prismjs is only depended on by @astrojs/prism within Astro's packages, so for projects using the Cloudflare integration without the <Prism /> component (projects that don't depend on @astrojs/prism), the following log now appears:

20:07:54 [WARN] [vite] Failed to resolve dependency: @astrojs/prism > prismjs, present in ssr 'optimizeDeps.include'
20:07:54 [WARN] [vite] Failed to resolve dependency: @astrojs/prism > prismjs/components.js, present in ssr 'optimizeDeps.include'
20:07:54 [WARN] [vite] Failed to resolve dependency: @astrojs/prism > prismjs/dependencies.js, present in ssr 'optimizeDeps.include'

@rururux
Copy link
Copy Markdown
Contributor Author

rururux commented Mar 17, 2026

Also, I just noticed there's actually an issue with the implementation in this PR, getLoader().load() was missing an argument that is required when the function passed to load() returns a Promise, which means it wasn't being awaited as expected.
I'll fix this right away.

edit: done

@rururux
Copy link
Copy Markdown
Contributor Author

rururux commented Mar 17, 2026

I added a simple detection logic to the Cloudflare Workers integration's Vite plugin that checks whether @astrojs/prism is installed in the current project. By conditionally including prismjs-related files in optimizeDeps.includes based on this result, the log issue should be resolved (verified locally).

One limitation to note: since the check works by reading the package.json in the root folder, it won't detect cases where @astrojs/prism is an indirect dependency of something installed at the root.
I also tried using require.resolve('@astrojs/prism') for the check, but since the test fixtures specify @astrojs/prism as workspace:*, the resolved path doesn't come out as expected, so I went with the package.json approach for now.

If you'd prefer, I can update the Cloudflare integration's test fixtures to install @astrojs/prism from npm instead of workspace:*, and adjust the detection logic accordingly.

Copy link
Copy Markdown
Member

@ematipico ematipico left a comment

Choose a reason for hiding this comment

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

I need to wrap my head with the new code. There are weird things

return;
}

const pathToLanguage = `../node_modules/prismjs/components/prism-${lang}.js`;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you explain me why we're doing this? This feels very hacky and crawling node_modules could lead to all sorts of things

Copy link
Copy Markdown
Contributor Author

@rururux rururux Mar 18, 2026

Choose a reason for hiding this comment

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

The reason I'm referencing node_modules directly to load language files is that using import.meta.glob for dynamic package imports causes an error when specifying something like import.meta.glob('prismjs/components/prism-*.js'): Internal server error: Invalid glob: "prismjs/components/prism-*.js" (resolved: "prismjs/components/prism-*.js"). It must start with '/' or './'

Using await import(`prismjs/components/prism-${lang}.js`) also fails with a The above dynamic import cannot be analyzed by Vite. warning.
https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations

So i went with the approach of referencing node_modules directly.

I do have one alternative approach in mind that might work, and i'm going to give it a try now.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

One of the approaches i had in mind doesn't seem to work out.
The tricky part is that the path needs to be statically known at the time of the dynamic import, so the options to work around this would be either pre-writing all language file paths to some file, or passing the paths through a virtual module from the Cloudflare Workers integration plugin.

@rururux
Copy link
Copy Markdown
Contributor Author

rururux commented Mar 19, 2026

I've switched to an approach that uses a virtual module to load Prism language files, but only in the Cloudflare Workers environment.
This eliminates the need to reference import.meta.glob() or /node_modules/ directly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat: markdown Related to Markdown (scope) pkg: integration Related to any renderer integration (scope)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[v6] <Prism /> component throws an error on pnpm astro dev when used with the Cloudflare Workers integration

2 participants