Skip to content

Instantly share code, notes, and snippets.

@noherczeg
Last active January 9, 2025 22:13
Show Gist options
  • Save noherczeg/e509f69bfa185035cf23b69ea855e026 to your computer and use it in GitHub Desktop.
Save noherczeg/e509f69bfa185035cf23b69ea855e026 to your computer and use it in GitHub Desktop.
import { type Plugin } from 'vite';
import { existsSync, readFileSync } from 'node:fs';
import { resolve } from 'node:path';
interface ImportmapConfig {
appendSuffix?: Record<string, string>,
keepExternals?: string[],
}
function vitePluginImportmap(configOverrides: ImportmapConfig = {}): Plugin {
return {
name: 'vite-plugin-importmap',
enforce: 'pre',
// @ts-ignore
config(config, { command }) {
const pkgPath = resolve(process.cwd(), 'package.json');
if (!existsSync(pkgPath)) {
throw new Error(`package.json not found at ${pkgPath}`);
}
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
const dependencies = pkg.dependencies || {};
// Generate Rollup exclude list
const externalDeps = Object.keys(dependencies);
const exclude = externalDeps;
if (command === 'build') {
config.build = config.build || {};
config.build.rollupOptions = config.build.rollupOptions || {};
config.build.rollupOptions.external = (id: string) => {
if (configOverrides.keepExternals?.includes(id)) {
return false;
}
return externalDeps.includes(id);
};
}
return { exclude };
},
transformIndexHtml(html) {
const pkgPath = resolve(process.cwd(), 'package.json');
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
const dependencies = pkg.dependencies || {};
// Create the importmap as a string
const importMap = {
imports: Object.entries(dependencies).reduce((map, [name, version]) => {
const suffix = configOverrides?.appendSuffix[name] || ''; // Get the suffix from configOverrides
map[name] = `https://esm.sh/${name}@${version}${suffix}`;
return map;
}, {} as Record<string, string>),
};
const importMapScript = `<script type="importmap">${JSON.stringify(importMap, null, 2)}</script>`;
// Inject the importmap script into the head of the HTML
return html.replace('</head>', `${importMapScript}\n</head>`);
},
};
}
export default vitePluginImportmap;
import path from 'node:path';
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import vitePluginImportmap from './vite-plugin-importmap';
const cdnUrl = 'https://esm.sh/';
const regex = /^(?:v[\d]*\/)?(@?.*)@([\d|\.]+|\*)/;
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => ({
base: '',
resolve: {
alias: [
{ find: '~', replacement: path.resolve(__dirname, 'src') },
],
},
plugins: [
vitePluginImportmap({
// keepExternals: ['react', 'react-dom'],
appendSuffix: {
axios: '?bundle',
// '@pandino/react-hooks': '?pin=v83',
// react: '?bundle',
},
}),
react(),
],
}));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment