使用 Vite 处理项目中的 glsl 文件

项目中有一些 WebGL 相关的着色器 (shader) 代码, 后缀名为 .glsl 。 目录文件结构为:

- src
- src/layers/particle-layer.ts
- src/layers/particle-layer.fragment.glsl
- src/layers/particle-layer.vertex.glsl

原来用 esbuild 进行转译和打包, 配置起来非常的容易, 直接使用内置的 loader 就可以处理, esbuild 的配置如下:

export default {
  entryPoints: './src/main.ts',
  outdir: './dist',
  splitting: true,
  chunkNames: 'chunks/[name]-[hash]',
  tsconfig: './tsconfig.json',
  loader: {
    '.glsl': 'text'
  }
}

上面的配置就是告诉 esbuild 将 glsl 作为文本来加载, 在 ts 或 js 文件中可以直接 import 导入使用,代码如下:

import vertex from './particle-layer.vertex.glsl'
import fragment from './particle-layer.fragment.glsl'

现在切换到 Vite 做转译和打包工具, 发现没有类似 esbuild 这样指定文件类型的处理方式。 虽然 Vite 有调用 esbuild , 其配置文件也支持 esbuild 选项, 但是只是 esbuild 的 transform 选项, 不是完整的 build 选项, 因此不能像 esbuild 那样简单指定 loader 来解决。

查看了 Vite 配置文件的 resolve 选项, 发现更多是关于路径方面的配置, 而不是文件内容相关的配置, 也无法解决这个问题。

也尝试了 Vite 配置文件的 optimizeDeps.esbuildOptions , 虽然是完整的 esbuild 选项, 能够指定 loader , 运行时会出错。

export default {
  base: '',
  publicDir: 'public',
  server: {
    host: '127.0.0.1',
    port: 3000,
  },
  optimizeDeps: {
    esbuildOptions: {
      loader: {
        '.glsl': 'text'
      }
    }
  },
}

运行时错误信息如下:

vite v6.0.7 building for production...
✓ 38 modules transformed.
x Build failed in 530ms
error during build:
src/layers/particle-layer/particle-layer-vertex.glsl (1:8): Expected ';', '}' or <eof> (Note that you need plugins to import files that are not JavaScript)
file: ~/Developer/javascript//wind-demo/src/layers/particle-layer/particle-layer-vertex.glsl:1:8

1: #define SHADER_NAME particle-layer-vertex-shader
           ^
2: #ifdef GL_ES
3: precision highp float;

这看起来应该是直接把 glsl 文件的内容当作 js 了。

那看起来应该是不能通过配置来实现 esbuild 原来的功能, 只能写一个插件来解决吧, 好在插件比较简单, 很容易实现, 代码如下:

function glslPlugin() {
  return {
    name: 'glsl-plugin',
    transform(code, id) {
      if (id.endsWith('.glsl')) {
        return {
          code: 'export default `' + code + '`;',
          map: null,
        };
      }
    },
  };
}

当然, 插件也可以写的更加复杂一些, 比如去除 glsl 文件中的空格/注视,甚至混淆等, 不过这些都可以后期再处理, 先能用再说。

最终的 Vite 配置文件如下:

export default defineConfig({
  base: '',
  publicDir: 'public',
  server: {
    host: '127.0.0.1',
    port: 3000,
  },
  plugins: [
    glslPlugin()
  ],
  build: {
    target: 'esnext',
  }
});

本博客基于 Tabler CSS 框架, 采用 Jekyll 模板引擎, 使用 Markdown 语法编写。

博客源代码及文章内容采用 AS-IS 协议发布,转载时请 AS-IS 。