Skip to content

Instantly share code, notes, and snippets.

@0b5vr
Last active January 31, 2024 12:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save 0b5vr/7c0d000ab9a43268c47273c272b81de0 to your computer and use it in GitHub Desktop.
Save 0b5vr/7c0d000ab9a43268c47273c272b81de0 to your computer and use it in GitHub Desktop.
vite-shader-minifier-plugin
// vite-shader-minifier-plugin
// Copyright (c) 2022 0b5vr
// SPDX-License-Identifier: MIT
// Compatible with Shader Minifier 1.2
// https://github.com/laurentlb/Shader_Minifier/releases/tag/1.2
// Usage:
// - Make sure `shader_minifier.exe` is visible via PATH
// - Install the plugin into your `vite.config.ts`
// - Optionally, you can give `minifierOptions`. You probably want to put `{ preserveExternals: true }`.
// Disclaimer: I'm pretty sure this published version will not be updated frequently
import { Plugin } from 'vite';
import { promisify } from 'util';
import cp from 'child_process';
import fs from 'fs';
import path from 'path';
const exec = promisify( cp.exec );
const fileRegex = /\?shader$/;
export interface ShaderMinifierOptions {
hlsl?: boolean;
fieldNames?: string;
preserveExternals?: boolean;
preserveAllGlobals?: boolean;
noRenaming?: boolean;
noRenamingList?: string[];
noSequence?: boolean;
smoothstep?: boolean;
}
function buildMinifierOptionsString( options: ShaderMinifierOptions ): string {
let str = '';
if ( options.hlsl ) {
str += '--hlsl ';
}
str += '--format text ';
if ( options.fieldNames ) {
str += `--field-names ${ options.fieldNames } `;
}
if ( options.preserveExternals ) {
str += '--preserve-externals ';
}
if ( options.preserveAllGlobals ) {
str += '--preserve-all-globals ';
}
if ( options.noRenaming ) {
str += '--no-renaming ';
}
if ( options.noRenamingList ) {
str += `--no-renaming-list ${ options.noRenamingList.join( ',' ) } `;
}
if ( options.noSequence ) {
str += '--no-sequence ';
}
if ( options.smoothstep ) {
str += '--smoothstep ';
}
return str;
}
export interface ShaderMinifierPluginOptions {
minify: boolean;
minifierOptions: ShaderMinifierOptions;
}
export const shaderMinifierPlugin: (
options: ShaderMinifierPluginOptions
) => Plugin = ( { minify, minifierOptions } ) => {
return {
name: 'shader-minifier',
enforce: 'pre',
async transform( src: string, id: string ) {
if ( fileRegex.test( id ) ) {
if ( minify === false ) {
return `export default \`${ src }\`;`;
}
if ( /^#pragma shader_minifier_plugin bypass$/m.test( src ) ) {
console.warn( `\`#pragma shader_minifier_plugin bypass\` detected in ${ id }. Bypassing shader minifier` );
return `export default \`${ src }\`;`;
}
const name = path.basename( id ).split( '?' )[ 0 ];
const minifierOptionsString = buildMinifierOptionsString( minifierOptions );
const tempy = await import( 'tempy' );
const minified = await tempy.temporaryFileTask( async ( pathOriginal ) => {
await fs.promises.writeFile( pathOriginal, src, { encoding: 'utf8' } );
return await tempy.temporaryFileTask( async ( pathMinified ) => {
const command = `shader_minifier.exe ${ pathOriginal } ${ minifierOptionsString }-o ${ pathMinified }`;
await exec( command ).catch( ( error ) => {
throw new Error( error.stdout );
} );
return await fs.promises.readFile( pathMinified, { encoding: 'utf8' } );
}, { name } );
}, { name } );
return {
code: `export default \`${ minified }\`;`,
};
}
}
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment