Working with Bundlers#
Webpack#
There is a Pyodide Webpack Plugin to load Pyodide from a CDN in a Webpack project.
Vite#
Note
The following instructions have been tested with Pyodide 0.26.2, Vite 5.4.9, and vite-plugin-pyodide 2.0.0.
First, install the Pyodide and vite-plugin-pyodide npm packages:
$ npm install pyodide vite-plugin-static-copy
Then, in your vite.config.mjs
file, exclude Pyodide from Vite’s dependency
pre-bundling by setting optimizeDeps.exclude
and ensure that
all Pyodide files will be available in dist/assets
for production builds by
using a Vite plugin:
import { defineConfig } from "vite";
import { viteStaticCopy } from "vite-plugin-static-copy";
import { dirname, join } from "path";
import { fileURLToPath } from "url";
const PYODIDE_EXCLUDE = [
"!**/*.{md,html}",
"!**/*.d.ts",
"!**/*.whl",
"!**/node_modules",
];
export function viteStaticCopyPyodide() {
const pyodideDir = dirname(fileURLToPath(import.meta.resolve("pyodide")));
return viteStaticCopy({
targets: [
{
src: [join(pyodideDir, "*")].concat(PYODIDE_EXCLUDE),
dest: "assets",
},
],
});
}
export default defineConfig({
optimizeDeps: { exclude: ["pyodide"] },
plugins: [viteStaticCopyPyodide()],
});
You can test your setup with this index.html
file:
<!doctype html>
<html lang="en">
<head>
<title>Vite + Pyodide</title>
<script type="module" src="main.mjs"></script>
</head>
</html>
And this src/main.mjs
file:
import { loadPyodide } from "pyodide";
async function hello_python() {
let pyodide = await loadPyodide();
return pyodide.runPythonAsync("1+1");
}
hello_python().then((result) => {
console.log("Python says that 1+1 =", result);
});
Make sure this works both in Vite’s dev mode:
npx vite
And as a production build:
npx vite build
npx vite preview