Skip to main content

Webpack 动态导入

在 Remotion 中一个常见的需求是从动态路径导入资源。这意味着有时你并不知道应当事先导入的资源的确切路径,并且希望在运行时进行计算。

🌐 A common need in Remotion is to import assets from dynamic paths. This means that sometimes you don't know the exact path of an asset that should be imported upfront and you want to calculate it during runtime.

这可能在 Webpack 中成为一个意想不到的障碍。在本页面中,我们收集了一些处理动态资源的技巧。

🌐 This can become an unexpected hurdle in Webpack. On this page we collect some tips how to handle dynamic assets.

以这个情景为例:

🌐 Take this scenario for an example:

import { Img, useCurrentFrame } from "remotion";

export const DynamicImports: React.FC = () => {
  const frame = useCurrentFrame();
  const img = "./assets/image" + frame + ".png";
  return <Img src={require(img)} />;
};

可能导致:

🌐 may result in:

Error: Cannot find module './image0.png'

即使文件存在。这是因为 Webpack 需要通过静态代码分析来确定它应该打包哪些资源,但无法做到这一点。

🌐 even if the file exists. This is because Webpack needs to figure out using static code analysis which assets it should bundle and cannot do so.

🌐 Recommended: Use staticFile() instead

我们建议你将资源放入 public/ 文件夹中,并使用 staticFile() 来引用它。这种新方法不会受到底层问题的影响。

🌐 We recommend that you put the asset inside the public/ folder and use staticFile() to reference it. This new way does not suffer from the underlying problem.

正确地编写动态表达式

🌐 Write dynamic expressions correctly

虽然顶部的示例没有起作用,但如果将表达式放在 require()import() 语句中,Webpack 足够智能可以做到这一点。在这种情况下,即使该资源从未被使用,Webpack 也会自动打包 assets/image 文件夹中的所有 .png 文件。

🌐 While the example at the top did not work, Webpack is smart enough to do so if you place your expression inside the require() or import() statement. In this case, Webpack will automatically bundle all .png files in the assets/image folder even if the asset is never used.

以下 确实 可行:

🌐 The following does work:

import { Img, useCurrentFrame } from "remotion";

export const DynamicImports: React.FC = () => {
  const frame = useCurrentFrame();
  return <Img src={require("./assets/image" + frame + ".png")} />;
};

如果你想了解更多信息,请阅读Webpack 文档页面关于此行为的说明。

🌐 Please read the Webpack documentation page about this behavior if you would like to learn more.

在运行时导入资源

🌐 Import assets at runtime

让我们设想一个场景,其中应该导入的资源是完全未知的,并且将在运行时读取,例如通过一个input prop:

🌐 Let's imagine a scenario where the asset that should be imported is completely unknown and will be read at runtime, for example through an input prop:

import { getInputProps, Img } from "remotion";

const DynamicAsset: React.FC = () => {
  const inputProps = getInputProps(); // {"imageSrc": "./assets/img0.png"}
  return <Img src={require(inputProps.imageSrc as string)} />;
};

这行不通,因为 Webpack 根本不知道它需要打包哪些资源。因此,导入必须失败。像上面一样,你可以通过在 require() 语句中放入一个表达式来强制 Webpack 打包整个 assets 文件夹:

🌐 This cannot work because Webpack has no idea which assets it has to bundle. Therefore the import has to fail. Like above, you can force Webpack to bundle the whole assets folder by putting an expression inside the require() statement:

import { getInputProps, Img } from "remotion";

const DynamicAsset: React.FC = () => {
  const inputProps = getInputProps(); // {"imageSrc": "img0.png"}
  // Works!
  return <Img src={require(("./assets/" + inputProps.imageSrc) as string)} />;
};

挣扎吗?

🌐 Struggling?

如果你在导入资源时仍然遇到问题,请在 Discord 上联系我们或提交一个问题。我们很想听取你关于我们如何改进的意见,并会帮助你解决问题。

🌐 If you still have troubles importing your assets, hit us up on Discord or file an issue. We'd love to hear your input about how we can improve and will help you out.