Thursday, May 9, 2024
HomeGolangCannot serve WASM from template - Code Evaluation

Cannot serve WASM from template – Code Evaluation


I’m undecided what occurred, as soon as I wrote the beneath issues run easily:

	// Serve wasm_exec.js file with appropriate MIME kind
	http.HandleFunc("/scripts/wasm_exec.js", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content material-Kind", "software/javascript")
		http.ServeFile(w, r, "/scripts/wasm_exec.js")
	})

	// Serve major.wasm file with appropriate MIME kind
	http.HandleFunc("/wasm/major.wasm", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content material-Kind", "software/wasm")
		http.ServeFile(w, r, "/wasm/major.wasm")
	})

Afterward I dedicated them, and the app nonetheless working easily!!

Beneath is my full code:

// major.go
bundle major

import (
	"html/template"
	"log"
	"web/http"
)

// Outline person entry ranges
var userAccessLevels = map[string][]string{
	"supervisor":           {"edit"},
	"auditor":           {"readonly"},
	"limitedAccessUser": {"readonly"},
	"supervisor":        {"edit", "no-access"},
}

// Pattern knowledge for the desk
var tableData = []struct {
	ID    int
	Identify  string
	Position  string
	Electronic mail string
}{
	{1, "John Doe", "supervisor", "john@instance.com"},
	{2, "Jane Doe", "auditor", "jane@instance.com"},
	{3, "Alice", "limitedAccessUser", "alice@instance.com"},
	{4, "Bob", "supervisor", "bob@instance.com"},
}

func major() {
	// utilizing GET /{$} imply / solely, however utilizing GET / imply / and something after it which can trigger routes battle
	http.Deal with("GET /house", loggingMiddleware(http.HandlerFunc(homePage)))
	http.Deal with("GET /base", loggingMiddleware(http.HandlerFunc(baseHandler)))

	http.HandleFunc("GET /{$}", handler)

	// // Serve wasm_exec.js file with appropriate MIME kind
	// http.HandleFunc("/scripts/wasm_exec.js", func(w http.ResponseWriter, r *http.Request) {
	// 	w.Header().Set("Content material-Kind", "software/javascript")
	// 	http.ServeFile(w, r, "/scripts/wasm_exec.js")
	// })

	// // Serve major.wasm file with appropriate MIME kind
	// http.HandleFunc("/wasm/major.wasm", func(w http.ResponseWriter, r *http.Request) {
	// 	w.Header().Set("Content material-Kind", "software/wasm")
	// 	http.ServeFile(w, r, "/wasm/major.wasm")
	// })

	//http.Deal with("https://discussion board.golangbridge.org/", http.FileServer(http.Dir("./static")))
	http.Deal with("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))

	// Begin the server with CSP headers
	http.ListenAndServe(":8080", nil)
}

func baseHandler(w http.ResponseWriter, r *http.Request) {
	// Outline templates
	//t := template.Should(template.ParseFiles("template/base.html", "template/physique.html"))
	t, err := template.ParseFiles("template/base.html", "template/physique.html") //)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// Execute base template
	if err := t.Execute(w, nil); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

func handler(w http.ResponseWriter, r *http.Request) {
	t, err := template.ParseFiles("template/index.html")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	t.Execute(w, nil)
}

func homePage(w http.ResponseWriter, r *http.Request) {
	userType := "supervisor"
	accessLevels, okay := userAccessLevels[userType]
	if !okay {
		http.Error(w, "Invalid person kind", http.StatusBadRequest)
		return
	}
	log.Println(accessLevels)

	t, err := template.ParseFiles("template/homePage.html")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	knowledge := struct {
		Title   string
		Message string
		Roles   []string
		Entry  map[string]string
		Desk   []struct {
			ID    int
			Identify  string
			Position  string
			Electronic mail string
		}
	}{
		Title:   "Welcome",
		Message: "That is the Dwelling Web page",
		Roles:   accessLevels,
		Entry:  makeAccessMap(accessLevels),
		Desk:   tableData,
	}
	t.Execute(w, knowledge)
}

func loggingMiddleware(subsequent http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Printf("Request acquired: %s %s", r.Methodology, r.URL.Path)
		subsequent.ServeHTTP(w, r)
		log.Println("Request dealt with efficiently")
	})
}

func makeAccessMap(accessLevels []string) map[string]string {
	accessMap := make(map[string]string)
	for _, degree := vary accessLevels {
		accessMap[level] = degree
	}
	return accessMap
}

And the Net Meeting recordsdata are constructed from:

// base.go
//go:construct js && wasm

bundle major

import (
	"encoding/json"
	"fmt"
	"syscall/js"
)

var (
	international   js.Worth
	doc js.Worth
)

func major() {
	international = js.World()
	doc = international.Get("doc") // Cache doc for effectivity

	international.Set("handleData", js.FuncOf(handleData))
	international.Set("notifyme", js.FuncOf(notifyme))
	//	international.Set("clickCallback", js.FuncOf(clickCallback))

	choose {} // Block major thread
}

func handleData(this js.Worth, args []js.Worth) interface{} {
	if len(args) < 2 {
		return nil // Deal with invalid variety of arguments gracefully
	}

	num := args[0].Int()
	textual content := args[1].String()

	knowledge := map[string]interface{}{
		"quantity": num,
		"textual content":   textual content,
	}

	jsonData, err := json.Marshal(knowledge)
	if err != nil {
		// Deal with potential marshalling errors (optionally available)
		log(fmt.Sprintf("Error: %v", err))
		return nil
	}

	addElement(jsonData)
	return string(jsonData)
}

func notifyme(this js.Worth, args []js.Worth) interface{} {
	script := `
	new perform() {
		let knowledge = "only a reminder";
		let para = doc.createElement("p");
		let node = doc.createTextNode(knowledge);
		para.appendChild(node);
		doc.physique.appendChild(para);
	}();
    `
	international.Name("eval", script)
	log("a Simply reminder ought to be printed on the web page")

	return nil
}

func log(message string) {
	js.World().Get("console").Name("log", message)
}

func createElement(tagName string) js.Worth {
	return js.World().Get("doc").Name("createElement", tagName)
}

func addElement(jsonData []byte) {
	var parsedData map[string]interface{}
	err := json.Unmarshal(jsonData, &parsedData)
	if err != nil {
		// Deal with potential unmarshalling errors (optionally available)
		return
	}

	textual content := parsedData["text"].(string)
	num := parsedData["number"].(float64)

	node := doc.Name("createTextNode", fmt.Sprintf("%v: What's the %.2f?", textual content, num)) // Format quantity with 2 decimal locations

	para := createElement("p")
	para.Name("appendChild", node)

	// Create a js.Func object for clickCallback
	clickCallbackFunc := js.FuncOf(clickCallback)
	addEventListener(para, "click on", clickCallbackFunc)

	physique := doc.Get("physique")
	physique.Name("appendChild", para)
}

func addEventListener(el js.Worth, occasion string, callback js.Func) {
	el.Name("addEventListener", occasion, callback)
}

func clickCallback(this js.Worth, args []js.Worth) interface{} {
	log("Para had been clicked")
	return nil
}

// $env:GOOS = "js"
// $env:GOARCH = "wasm"
// $CGO_LDFLAGS="-Wl,-LTO"
// go construct -ldflags="-s -w" -o base.wasm -tags js,wasm base.go
// go construct -o base.wasm -tags js,wasm base.go

And

// physique.go
//go:construct js && wasm

bundle major

import (
	"syscall/js"
)

var (
	international js.Worth
)

func init() {
	international = js.World()
}

func major() {
	international.Set("handleClick", js.FuncOf(handleClick))

	choose {} // Block major thread
}

func handleClick(this js.Worth, args []js.Worth) interface{} {
	alert("Whats up, world!") // Use customized alert perform
	return nil
}

func alert(message string) {
	international.Name("alert", message)
}

