React project - media BlocklyOption not working

107 views
Skip to first unread message

Sameer Apte

unread,
Mar 20, 2024, 12:02:10 PM3/20/24
to Blockly
Hi,

I am using Blockly in my react(next.js) project.
Plugin version is "blockly": "^10.4.3",
However what I notice is that when I render (& initialise ) Blockly component from a url which is like http://localhost:3000/abc it is able to get the medias correctly as it forms the urls like 
http://localhost:3000/media/sprites.png
http://localhost:3000/media/click.mp3

But when I render (& initialise ) Blockly component from a url which is like http://localhost:3000/abc/xyz i.e. url which is not at root level, it fails to find the medias as it tries to get media using urls as below
http://localhost:3000/abc/xyz/media/sprites.png
http://localhost:3000/abc/xyz/media/click.mp3

As per Blockly docs, I tried playing a lot with media opetion value with no luck.
Am I missing anything?
useEffect(() => {
const {initialXml, initialJson, children, callback, toolBoxJson, ...rest} = props;
if (blocklyDivRef.current) {
primaryWorkspace.current = Blockly.inject(
blocklyDivRef.current,
{
toolbox: toolBoxJson,
media: '/',
...rest
},


Regards,
Sameer Apte

Maribeth Moffatt

unread,
Mar 20, 2024, 2:32:03 PM3/20/24
to Blockly
Hi,

The media option takes in a full URL to the `media` directory. The directory is not required to be named 'media' so Blockly does not assume that. In other words, the value you pass in needs to include the name of the directory containing the files. `/` is unlikely to be a valid name unless you're hosting all of the files at the root level of your server.

Blockly isn't doing anything fancy with this value. Essentially, Blockly creates HTML that would look like this
`<img src="${MEDIA_PATH}/arrow.png">`. You just need to supply the `media` option so that this URL resolves correctly, following normal url resolution rules.

If your media is actually located at localhost:3000/media
and your Blockly page is located at localhost:3000/abc/xyz
Then I would try the URL `/media`.

You haven't said where your media directory is actually located, so I'm just guessing. If that doesn't work and you would like further assistance I would need to know the actual location of your media directory.

Best,
Maribeth

Sameer Apte

unread,
Mar 20, 2024, 5:58:12 PM3/20/24
to Blockly
Thanks Maribeth for getting back.

Your guess is right. they are available under /media and when I read the docs I thought it would be exactly how you explained.
Only thing is - no matter what I set media value to be, it seems to be ignoring it and constructing the url based on url in browser.

Note that this is used through React (Next.js) project and media files are placed under the folder called public which as per next.js holds publicly available assets.

const {initialXml, initialJson, children, callback, toolBoxJson, ...rest} = props;
if (blocklyDivRef.current) {
console.log("Trying with /media now")

primaryWorkspace.current = Blockly.inject(
blocklyDivRef.current,
{
toolbox: toolBoxJson,
// media: 'http://some-non-existant-url/',
media: '/media',
...rest
},
);

Would it be possible for you / someone to point me on github where this logic resides to derive media asset path please? I am using package version "blockly""^10.4.3",

Regards,
Sameer Apte

Maribeth Moffatt

unread,
Mar 20, 2024, 7:17:59 PM3/20/24
to Blockly
Sure, the media URLs are composed in multiple places, but here's one example: https://github.com/google/blockly/blob/199c00afd5dfcc8f18518b7101c42afc3aadef9e/core/inject.ts#L360
`pathToMedia` is derived from the options struct here: https://github.com/google/blockly/blob/199c00afd5dfcc8f18518b7101c42afc3aadef9e/core/options.ts#L143 - basically, if you don't pass in a 'media' option, we'll use our default which is hosted assets from app engine. if you do pass in a value, we'll just make sure it ends with a slash.

But I am confused by your response. First you say that "they are available under /media" and later you say "files are placed under the folder called public" - which is it? If your media is hosted under `/public/media` then that is the string you'd need to pass in. Do note that you probably need to configure these assets to be copied into that directory during your build process, unless React has some magic that knows you want them placed there. I'm not familiar with React and that is not a blockly-specific question so I'd have to send you elsewhere for support with that, unfortunately.

I would start by confirming that these assets are actually being hosted by your server in the location you think they are.

Best,
Maribeth

Sameer Apte

unread,
Mar 21, 2024, 10:24:44 AM3/21/24
to Blockly
Thanks Maribeth.
In a Next.js project, the public folder is a special directory that allows you to serve static assets directly from the root URL of your application. Any files placed in the public folder are served at the root of your website without being processed by Next.js's build system. So when I put media directory directly inside public folder, it becomes accessible at root  as below
I had used the reference example given by Blockly team so was hoping even if it is to do with React someone might be able to assist.
No probs. I will try and if can figure out what is going on here will put update here in future.
Thanks

Maribeth Moffatt

unread,
Mar 21, 2024, 11:51:47 AM3/21/24
to Blockly
Gotcha. If you pass `/media` as the option string, what URL does the browser try to load the assets from? You should be able to see this in the network tab of chrome console.

You could also try passing a relative URL, if you know your blockly app is two layers down from root, try `../../media`

Best,
Maribeth

Sameer Apte

unread,
Apr 4, 2024, 6:50:33 AM4/4/24
to Blockly
Hi Maribeth,

Sorry about the delayed response.
But I got to the bottom of this.
Looks like if one is using react wherein Blockly is used as Component as shown in react example samples.. we need to control all these aspects individually as attributes of the BlocklyComponent.

BlocklyOptions as json config object does not mean anything in that world.
I had to change media url as below to get it working.
Thanks for your help Maribeth.
<BlocklyComponent readOnly={false}
trashcan={true}
media={'/media/'}
move={{
scrollbars: true,
drag: true,
wheel: true
}}
horizontalLayout={false}
zoom={{
controls: true,
wheel: true,
startScale: 1,
maxScale: 3,
minScale: 0.3,
scaleSpeed: 1.2
}}


Regards,
Sameer Apte

Reply all
Reply to author
Forward
0 new messages