Repository: pyscript/pyscript
File: pyscriptjs/src/main.ts (TypeScript)

Code before:
            });
        });
        document.head.appendChild(script);
    }

    // lifecycle (5)
    // See the overview comment above for an explanation of how we jump from
    // point (4) to point (5).
    //
    // Invariant: this.config is set and available.
    async afterRuntimeLoad(runtime: Runtime): Promise<void> {
        console.assert(this.config !== undefined);

        this.logStatus('Python startup...');
        await runtime.loadInterpreter();
        this.logStatus('Python ready!');

        this.logStatus('Setting up virtual environment...');
        await this.setupVirtualEnv(runtime);
        mountElements(runtime);

        // lifecycle (6.5)
        this.plugins.afterSetup(runtime);

        //Refresh module cache in case plugins have modified the filesystem
        runtime.interpreter.runPython(`import importlib; importlib.invalidate_caches()`)
        this.logStatus('Executing <py-script> tags...');
        this.executeScripts(runtime);

        this.logStatus('Initializing web components...');
        // lifecycle (8)
        createCustomElements(runtime);

        initHandlers(runtime);

        // NOTE: runtime message is used by integration tests to know that
        // pyscript initialization has complete. If you change it, you need to
        // change it also in tests/integration/support.py
        this.logStatus('Startup complete');
        this.plugins.afterStartup(runtime);
        logger.info('PyScript page fully initialized');
    }

    // lifecycle (6)
    async setupVirtualEnv(runtime: Runtime): Promise<void> {
        // XXX: maybe the following calls could be parallelized, instead of
        // await()ing immediately. For now I'm using await to be 100%
        // compatible with the old behavior.
        logger.info('importing pyscript');

        // Save and load pyscript.py from FS

Review comment (performance):
I would still suggest for Pyodide:
```suggestion
        let importlib = runtime.interpreter.pyimport("importlib"); 
        importlib.invalidate_caches();
```
since this doesn't pollute the globals. 

But if you are trying to support other runtimes maybe it's better to stick with something more portable? If you factor out `invalidate_caches` as a separate method, then you could check if `pyimport` is available and use this method if so otherwise fall back to the other approach. Or you could make a persistent `runPythonPrivate` that runs things in a separate private context that won't pollute the user globals.

Code after:
            });
        });
        document.head.appendChild(script);
    }

    // lifecycle (5)
    // See the overview comment above for an explanation of how we jump from
    // point (4) to point (5).
    //
    // Invariant: this.config is set and available.
    async afterRuntimeLoad(runtime: Runtime): Promise<void> {
        console.assert(this.config !== undefined);

        this.logStatus('Python startup...');
        await runtime.loadInterpreter();
        this.logStatus('Python ready!');

        this.logStatus('Setting up virtual environment...');
        await this.setupVirtualEnv(runtime);
        mountElements(runtime);

        // lifecycle (6.5)
        this.plugins.afterSetup(runtime);

        //Refresh module cache in case plugins have modified the filesystem
        runtime.invalidate_module_path_cache()
        this.logStatus('Executing <py-script> tags...');
        this.executeScripts(runtime);

        this.logStatus('Initializing web components...');
        // lifecycle (8)
        createCustomElements(runtime);

        initHandlers(runtime);

        // NOTE: runtime message is used by integration tests to know that
        // pyscript initialization has complete. If you change it, you need to
        // change it also in tests/integration/support.py
        this.logStatus('Startup complete');
        this.plugins.afterStartup(runtime);
        logger.info('PyScript page fully initialized');
    }

    // lifecycle (6)
    async setupVirtualEnv(runtime: Runtime): Promise<void> {
        // XXX: maybe the following calls could be parallelized, instead of
        // await()ing immediately. For now I'm using await to be 100%
        // compatible with the old behavior.
        logger.info('importing pyscript');

        // Save and load pyscript.py from FS