Make Icon work more easily in non-Webpack contexts
The problem
In a non-Webpack context such as Rollup/Vite/esbuild, it can be quite difficult to get the pathing working properly so that the code that resolves icon works properly, often leading to a message like Error: No icon named "exclamation-inverse" which isn't true; it's just that the import didn't work.
This appears to be in part because the line in the built module ends up looking like this:
const icon = await import(/* webpackChunkName: '[request]' */ `../../styles/icons/${this.name}.js`);
Which may work in Webpack contexts but can fail because of the relative nature of the path in other contexts.
The solution
Use something other than relative pathing for the icon import, such that it will correctly resolve to the icon file in question in more situations.
Alternatives considered
I've tried messing around with "correcting" this relative pathing in a Vite project, but it's proving difficult. The bundle is at e.g. /assets/vendor.[hash].js, and the icon path then can't go up two levels like it's trying to. The only workaround would be to push the vendor file down a level, I believe.
This appears to be because of vitejs/vite#6179 and how Rollup's dynamic imports work. The suggested workaround in the Vite issue discussion does improve the build, causing the transpiled code to reference the icon files explicitly and copy them over appropriately. However, the relative references still don't work because the request ends up being relative to node_modules/.vite/deps/ rather than the original location of the module.
Two workarounds(?) using vite.config.js courtesy of @michael-iden and @Ivanok:
import { defineConfig } from "vite";
import path from "path";
export default defineConfig({
resolve: {
alias: {
'/node_modules/styles/icons': path.resolve(
__dirname,
'node_modules/@ithaka/pharos/lib/styles/icons'
),
},
},
});
import { defineConfig } from "vite";
import dynamicImport from "vite-plugin-dynamic-import";
export default defineConfig({
plugins: [
dynamicImport({
filter(id) {
if (id.includes("/node_modules/@ithaka/pharos/")) {
return true;
}
},
}),
],
});
With these I am inclined to close this issue, but opinions are welcome.