Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZKHelloworld/4d518583b90ddcb4762d49c102a42054 to your computer and use it in GitHub Desktop.
Save ZKHelloworld/4d518583b90ddcb4762d49c102a42054 to your computer and use it in GitHub Desktop.
import path from 'path';
import fs from 'fs';
import { generate } from 'astring'
interface Options {
test: RegExp;
include: string[];
dir: string;
}
function hash(src: string): string {
var hash = 0, i, chr;
if (src.length === 0) {
return '';
}
for (i = 0; i < src.length; i++) {
chr = src.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer
}
return Math.abs(hash).toString().substring(0, 5);
}
function generateFileNameWithHash(fileName: string, filePath: string) {
if (!fileName) {
return '';
}
return `${path.parse(fileName).name}-${hash(filePath)}${path.parse(fileName).ext}`;
}
export default function vitePluginLibraryAssetExternal(options: Options) {
let aliasPlugin;
let outputDir;
return {
name: 'vite-plugin-library-asset-external',
config(config) {
if (config?.build?.rollupOptions?.external) {
config.build.rollupOptions.external.push(options.test);
} else {
config.build.rollupOptions.external = [options.test];
}
},
configResolved(config) {
outputDir = path.resolve(config.root, config.build.outDir);
},
buildStart({ plugins }) {
aliasPlugin = plugins.find(p => p.name === 'alias');
},
async transform(src, id) {
if (options.include.indexOf(path.extname(id)) === -1) {
return null;
}
let transformed = false;
// iterate every import declaration
const ast = this.parse(src);
for (let node of ast?.body || []) {
if (node.type !== 'ImportDeclaration') {
continue;
}
if (!options.test.test(node.source.value)) {
continue;
}
let assetInfo;
if (aliasPlugin) {
assetInfo = await aliasPlugin.resolveId.call(this, node.source.value, id);
}
if (!assetInfo) {
assetInfo = await this.resolve(node.source.value, id);
}
if (!assetInfo) {
this.error(`[vite-plugin-library-asset-external] resolve asset failed, importee: ${node.source.value} importer: ${id}`);
continue;
}
if (!assetInfo.external) {
continue;
}
const fileName = generateFileNameWithHash(path.basename(assetInfo.id), assetInfo.id);
const assetName = `${options.dir}/${fileName}`;
await this.emitFile({
type: 'asset',
name: assetName,
source: fs.readFileSync(assetInfo.id),
});
const outputAssetPath = path.join(outputDir, assetName);
node.source.value = `${outputAssetPath}`;
node.source.raw = `"${outputAssetPath}"`;
transformed = true;
}
if (!transformed) {
return null;
}
return {
code: generate(ast),
};
},
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment