Skip to content

Instantly share code, notes, and snippets.

@mopeneko
Created December 5, 2022 15:48
Show Gist options
  • Save mopeneko/0c373ff7d9a8a138c46719606c89e17d to your computer and use it in GitHub Desktop.
Save mopeneko/0c373ff7d9a8a138c46719606c89e17d to your computer and use it in GitHub Desktop.
GoのSSRに部分的にReact+TSXを導入する
package main
import (
"io"
"log"
"net/http"
"text/template"
)
const (
tmpl = `
<html>
<body>
<div id="foo"></div>
<script src="{{ .BabelURL }}" crossorigin></script>
{{ .InitTSX }}
<script type="text/babel" data-type="module" data-presets="tsx,react">
import React, { useState } from '{{ .ReactURL }}';
import { render } from '{{ .ReactDOMURL }}';
const Component = () => {
const [ count, setCount ] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount((prev) => prev + 1)}>Click</button>
</div>
);
};
render(<Component />, document.getElementById('foo'));
</script>
</body>
</html>
`
initTSX = `
<script>
Babel.registerPreset('tsx', {
presets: [
[Babel.availablePresets['typescript'], {allExtensions: true, isTSX: true}]
],
});
</script>
`
)
func main() {
t, err := template.New("tmpl").Parse(tmpl)
if err != nil {
log.Fatalf("failed to parse template: %+v", err)
}
http.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
params := map[string]any{
"BabelURL": "https://unpkg.com/@babel/standalone@7.20.6/babel.min.js",
"ReactURL": "https://cdn.skypack.dev/pin/react@v17.0.1-yH0aYV1FOvoIPeKBbHxg/mode=imports,min/optimized/react.js",
"ReactDOMURL": "https://cdn.skypack.dev/pin/react-dom@v17.0.1-oZ1BXZ5opQ1DbTh7nu9r/mode=imports,min/optimized/react-dom.js",
"InitTSX": initTSX,
}
t.Execute(w, params)
if err != nil {
log.Printf("failed to execute template: %+v", err)
w.WriteHeader(http.StatusInternalServerError)
io.WriteString(w, "internal server error")
}
})
// Web サーバーを起動する
log.Fatal(http.ListenAndServe(":8080", nil))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment