Currently just serving a "Hello world" page when running the web cli in --dev mode. Updates tailscale/corp#13775 Co-authored-by: Will Norris <will@tailscale.com> Signed-off-by: Sonia Appasamy <sonia@tailscale.com>main
parent
215480a022
commit
16bc9350e3
@ -0,0 +1,75 @@ |
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package web |
||||
|
||||
import ( |
||||
"log" |
||||
"net/http" |
||||
"net/http/httputil" |
||||
"net/url" |
||||
"os" |
||||
"os/exec" |
||||
"path/filepath" |
||||
"strings" |
||||
) |
||||
|
||||
// startDevServer starts the JS dev server that does on-demand rebuilding
|
||||
// and serving of web client JS and CSS resources.
|
||||
func (s *Server) startDevServer() (cleanup func()) { |
||||
root := gitRootDir() |
||||
webClientPath := filepath.Join(root, "client", "web") |
||||
|
||||
yarn := filepath.Join(root, "tool", "yarn") |
||||
node := filepath.Join(root, "tool", "node") |
||||
vite := filepath.Join(webClientPath, "node_modules", ".bin", "vite") |
||||
|
||||
log.Printf("installing JavaScript deps using %s... (might take ~30s)", yarn) |
||||
out, err := exec.Command(yarn, "--non-interactive", "-s", "--cwd", webClientPath, "install").CombinedOutput() |
||||
if err != nil { |
||||
log.Fatalf("error running tailscale web's yarn install: %v, %s", err, out) |
||||
} |
||||
log.Printf("starting JavaScript dev server...") |
||||
cmd := exec.Command(node, vite) |
||||
cmd.Dir = webClientPath |
||||
cmd.Stdout = os.Stdout |
||||
cmd.Stderr = os.Stderr |
||||
if err := cmd.Start(); err != nil { |
||||
log.Fatalf("Starting JS dev server: %v", err) |
||||
} |
||||
log.Printf("JavaScript dev server running as pid %d", cmd.Process.Pid) |
||||
return func() { |
||||
cmd.Process.Signal(os.Interrupt) |
||||
err := cmd.Wait() |
||||
log.Printf("JavaScript dev server exited: %v", err) |
||||
} |
||||
} |
||||
|
||||
func (s *Server) addProxyToDevServer() { |
||||
if !s.devMode { |
||||
return // only using Vite proxy in dev mode
|
||||
} |
||||
// We use Vite to develop on the web client.
|
||||
// Vite starts up its own local server for development,
|
||||
// which we proxy requests to from Server.ServeHTTP.
|
||||
// Here we set up the proxy to Vite's server.
|
||||
handleErr := func(w http.ResponseWriter, r *http.Request, err error) { |
||||
w.Header().Set("Content-Type", "text/plain") |
||||
w.WriteHeader(http.StatusBadGateway) |
||||
w.Write([]byte("The web client development server isn't running. " + |
||||
"Run `./tool/yarn --cwd client/web start` from " + |
||||
"the repo root to start the development server.")) |
||||
w.Write([]byte("\n\nError: " + err.Error())) |
||||
} |
||||
viteTarget, _ := url.Parse("http://127.0.0.1:4000") |
||||
s.devProxy = httputil.NewSingleHostReverseProxy(viteTarget) |
||||
s.devProxy.ErrorHandler = handleErr |
||||
} |
||||
|
||||
func gitRootDir() string { |
||||
top, err := exec.Command("git", "rev-parse", "--show-toplevel").Output() |
||||
if err != nil { |
||||
log.Fatalf("failed to find git top level (not in corp git?): %v", err) |
||||
} |
||||
return strings.TrimSpace(string(top)) |
||||
} |
||||
@ -0,0 +1,3 @@ |
||||
<!doctype html> |
||||
Hello world |
||||
</html> |
||||
@ -0,0 +1,31 @@ |
||||
{ |
||||
"name": "webui", |
||||
"version": "0.0.1", |
||||
"license": "BSD-3-Clause", |
||||
"engines": { |
||||
"node": "18.16.1", |
||||
"yarn": "1.22.19" |
||||
}, |
||||
"private": true, |
||||
"dependencies": {}, |
||||
"devDependencies": { |
||||
"tailwindcss": "^3.1.6", |
||||
"typescript": "^4.7.4", |
||||
"vite": "^4.3.9", |
||||
"@vitejs/plugin-react-swc": "^3.3.2", |
||||
"vite-tsconfig-paths": "^3.5.0", |
||||
"vite-plugin-svgr": "^3.2.0", |
||||
"vite-plugin-rewrite-all": "^1.0.1", |
||||
"vitest": "^0.32.0" |
||||
}, |
||||
"scripts": { |
||||
"build": "vite build", |
||||
"start": "vite", |
||||
"lint": "tsc --noEmit", |
||||
"test": "vitest" |
||||
}, |
||||
"prettier": { |
||||
"semi": false, |
||||
"printWidth": 80 |
||||
} |
||||
} |
||||
@ -0,0 +1,69 @@ |
||||
/// <reference types="vitest" />
|
||||
import { createLogger, defineConfig } from "vite" |
||||
import rewrite from "vite-plugin-rewrite-all" |
||||
import svgr from "vite-plugin-svgr" |
||||
import paths from "vite-tsconfig-paths" |
||||
|
||||
// Use a custom logger that filters out Vite's logging of server URLs, since
|
||||
// they are an attractive nuisance (we run a proxy in front of Vite, and the
|
||||
// tailscale web client should be accessed through that).
|
||||
// Unfortunately there's no option to disable this logging, so the best we can
|
||||
// do it to ignore calls from a specific function.
|
||||
const filteringLogger = createLogger(undefined, { allowClearScreen: false }) |
||||
const originalInfoLog = filteringLogger.info |
||||
filteringLogger.info = (...args) => { |
||||
if (new Error("ignored").stack?.includes("printServerUrls")) { |
||||
return |
||||
} |
||||
originalInfoLog.apply(filteringLogger, args) |
||||
} |
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({ |
||||
base: "/", |
||||
plugins: [ |
||||
paths(), |
||||
svgr(), |
||||
// By default, the Vite dev server doesn't handle dots
|
||||
// in path names and treats them as static files.
|
||||
// This plugin changes Vite's routing logic to fix this.
|
||||
// See: https://github.com/vitejs/vite/issues/2415
|
||||
rewrite(), |
||||
], |
||||
build: { |
||||
outDir: "build", |
||||
sourcemap: true, |
||||
}, |
||||
esbuild: { |
||||
logOverride: { |
||||
// Silence a warning about `this` being undefined in ESM when at the
|
||||
// top-level. The way JSX is transpiled causes this to happen, but it
|
||||
// isn't a problem.
|
||||
// See: https://github.com/vitejs/vite/issues/8644
|
||||
"this-is-undefined-in-esm": "silent", |
||||
}, |
||||
}, |
||||
server: { |
||||
// This needs to be 127.0.0.1 instead of localhost, because of how our
|
||||
// Go proxy connects to it.
|
||||
host: "127.0.0.1", |
||||
// If you change the port, be sure to update the proxy in adminhttp.go too.
|
||||
port: 4000, |
||||
// Don't proxy the WebSocket connection used for live reloading by running
|
||||
// it on a separate port.
|
||||
hmr: { |
||||
protocol: "ws", |
||||
port: 4001, |
||||
}, |
||||
}, |
||||
test: { |
||||
exclude: ["**/node_modules/**", "**/dist/**"], |
||||
testTimeout: 20000, |
||||
environment: "jsdom", |
||||
deps: { |
||||
inline: ["date-fns", /\.wasm\?url$/], |
||||
}, |
||||
}, |
||||
clearScreen: false, |
||||
customLogger: filteringLogger, |
||||
}) |
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue