three.js 在 cdn 上使用 svelte 或 react

three.js over cdn using svelte or react

有没有什么方法可以构建我的 svelte 或 React 应用程序,three.js 模块(我通常使用 npm 导入)将被声明为脚本标签,该标签将从加速网络?我想保留框架的优势,但也能够减少我的最终包大小,因为我的大部分包都包含三个代码。

谢谢你的智慧

是的,您可以执行以下操作:

在您的“index.html”文件中,您可以按如下方式从 CDN 导入 js 文件:

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>

然后,在你想要使用它的文件中,例如 React 组件,你可以执行以下操作:

const THREE = window.THREE;

这将替换您的导入语句,它本来是 import * as THREE from "three";import THREE from "three";

有两种方法可以实现减小捆绑包大小的目标:

  1. 从 CDN 导入(您的建议)
  2. 代码拆分

从 CDN 导入

为了保持 ESModules 的语义,您可以简单地将当前的 three.js 导入替换为来自 npm CDN 的 URL,例如 unpkg:

Pros Cons
No extra configuration needed Slower to load, as browser needs to spin up new connections to access third-party CDN

异步

<script>
  // App.svelte

  import('https://unpkg.com/three@0.133.1/build/three.min.js').then(({ default: THREE }) => {
    // your code here
  });
</script>

同步

Note: Importing like this blocks the rest of your script from loading while three.js is downloading, which defeats the purpose of the whole shebang. It's just here for completeness

<script>
  // App.svelte

  import { default as THREE } from 'https://unpkg.com/three@0.133.1/build/three.min.js';

  // your code here
</script>

代码拆分

此方法利用了您已经在使用捆绑器这一事实(可能 rollupvitewebpack)。这个答案将集中在 rollup 上,因为它是 svelte 示例中使用的默认值。

Pros Cons
Faster to load, as browser can use existing connections to access first-party resources More complicated to get set up

异步

在您的 rollup.config.js 文件中,确保 output.format 设置为 'esm' 并且设置 output.dir 而不是 output.file

// rollup.config.js

import svelte from 'rollup-plugin-svelte';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import postcss from 'rollup-plugin-postcss';

const production = !process.env.ROLLUP_WATCH;

export default {
  input: 'src/index.js',
  output: {
    sourcemap: !production,
    format: 'esm',
    name: 'app',
    dir: 'public',
  },
  plugins: {
    // your plugins

    svelte({
      compilerOptions: {
        dev: !production,
      },
    }),

    postcss({
      extract: 'bundle.css',
    }),

    resolve({
      browser: true,
      dedupe: ['svelte'],
    }),

    commonjs(),
  }
}
<script>
  // App.svelte

  import('three').then(({ default: THREE }) => {
    // your code here
  });
</script>

Note: There is no synchronous way due to how code-splitting is evaluated at compile time. Plus it doesn't make much sense to do it like that anyways.