Webpack dynamic imports
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.
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:
tsx
import {Img ,useCurrentFrame } from "remotion";export constDynamicImports :React .FC = () => {constframe =useCurrentFrame ();constimg = "./assets/image" +frame + ".png";return <Img src ={require (img )} />;};
tsx
import {Img ,useCurrentFrame } from "remotion";export constDynamicImports :React .FC = () => {constframe =useCurrentFrame ();constimg = "./assets/image" +frame + ".png";return <Img src ={require (img )} />;};
may result in:
bash
Error: Cannot find module './image0.png'
bash
Error: Cannot find module './image0.png'
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
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
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:
tsx
import {Img ,useCurrentFrame } from "remotion";export constDynamicImports :React .FC = () => {constframe =useCurrentFrame ();return <Img src ={require ("./assets/image" +frame + ".png")} />;};
tsx
import {Img ,useCurrentFrame } from "remotion";export constDynamicImports :React .FC = () => {constframe =useCurrentFrame ();return <Img src ={require ("./assets/image" +frame + ".png")} />;};
Please read the Webpack documentation page about this behavior if you would like to learn more.
Import assets at runtime
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:
tsx
import {getInputProps ,Img } from "remotion";constDynamicAsset :React .FC = () => {constinputProps =getInputProps (); // {"imageSrc": "./assets/img0.png"}return <Img src ={require (inputProps .imageSrc )} />;};
tsx
import {getInputProps ,Img } from "remotion";constDynamicAsset :React .FC = () => {constinputProps =getInputProps (); // {"imageSrc": "./assets/img0.png"}return <Img src ={require (inputProps .imageSrc )} />;};
This cannot work because Webpack has no ideas 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:
tsx
import {getInputProps ,Img } from "remotion";constDynamicAsset :React .FC = () => {constinputProps =getInputProps (); // {"imageSrc": "img0.png"}// Works!return <Img src ={require ("./assets/" +inputProps .imageSrc )} />;};
tsx
import {getInputProps ,Img } from "remotion";constDynamicAsset :React .FC = () => {constinputProps =getInputProps (); // {"imageSrc": "img0.png"}// Works!return <Img src ={require ("./assets/" +inputProps .imageSrc )} />;};
Struggling?
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.