WESL Logo

Publishing Packages

#Naming Conventions

#Publishing a package to npm.js

Use wesl-packager to gather WGSL and WESL shader modules into an npm package.

#Command Line Tools

Here’s an example, creating a bundled package in the dist directory from sources in the src/shaders directory.

npx wesl-packager --rootDir src/shaders --outDir dist

Add the files generated by wesl-packager to the package’s package.json:

/// in package.json
  "exports": {
    ".": {
      "types": "./dist/weslBundle.d.ts",
      "import": "./dist/weslBundle.js"
    }
  },

#npm Shader Package Format

The format generated for shader packages (and consumed by the WESL JavaScript/TypeScript tools) is a WeslBundle:

export interface WeslBundle {
  /** name of the package, e.g. random_wgsl */
  name: string;

  /** wesl edition of the code e.g. unstable_2025_1 */
  edition: string;

  /** map of wesl/wgsl modules:
   *    keys are file paths, relative to package root (e.g. "./lib.wgsl")
   *    values are wgsl/wesl code strings
   */
  modules: Record<string, string>;

  /** packages referenced by this package */
  dependencies?: WeslBundle[];
}

Shaders are bundled simply as strings with relative file paths in the modules field.

dependencies reference import statements in the js output bundle so that shader packages can depend on other packages. Shader dependency versioning is handled by the package manager.

#Importing and lib.wesl

npm users can then easily use the shader package. For a new package called foo_wgsl:

  1. npm add foo_wgsl

  2. add foo_wgsl to the dependencies list in the wesl.toml file

  3. import from the package in WESL, using the module paths in place of the relative file paths:

    import foo_wgsl::util::foo;  
    
    fn main() {
      foo();`
    }
    

To keep things short, the special module name lib.wesl is addressable at the root level of the package:

fn main() {
   foo_wgsl::bar();`
}

#Publishing a package to crates.io

See rust example here