// $env:GOOS = "js"
// $env:GOARCH = "wasm"
// $CGO_LDFLAGS="-Wl,-LTO"
// go construct -ldflags="-s -w" -o physique.wasm -tags js,wasm physique.go
// go construct -o physique.wasm -tags js,wasm physique.go

The generated wasm recordsdata had been moved to the folder static/wasm

And within the static/script folder I’ve:

// wasm_load.js
const modules = {};
let wasm;

async perform loadWasmModule(module) {
    modules[module] = new Go();

    strive {
        const response = await fetch(`/static/wasm/${module}.wasm`);
        const bytes = await response.arrayBuffer();
        const result_1 = await WebAssembly.instantiate(bytes, modules[module].importObject);
        wasm = result_1.occasion;
        modules[module].run(wasm);
    } catch (error) {
        console.error(`Didn't load wasm module ${module}:`, error);
    }
}

The template recordsdata used are:

// template/base.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta title="viewport" content material="width=device-width, initial-scale=1.0">
    <title>Base Template</title>
    <script src="https://discussion board.golangbridge.org/static/scripts/wasm_exec.js"></script>
    <script src="/static/scripts/wasm_load.js"></script>
</head>
<physique>
    <header>
        <h1>Welcome to My Web site</h1>
    </header>
    
    <major>
        {{template "content material" .}}
    </major>
    
    <footer>
        <p>&copy; 2024 My Web site. All rights reserved.</p>
        <button onclick="notifyme()">notifyme</button>
    </footer>

</physique>

<script>
    loadWasmModule('base')
</script>

</html>

And

//template/physique.js
{{outline "content material"}}
    <h2>Physique Content material</h2>
    <button onclick="handleClick()">Click on me</button>
    <p>That is the content material of the physique template.</p>
    <button onclick="callHandleData()">handleData</button>


<script>
  loadWasmModule('physique')
  perform callHandleData() {
    let knowledge = handleData(46, "Whats up, World!");
    // Parse the info utilizing JSON.parse  // Parse the info utilizing JSON.parse
    let parsedData = JSON.parse(knowledge);  // Double stringify for security

    // Entry the textual content property from the parsed object
    let textual content = parsedData.textual content;
    let num = parsedData.quantity;
    alert(knowledge)
    alert(textual content + " What's the "+ num);  // Or use textual content for additional manipulation
  }
</script>

{{finish}}

And

//template.index.html
{{outline "content material"}}
    <h2>Physique Content material</h2>
    <button onclick="handleClick()">Click on me</button>
    <p>That is the content material of the physique template.</p>
    <button onclick="callHandleData()">handleData</button>


<script>
  loadWasmModule('physique')
  perform callHandleData() {
    let knowledge = handleData(46, "Whats up, World!");
    // Parse the info utilizing JSON.parse  // Parse the info utilizing JSON.parse
    let parsedData = JSON.parse(knowledge);  // Double stringify for security

    // Entry the textual content property from the parsed object
    let textual content = parsedData.textual content;
    let num = parsedData.quantity;
    alert(knowledge)
    alert(textual content + " What's the "+ num);  // Or use textual content for additional manipulation
  }
</script>

{{finish}}

And

//template/homePage.html
<!DOCTYPE html>
<html>
<head>
    <title>{{.Title}}</title>
    <model>
        /* CSS types right here */
        desk {
            border-collapse: collapse;
            width: 100%;
            table-layout: mounted;
        }

        th, td {
            padding: 3px; /* Adjusted padding for narrower rows */
            border: 1px strong #ddd;
            text-align: left;
            width: 150px; /* Set mounted width for cells */
            overflow: hidden; /* Conceal overflow content material */
            white-space: nowrap; /* Stop wrapping */
        }

        tr:nth-child(even) {
            background-color: #f2f2f2;
        }

        /* tr:hover {
            background-color: #ddd;
        } */

        th {
            background-color: #4CAF50;
            coloration: white;
        }

        .editable {
            background-color: #fff;
        }

        .editable:focus {
            background-color: #f0f0f0;
        }

        /* Outline particular person widths for columns */
        .col1 {
            width: 100px; /* Width for ID column */
        }

        .col2 {
            width: 200px; /* Width for Identify column */
        }

        .col3 {
            width: 150px; /* Width for Position column */
        }

        .col4 {
            width: 250px; /* Width for Electronic mail column */
        }

        /* Fashion for the primary column */
        .first-column {
            background-color: #ffcccb; /* Mild crimson background coloration */
        }

        /* Hover impact for desk cells */
        tbody tr:hover td,
        tbody tr td:hover {
            background-color: #ffe5cc; /* Mild orange background coloration */
        }

        @media display and (max-width: 600px) {
            desk {
                border: 0;
            }
            th, td {
                border: none;
                show: block;
                padding: 3px; /* Adjusted padding for narrower rows */
                width: 100%; /* Set width to 100% for full width in smaller screens */
            }
            th {
                background-color: #4CAF50;
                coloration: white;
                text-align: left;
            }
        }
    </model>
</head>
<physique>
    <h1>{{.Title}}</h1>
    <p>{{.Message}}</p>
    <p>Person roles are: {{.Roles}}</p>

    <div>
        {{vary $position, $entry := .Entry}}
            <p>Position: {{$position}}, Entry: {{$entry}}</p>
        {{finish}}
    </div>

    {{ $readOnly := false }}
    {{ $isVisible := true }}
    {{ vary .Roles }}
        {{ if eq . "no-access" }}
            {{ $isVisible = false }}
        {{ finish }}
        {{ if eq . "readonly" }}
            {{ $readOnly = true }}
        {{ finish }}
    {{ finish }}

    {{ if $isVisible }}
        <div data-access="{{if $readOnly}} readonly {{finish}}">
            <enter kind="textual content" {{if $readOnly}} readonly {{finish}} placeholder="Enter textual content right here">
        </div>
    {{ else }}
        <p>This content material just isn't accessible.</p>
    {{ finish }}


    
    <desk border="1">
        <tr>
            <th class="col1">ID</th>
            <th class="col2">Identify</th>
            <th class="col3">Position</th>
            {{ if $isVisible }}
            <th class="col4" data-access="{{if $readOnly}}readonly{{finish}}">Electronic mail</th>
            {{ finish }}
        </tr>
        {{vary .Desk}}
            <tr>
                <td contenteditable="true" class="editable col1 first-column">{{.ID}}</td>
                <td contenteditable="true" class="editable col2">{{.Identify}}</td>
                <td contenteditable="true" class="editable col3">{{.Position}}</td>
                {{ if $isVisible }}
                <td contenteditable="true" class="editable col4" data-access="{{if $readOnly}}readonly{{finish}}">{{.Electronic mail}}</td>
                {{ finish }}
            </tr>
        {{finish}}
    </desk>

    <script>
        // Add occasion listeners to every editable cell
        const editableCells = doc.querySelectorAll('.editable');
        editableCells.forEach(cell => {
            cell.addEventListener('enter', perform() {
                // Add your logic right here to deal with enter modifications
                console.log('Cell content material modified:', this.textContent);
            });
        });

                // Add occasion listeners to every cell within the desk physique
                const cells = doc.querySelectorAll('tbody td');
        cells.forEach(cell => {
            cell.addEventListener('mouseover', perform() {
                // Add highlighted class to the row
                this.parentNode.classList.add('highlighted');

                // Add highlighted class to all cells in the identical column
                const index = Array.from(this.parentNode.youngsters).indexOf(this);
                const allRows = doc.querySelectorAll('tbody tr');
                allRows.forEach(row => {
                    row.youngsters[index].classList.add('highlighted');
                });
            });

            cell.addEventListener('mouseout', perform() {
                // Take away highlighted class from the row
                this.parentNode.classList.take away('highlighted');

                // Take away highlighted class from all cells in the identical column
                const index = Array.from(this.parentNode.youngsters).indexOf(this);
                const allRows = doc.querySelectorAll('tbody tr');
                allRows.forEach(row => {
                    row.youngsters[index].classList.take away('highlighted');
                });
            });
        });
    </script>
</physique>
</html>

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments