{"id":15627,"library":"glsl-shader-loader","title":"GLSL Shader Loader for Webpack","description":"glsl-shader-loader is a Webpack loader designed to bundle GLSL shader source code, enabling modular management of shaders for WebGL applications. It allows developers to organize GLSL functions into separate files and import them using a custom `#pragma loader: import` syntax directly within other `.glsl` files. The loader performs static analysis to resolve dependencies, remove unused functions, and ensure functions are imported only once, resulting in an optimized shader string ready for use with WebGL. As of version 0.1.6, it focuses on providing a preprocessor-like experience for GLSL, which is useful for complex shader graphs and code reuse. Its release cadence appears to be slow, with the latest version indicating an early stage or a stable, low-maintenance tool rather than rapid development. Key differentiators include its syntax tree analysis for dependency resolution and optimization, which goes beyond simple string concatenation.","status":"maintenance","version":"0.1.6","language":"javascript","source_language":"en","source_url":"https://github.com/migalooo/glsl-shader-loader","tags":["javascript","glsl","shader","webgl","module","component","webpack","loader","import"],"install":[{"cmd":"npm install glsl-shader-loader","lang":"bash","label":"npm"},{"cmd":"yarn add glsl-shader-loader","lang":"bash","label":"yarn"},{"cmd":"pnpm add glsl-shader-loader","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"This package is a Webpack loader and requires Webpack for its functionality.","package":"webpack","optional":false}],"imports":[{"note":"This is how the loader is referenced and configured within your `webpack.config.js` file, not a direct JavaScript import.","wrong":"loader: require('glsl-shader-loader')","symbol":"glsl-shader-loader","correct":"loader: 'glsl-shader-loader'"},{"note":"After configuring the loader in Webpack, `.glsl` files can be imported into JavaScript/TypeScript as strings, representing the processed shader source. The CJS `require` might work with specific Webpack configs, but ESM `import` is more idiomatic.","wrong":"const fragmentShaderSource = require('./fragmentShaderSource.glsl');","symbol":"ShaderModule","correct":"import fragmentShaderSource from './fragmentShaderSource.glsl';"},{"note":"This is a special directive used *within GLSL files* to import functions from other GLSL files. It is not a JavaScript `import` statement but a preprocessor command processed by the loader.","wrong":"import { functionName } from './file.glsl';","symbol":"GLSLFunctionImport","correct":"#pragma loader: import { functionName } from './file.glsl';"}],"quickstart":{"code":"import path from 'path';\nimport webpack from 'webpack';\nimport MemoryFS from 'memory-fs';\n\n// Basic webpack config to use glsl-shader-loader\nconst config = {\n  mode: 'development',\n  entry: './app.js',\n  output: {\n    path: path.resolve(__dirname, 'dist'),\n    filename: 'bundle.js',\n  },\n  module: {\n    rules: [\n      {\n        test: /\\.(frag|vert|glsl)$/,\n        use: [\n          {\n            loader: 'glsl-shader-loader',\n            options: {\n              // Optional: specify a root path for absolute GLSL imports\n              // root: path.resolve(__dirname, 'src/shaders')\n            }\n          }\n        ]\n      }\n    ]\n  }\n};\n\n// Example application JS (app.js)\nconst appJsContent = `\nimport fragmentShaderSource from './fragmentShaderSource.glsl';\n\nconsole.log('--- Compiled Fragment Shader Source ---');\nconsole.log(fragmentShaderSource);\n\n// In a real WebGL app, you'd use:\n// const gl = canvas.getContext('webgl');\n// const shader = gl.createShader(gl.FRAGMENT_SHADER);\n// gl.shaderSource(shader, fragmentShaderSource);\n// gl.compileShader(shader);\n`;\n\n// Example GLSL file (fragmentShaderSource.glsl)\nconst fragmentShaderContent = `\nprecision mediump float;\n\nvarying vec2 v_texCoord;\n\n#pragma loader: import { randomColor } from './utils.glsl';\n\nvoid main() {\n  vec3 color = randomColor(v_texCoord);\n  gl_FragColor = vec4(color, 1.0);\n}\n`;\n\n// Example GLSL utility file (utils.glsl)\nconst utilsGlslContent = `\nvec3 randomColor(vec2 coord) {\n  // Simple pseudo-random color based on coordinates\n  float r = fract(sin(dot(coord.xy, vec2(12.9898, 78.233))) * 43758.5453);\n  float g = fract(sin(dot(coord.xy, vec2(53.123, 19.345))) * 53758.9876);\n  float b = fract(sin(dot(coord.xy, vec2(87.654, 34.567))) * 63758.1234);\n  return vec3(r, g, b);\n}\n\nvec3 anotherFunction() {\n  return vec3(0.0);\n}\n`;\n\n// Setup an in-memory file system for webpack to read from\nconst fs = new MemoryFS();\nfs.mkdirpSync(path.resolve(__dirname, 'dist'));\nfs.mkdirpSync(path.resolve(__dirname, 'src'));\nfs.mkdirpSync(path.resolve(__dirname, 'utils'));\nfs.writeFileSync('./app.js', appJsContent);\nfs.writeFileSync('./fragmentShaderSource.glsl', fragmentShaderContent);\nfs.writeFileSync('./utils.glsl', utilsGlslContent);\n\nconst compiler = webpack(config);\ncompiler.inputFileSystem = fs;\ncompiler.outputFileSystem = fs;\n\ncompiler.run((err, stats) => {\n  if (err) {\n    console.error(err.stack || err);\n    if (err.details) {\n      console.error(err.details);\n    }\n    return;\n  }\n\n  const info = stats.toJson();\n\n  if (stats.hasErrors()) {\n    console.error(info.errors);\n  }\n  if (stats.hasWarnings()) {\n    console.warn(info.warnings);\n  }\n\n  console.log('\\nWebpack build completed.');\n  const bundlePath = path.resolve(__dirname, 'dist', 'bundle.js');\n  const bundleContent = fs.readFileSync(bundlePath, 'utf8');\n  // In a real scenario, you'd typically serve this bundle or inject it.\n  // For this quickstart, we'll just show the generated content.\n  // To demonstrate the *processed* GLSL, we'd need to run the bundle\n  // which is outside the scope of this quickstart directly.\n  // The console.log in app.js inside the bundle would show the processed shader.\n});\n","lang":"javascript","description":"This quickstart demonstrates how to configure glsl-shader-loader in Webpack to process `.glsl` files, including internal GLSL `#pragma loader: import` statements, and then import the resulting shader string into a JavaScript application."},"warnings":[{"fix":"Review the GitHub repository for recent commits and open issues before committing to long-term use. Consider potential compatibility issues with very new Webpack versions.","message":"The package version 0.1.6 suggests it might be in an early development stage or is no longer actively maintained. While functional, it might not receive updates for newer Webpack versions or address new GLSL features/standards.","severity":"gotcha","affected_versions":"0.1.x"},{"fix":"Ensure your build pipeline and any GLSL validation tools are aware of or can ignore these custom pragmas. You may need to preprocess GLSL for other tools if this loader's output isn't directly compatible.","message":"The `#pragma loader: import` syntax is unique to this loader and not standard GLSL. It might not be compatible with other GLSL tooling or linting without specific configuration.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Always use named imports (`#pragma loader: import { originalName } from './file.glsl';`) if the target `.glsl` file contains more than one function. Only use `import newName from './file.glsl';` if you are absolutely certain there is a single function to be imported and renamed.","message":"When importing a single function from a GLSL file, you can rename it during import (e.g., `#pragma loader: import newName from './file.glsl';`). However, this only works if the source file contains *only one* function. If multiple functions exist, renaming fails, and you must use named imports.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Ensure all imported GLSL functions are explicitly called within the main shader source if you intend for them to be included in the final bundled output.","message":"The loader performs static analysis and only includes imported functions if they are actually called within the consuming shader. While this is an optimization, it can lead to unexpected behavior if a function is imported but not explicitly called, as it will be omitted from the final output.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Add or verify the `glsl-shader-loader` configuration in your `webpack.config.js` under `module.rules`, ensuring the `test` regex matches your GLSL file extensions (e.g., `test: /\\.(frag|vert|glsl)$/`).","cause":"Webpack is trying to parse a `.glsl` file as a standard JavaScript module because glsl-shader-loader is not correctly configured or applied.","error":"Module parse failed: Unexpected token (1:0) You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file."},{"fix":"Double-check the relative path specified in the `#pragma loader: import` statement. If using the `root` option in the loader configuration, ensure absolute paths starting with `/` correctly map to your specified root directory.","cause":"The `#pragma loader: import` path within a `.glsl` file is incorrect or cannot be resolved by the loader.","error":"Error: Can't resolve './file.glsl' in 'path/to/shader/'"},{"fix":"Ensure you are using `import myShaderSource from './myShader.glsl'` in your JavaScript files, and `glsl-shader-loader` is configured. Within GLSL files, strictly use `#pragma loader: import { functionName } from './file.glsl';` for function imports.","cause":"Attempting to use a standard JavaScript `import` statement for a GLSL file directly, or incorrect syntax within the GLSL `#pragma` directive.","error":"SyntaxError: Unexpected identifier 'functionName'"}],"ecosystem":"npm"}