serve frontend + backend as a one binary
This commit is contained in:
		| @@ -7,13 +7,15 @@ package main | |||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net/http" | 	"net/http" | ||||||
|  | 	"strings" | ||||||
| 
 | 
 | ||||||
| 	"gitserver.in/patialtech/mux" | 	"gitserver.in/patialtech/mux" | ||||||
| 	"gitserver.in/patialtech/mux/middleware" | 	"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/config" | ||||||
| 	"gitserver.in/patialtech/rano/graph" | 	"gitserver.in/patialtech/rano/graph" | ||||||
| 	"gitserver.in/patialtech/rano/util/logger" | 	"gitserver.in/patialtech/rano/util/logger" | ||||||
|  | 	"gitserver.in/patialtech/rano/web" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func main() { | func main() { | ||||||
| @@ -24,6 +26,7 @@ func main() { | |||||||
| 	// CORS | 	// CORS | ||||||
| 	r.Use(middleware.CORS(middleware.CORSOption{ | 	r.Use(middleware.CORS(middleware.CORSOption{ | ||||||
| 		AllowedHeaders: []string{"Content-Type"}, | 		AllowedHeaders: []string{"Content-Type"}, | ||||||
|  | 		AllowedOrigins: []string{config.Read().WebURL}, | ||||||
| 		MaxAge:         60, | 		MaxAge:         60, | ||||||
| 	})) | 	})) | ||||||
| 	// Secure Headers | 	// Secure Headers | ||||||
| @@ -40,7 +43,37 @@ func main() { | |||||||
| 
 | 
 | ||||||
| 	// catch all | 	// catch all | ||||||
| 	r.GET("/", func(w http.ResponseWriter, r *http.Request) { | 	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 { | 	r.Serve(func(srv *http.Server) error { | ||||||
| @@ -18,17 +18,13 @@ import ( | |||||||
|  |  | ||||||
| const ( | const ( | ||||||
| 	// projDir need to be same as project code root dir name | 	// projDir need to be same as project code root dir name | ||||||
| 	projDir  = "rano" | 	projDir        = "rano" | ||||||
| 	EnvDev   = "development" |  | ||||||
| 	EnvProd  = "production" |  | ||||||
| 	EnvStage = "staging" |  | ||||||
|  |  | ||||||
| 	AuthUserCtxKey = "AuthUser" | 	AuthUserCtxKey = "AuthUser" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
| 	conf   *Config | 	conf   *Config | ||||||
| 	AppEnv Env = EnvDev | 	AppEnv = "development" // production | staging | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type ( | type ( | ||||||
| @@ -47,7 +43,7 @@ type ( | |||||||
|  |  | ||||||
| func init() { | func init() { | ||||||
| 	var base string | 	var base string | ||||||
| 	if AppEnv == EnvDev { | 	if AppEnv == "development" { // AppEnv will be changed on build time using ldflags -X | ||||||
| 		wd, _ := os.Getwd() | 		wd, _ := os.Getwd() | ||||||
| 		idx := strings.Index(wd, projDir) | 		idx := strings.Index(wd, projDir) | ||||||
| 		if idx > -1 { | 		if idx > -1 { | ||||||
| @@ -57,6 +53,8 @@ func init() { | |||||||
| 		base, _ = os.Executable() | 		base, _ = os.Executable() | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	logger.Info("*** %s", AppEnv) | ||||||
|  |  | ||||||
| 	envVar, err := dotenv.Read(base, fmt.Sprintf(".env.%s", AppEnv)) | 	envVar, err := dotenv.Read(base, fmt.Sprintf(".env.%s", AppEnv)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		panic(err) | 		panic(err) | ||||||
|   | |||||||
| @@ -1,7 +1,5 @@ | |||||||
| import path from 'node:path'; |  | ||||||
| import adapter from '@sveltejs/adapter-static'; | import adapter from '@sveltejs/adapter-static'; | ||||||
|  |  | ||||||
| const webDir = path.resolve('.', 'web'); |  | ||||||
|  |  | ||||||
| /** @type {import('@sveltejs/kit').Config} */ | /** @type {import('@sveltejs/kit').Config} */ | ||||||
| const 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. | 		// 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. | 		// 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. | 		// See https://kit.svelte.dev/docs/adapters for more information about adapters. | ||||||
| 		adapter: adapter(), |  | ||||||
| 		files: { | 		files: { | ||||||
| 			appTemplate: path.resolve(webDir, 'app.html'), | 			appTemplate: "web/app.html" , | ||||||
| 			routes: path.resolve(webDir, 'routes'), | 			routes: "web/routes", | ||||||
| 			lib: path.resolve(webDir, 'lib'), | 			lib: "web/lib", | ||||||
| 			assets: path.resolve(webDir, 'public') | 			assets: "public/lib" | ||||||
| 		}, | 		}, | ||||||
| 		alias: { | 		alias: { | ||||||
| 			$image: path.resolve(webDir, 'assets', 'image'), | 			$image: "web/assets/image", | ||||||
| 			$svg: path.resolve(webDir, 'assets', 'svg') | 			$svg: "web/assets/svg" | ||||||
| 		}, | 		}, | ||||||
| 		paths: { | 		paths: { | ||||||
| 			assets: process.env.ASSETS_HOST ?? '' | 			assets: process.env.ASSETS_HOST ?? '' | ||||||
| @@ -28,8 +25,8 @@ const config = { | |||||||
| 			pollInterval: 1000 * 60 * 1 // 5 minutes | 			pollInterval: 1000 * 60 * 1 // 5 minutes | ||||||
| 		}, | 		}, | ||||||
| 		adapter: adapter({ | 		adapter: adapter({ | ||||||
| 			pages: path.resolve(webDir, 'public', 'build'), | 			pages: "web/public/build", | ||||||
| 			assets: path.resolve(webDir, 'public', 'build'), | 			assets: "web/public/build", | ||||||
| 			fallback: 'fallback.html', | 			fallback: 'fallback.html', | ||||||
| 			strict: true | 			strict: true | ||||||
| 		}) | 		}) | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								taskfile.yml
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								taskfile.yml
									
									
									
									
									
								
							| @@ -1,9 +1,12 @@ | |||||||
| version: '3' | version: '3' | ||||||
|  |  | ||||||
|  | dotenv: ['.env.{{.ENV}}'] | ||||||
|  |  | ||||||
| env: | env: | ||||||
|   ENV: development |   ENV: development | ||||||
|  |  | ||||||
| dotenv: ['.env.{{.ENV}}'] | vars: | ||||||
|  |   MOD_NAME: gitserver.in/patialtech/rano | ||||||
|  |  | ||||||
| tasks: | tasks: | ||||||
|   install: |   install: | ||||||
| @@ -14,7 +17,7 @@ tasks: | |||||||
|   start-graph: |   start-graph: | ||||||
|     desc: run graph server |     desc: run graph server | ||||||
|     cmds: |     cmds: | ||||||
|       - cmd: go run ./cmd/server |       - cmd: go run ./bin/server | ||||||
|  |  | ||||||
|   start-web: |   start-web: | ||||||
|     desc: run web in dev mode |     desc: run web in dev mode | ||||||
| @@ -44,11 +47,11 @@ tasks: | |||||||
|       - cmd: deno task codegen |       - cmd: deno task codegen | ||||||
|  |  | ||||||
|   ent-new: |   ent-new: | ||||||
|     desc: create new db Emtity |     desc: create new db Entity | ||||||
|     cmd: cd ./db && go run -mod=mod entgo.io/ent/cmd/ent new {{.name}} |     cmd: cd ./db && go run -mod=mod entry.io/ent/cmd/ent new {{.name}} | ||||||
|  |  | ||||||
|   ent-gen: |   ent-gen: | ||||||
|     desc: genertate from ent schema |     desc: generate from ent schema | ||||||
|     cmds: |     cmds: | ||||||
|       - go generate ./db/ent |       - go generate ./db/ent | ||||||
|  |  | ||||||
| @@ -61,4 +64,17 @@ tasks: | |||||||
|     desc: apply automatically migration using Ent schema |     desc: apply automatically migration using Ent schema | ||||||
|     cmds: |     cmds: | ||||||
|       - task: ent-gen |       - 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 | ||||||
							
								
								
									
										
											BIN
										
									
								
								web/public/android-chrome-192x192.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								web/public/android-chrome-192x192.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 5.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								web/public/android-chrome-512x512.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								web/public/android-chrome-512x512.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 15 KiB | 
							
								
								
									
										
											BIN
										
									
								
								web/public/apple-touch-icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								web/public/apple-touch-icon.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 4.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								web/public/favicon-16x16.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								web/public/favicon-16x16.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 262 B | 
							
								
								
									
										
											BIN
										
									
								
								web/public/favicon-32x32.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								web/public/favicon-32x32.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 548 B | 
							
								
								
									
										
											BIN
										
									
								
								web/public/favicon.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								web/public/favicon.ico
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 15 KiB | 
							
								
								
									
										11
									
								
								web/public/site.webmanifest
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								web/public/site.webmanifest
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										6
									
								
								web/web.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | package web | ||||||
|  |  | ||||||
|  | import "embed" | ||||||
|  |  | ||||||
|  | //go:embed public public/build/_app | ||||||
|  | var Public embed.FS | ||||||
		Reference in New Issue
	
	Block a user