diff --git a/plugins/preload.js b/plugins/preload.js new file mode 100644 index 000000000..d55a6ce2b --- /dev/null +++ b/plugins/preload.js @@ -0,0 +1,48 @@ +import { promises as fs } from 'node:fs'; +import path from 'node:path'; + +/** + * @returns {import('vite').Plugin} + */ +export function preloadPlugin() { + return { + name: 'preload-plugin', + async closeBundle() { + const [manifestContent, replContent, assetsDir] = await Promise.all([ + fs.readFile(path.resolve('build', '.vite/manifest.json'), 'utf-8'), + fs.readFile(path.resolve('build', 'repl/index.html'), 'utf-8'), + fs.readdir(path.resolve('build', 'assets')) + ]); + + const replWorker = `assets/${assetsDir.find((file) => file.startsWith('repl.worker-'))}`; + + const manifest = JSON.parse(manifestContent); + + let errorOverlay = ''; + for (const file in manifest) { + if (manifest[file].name == 'error-overlay') { + errorOverlay = file; + break; + } + } + + const preloadTags = [ + 'src/components/controllers/repl-page.jsx', + 'src/components/controllers/repl/runner.jsx', + 'src/components/code-editor/index.jsx', + errorOverlay, + replWorker + ].map((file) => { + const filePath = manifest[file] ? manifest[file].file : file; + return `\n\t\t`; + }).join(''); + + const replWithPreload = replContent.replace( + '', + `${preloadTags}` + ); + + await fs.writeFile(path.resolve('build', 'repl/index.html'), replWithPreload); + } + }; +} diff --git a/vite.config.js b/vite.config.js index 576f5a8dd..9f59ca1ca 100644 --- a/vite.config.js +++ b/vite.config.js @@ -9,6 +9,7 @@ import { netlifyPlugin } from './plugins/netlify.js'; import { spaFallbackMiddlewarePlugin } from './plugins/spa-fallback-middleware.js'; import { htmlRoutingMiddlewarePlugin } from './plugins/html-routing-middleware.js'; import { rssFeedPlugin } from './plugins/rss-feed.js'; +import { preloadPlugin } from './plugins/preload.js'; // TODO: Should we do this for all routes, rely on discovery a bit less? import { tutorialRoutes } from './src/lib/route-utils.js'; @@ -20,7 +21,8 @@ export default defineConfig({ }, build: { target: ['chrome88', 'edge88', 'es2020', 'firefox78', 'safari14'], - outDir: 'build' + outDir: 'build', + manifest: true }, plugins: [ replace({ @@ -58,6 +60,7 @@ export default defineConfig({ netlifyPlugin(), spaFallbackMiddlewarePlugin(), htmlRoutingMiddlewarePlugin(), - rssFeedPlugin() + rssFeedPlugin(), + preloadPlugin() ] });