Is it possible to use vanilla js, html and css instead of a framework

If I want to serve a completely static webpage do I have to use something like react or vue? When I read through the frontend documentation I see the following:

“Currently, you can only use Javascript to implement the front-end for your canister. This tutorial illustrates using the React framework to manage the Document Object Model (DOM) for your canister. Because React has its own custom DOM syntax, you need to modify the webpack configuration to compile the front-end code, which is written in JSX. For more information about learning to use React and JSX, see Getting started on the React website

Does that mean that there is no way to just directly serve a html page?

Hey Fulco,

Does that mean that there is no way to just directly serve a html page?

Not at all! Right now we are currently using webpack to bundle your UI assets, so one thing you could do is something like this:

Have an index.html file in an asset canister (https://sdk.dfinity.org/docs/developers-guide/tutorials/explore-templates.html#default-frontend)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
</body>
</html>

and have an index.js file:

// import the canister (using webpack to resolve the JS for you)
import canister from "ic:canisters/{your-canister-name}";

// use the asset canister's retrieve method to request a file (the `index.html` file from above)
canister.retrieve('index.html').then( htmlBytes => {
  // now that you have the html, decode it and create a new element
  const html = new TextDecoder().decode(new Uint8Array(htmlBytes));
  const el = new DOMParser().parseFromString(html, "text/html");
  // insert your HTML into the bootstrap HTML under the element with id `"app"`
  document.body.replaceChild(el.firstElementChild, document.getElementById('app'));
})

Let me know if you have any questions, I may have taken a few shortcuts here for simplicity’s sake.

5 Likes

Thanks for the reply! I think in your example htmlBytes is supposed to be result? However when I try that I get the following error:

VM372:1 Uncaught (in promise) TypeError: Failed to execute 'decode' on 'TextDecoder': The provided value is not of type '(ArrayBuffer or ArrayBufferView)' at eval (eval at _loadJs (bootstrap.js:formatted:9872), <anonymous>:1:1217)

this is my setup btw a new project on with dfx new carbosix in 6.0

2 Likes

This was very helpful @andrew_DFN, thank you.
I got this to build ok on 6.0, however, it’s not displaying on the frontend.
Are any changes to main.mo required?

Right you are, @Fulco! I missed a critical step, my apologies.

I edited my code above, but instead of const html = new TextDecoder(result) it should be const html = new TextDecoder().decode(new Uint8Array(result));

Here’s a link to my example repo with the above stuff workin :slight_smile: hope this helps!

3 Likes

Hey @Carbosix let me know if the above code changes work for you? Shouldn’t require changes to main.mo, no.

2 Likes

Works perfectly!!! Thanks again!