serve frontend + backend as a one binary

This commit is contained in:
Ankit Patial 2024-11-19 17:16:36 +05:30
parent 5954ec2501
commit e378db58b8
14 changed files with 87 additions and 26 deletions

View File

@ -7,13 +7,15 @@ package main
import (
"fmt"
"net/http"
"strings"
"gitserver.in/patialtech/mux"
"gitserver.in/patialtech/mux/middleware"
"gitserver.in/patialtech/rano/cmd/server/handler"
"gitserver.in/patialtech/rano/bin/server/handler"
"gitserver.in/patialtech/rano/config"
"gitserver.in/patialtech/rano/graph"
"gitserver.in/patialtech/rano/util/logger"
"gitserver.in/patialtech/rano/web"
)
func main() {
@ -24,6 +26,7 @@ func main() {
// CORS
r.Use(middleware.CORS(middleware.CORSOption{
AllowedHeaders: []string{"Content-Type"},
AllowedOrigins: []string{config.Read().WebURL},
MaxAge: 60,
}))
// Secure Headers
@ -40,7 +43,37 @@ func main() {
// catch all
r.GET("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hello there"))
var (
resourcePath string
path = r.URL.Path
)
if strings.HasPrefix(path, "/_app") {
resourcePath = "public/build" + path
} else if strings.HasSuffix(path, ".png") ||
strings.HasSuffix(path, ".ico") ||
strings.HasSuffix(path, ".svg") ||
strings.HasSuffix(path, "robot.txt") ||
strings.HasSuffix(path, "site.webmanifest") {
resourcePath = "public" + path
} else {
resourcePath = "public/build/fallback.html"
}
if b, err := web.Public.ReadFile(resourcePath); err != nil {
_, _ = w.Write([]byte("hello there"))
} else {
if strings.HasSuffix(path, ".js") {
w.Header().Set("Content-Type", "text/javascript")
} else if strings.HasSuffix(path, ".css") {
w.Header().Set("Content-Type", "text/css")
} else {
w.Header().Set("Content-Type", http.DetectContentType(b))
}
w.WriteHeader(http.StatusOK)
_, _ = w.Write(b)
}
})
r.Serve(func(srv *http.Server) error {

View File

@ -18,17 +18,13 @@ import (
const (
// projDir need to be same as project code root dir name
projDir = "rano"
EnvDev = "development"
EnvProd = "production"
EnvStage = "staging"
projDir = "rano"
AuthUserCtxKey = "AuthUser"
)
var (
conf *Config
AppEnv Env = EnvDev
AppEnv = "development" // production | staging
)
type (
@ -47,7 +43,7 @@ type (
func init() {
var base string
if AppEnv == EnvDev {
if AppEnv == "development" { // AppEnv will be changed on build time using ldflags -X
wd, _ := os.Getwd()
idx := strings.Index(wd, projDir)
if idx > -1 {
@ -57,6 +53,8 @@ func init() {
base, _ = os.Executable()
}
logger.Info("*** %s", AppEnv)
envVar, err := dotenv.Read(base, fmt.Sprintf(".env.%s", AppEnv))
if err != nil {
panic(err)

View File

@ -1,7 +1,5 @@
import path from 'node:path';
import adapter from '@sveltejs/adapter-static';
const webDir = path.resolve('.', 'web');
/** @type {import('@sveltejs/kit').Config} */
const config = {
@ -9,16 +7,15 @@ const config = {
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
adapter: adapter(),
files: {
appTemplate: path.resolve(webDir, 'app.html'),
routes: path.resolve(webDir, 'routes'),
lib: path.resolve(webDir, 'lib'),
assets: path.resolve(webDir, 'public')
appTemplate: "web/app.html" ,
routes: "web/routes",
lib: "web/lib",
assets: "public/lib"
},
alias: {
$image: path.resolve(webDir, 'assets', 'image'),
$svg: path.resolve(webDir, 'assets', 'svg')
$image: "web/assets/image",
$svg: "web/assets/svg"
},
paths: {
assets: process.env.ASSETS_HOST ?? ''
@ -28,8 +25,8 @@ const config = {
pollInterval: 1000 * 60 * 1 // 5 minutes
},
adapter: adapter({
pages: path.resolve(webDir, 'public', 'build'),
assets: path.resolve(webDir, 'public', 'build'),
pages: "web/public/build",
assets: "web/public/build",
fallback: 'fallback.html',
strict: true
})

View File

@ -1,9 +1,12 @@
version: '3'
dotenv: ['.env.{{.ENV}}']
env:
ENV: development
dotenv: ['.env.{{.ENV}}']
vars:
MOD_NAME: gitserver.in/patialtech/rano
tasks:
install:
@ -14,7 +17,7 @@ tasks:
start-graph:
desc: run graph server
cmds:
- cmd: go run ./cmd/server
- cmd: go run ./bin/server
start-web:
desc: run web in dev mode
@ -44,11 +47,11 @@ tasks:
- cmd: deno task codegen
ent-new:
desc: create new db Emtity
cmd: cd ./db && go run -mod=mod entgo.io/ent/cmd/ent new {{.name}}
desc: create new db Entity
cmd: cd ./db && go run -mod=mod entry.io/ent/cmd/ent new {{.name}}
ent-gen:
desc: genertate from ent schema
desc: generate from ent schema
cmds:
- go generate ./db/ent
@ -61,4 +64,17 @@ tasks:
desc: apply automatically migration using Ent schema
cmds:
- task: ent-gen
- go run ./cmd/migrate-up
- go run ./bin/migrate-up
build-web-prod:
desc: apply automatically migration using Ent schema
cmds:
- deno task build
env:
ASSETS_HOST:
build-prod:
desc: apply automatically migration using Ent schema
cmds:
- task: build-web-prod
- CGO_ENABLED=0 go build -trimpath -ldflags "-s -w" -ldflags "-X '{{.MOD_NAME}}/config.AppEnv=production'" -o ./server ./bin/server

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 B

BIN
web/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,11 @@
{
"name": "",
"short_name": "",
"icons": [
{ "src": "/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png" }
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

6
web/web.go Normal file
View File

@ -0,0 +1,6 @@
package web
import "embed"
//go:embed public public/build/_app
var Public embed.FS