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 parser for pyodide.js and pyodide.mjs to avoid webpack traversing dependencies #22

Merged
merged 17 commits into from
Nov 16, 2023

Conversation

mneil
Copy link
Collaborator

@mneil mneil commented Nov 16, 2023

Fixes #20 and #21

Pyodide is an emscripten project. There are various ways to produce those builds with emscripten and only certain configuration are appropriate for webpack. Not all consumers of pyodide know or care about webpack - we cannot enforce certain build patterns on the core team for a subset of users.

This large change adds a loader with a parser to the plugin. Webpack will no longer look at the pyodide.m?.js file and try to make sense of it. Instead we parse it ourselves to make changes appropriate for webpack and then inject it as a chunk.

Reduces the amount of other configuration that may need to go
in like stubbing node core, ignoring certain node modules, or
writing your own loader.

Use acorn to find and replace global pyodide and add in named
exports so we have a consistent interface between common and esm.
Regular expression isn't as resiliant to change as AST.

CLean up configuration so it's easier to understand the different
build outputs for debugging.

Add examples for users.
Main change adds the after build into a new script to be
reused in the other configs. After build is used to copy the build
into the example folders which are useful for testing. You cannot
npm link the build because the links will resolve pyodide differently
and a check for specific types will fail when it loads the same file
twice from different location (they receive different memory addresses).
Using esbuild to transpile the pyodide module (.mjs) to common
js format. There may be a better way to do this but the issue is:

When you build a module project (ie your project using pyodide is a
module) with webpack then it loads the pyodide.mjs.

We do not want webpack to process the pyodide.m?js file at all because
they have been output by emscripten and are already compatible with
the browser and node and contain pollyfills. The easiest way to handle
skipping a pollyfill is to load the file as a string and eval it
into existence. Webpack will skip processing this and treat it
as a string.

You cannot eval a module. eval doesn't recognize import/export. I
convert the build to commonjs, eval it, then export the loadPyodide
function back for esm compatability.
This was a copy/pasta from a fit of debugging
This file needs to be commonjs. Webpack loaders do not currently
support esm.
Done testing. Loading the esm module like a typical import should
work without having to specify the full file path
One code path to rule them all. All code is commonjs all the time
now. Is this backwards? I don't think so. Mentioned in previous commits
you cannot eval an esm piece of code and webpack will try to parse
any js you throw at it. There's got to be a better way and I just don't
know it.
More exhaustive tests that verify each
build passes without errors.
We need to know where to copy files from so resolving the pyodide
package location is necessary. The old way assumed there was a
node_modules folder in your cwd and then listed all folders
in there looking for 1 named pyodide.

Now using require.resolve to let node find the package for us then
walk up to find the root of the package. Require.resolve returns
the main / entrypoint of the package which can be nested. We need
the folder that contains package.json.

There is a catch to stop traversing any lower than the node_modules
folder so it doesn't try to walk into protected directories.
Share dependencies during development with examples making it easier
to develop and run tests.
Required minor changes to test and build phase so that we only
count "examples" as the directories in the examples folder and
not  everything in that folder (files, links, etc...).
No need to support anything less than 18. 14 and better should
work but 18 is already in maintainance mode. 16 is EOL.

Recommend node 20 for new projects.
esm builds are working now without issue. Full support for both
commonjs and esm builds is added.

Addresses #21. We no longer allow webpack to try and parse the
emscripten build. We do that ourselves.
@mneil mneil merged commit 646bee5 into main Nov 16, 2023
2 checks passed
@mneil mneil deleted the parsing-20 branch November 16, 2023 22:34
@@ -0,0 +1,15 @@
const { loadPyodide } = require("pyodide");
Copy link

Choose a reason for hiding this comment

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

Since the examples are used for tests, this should import everything. I.e. by also importing version, hopefully it would reveal the same error as in #25

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.

PyodidePlugin is not a constructor error
3 participants