5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-02 17:22:01 +08:00

Feature/auto devserver port (#1547)

* Support "auto" devserverurl
This commit is contained in:
Lea Anthony 2022-07-12 21:41:41 +10:00 committed by GitHub
parent d1ae16ad3c
commit 1dec40db33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 104 additions and 115 deletions

View File

@ -183,6 +183,19 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
signal.Notify(quitChannel, os.Interrupt, os.Kill, syscall.SIGTERM)
exitCodeChannel := make(chan int, 1)
// frontend:dev:watcher command.
if command := projectConfig.DevWatcherCommand; command != "" {
closer, devServerURL, err := runFrontendDevWatcherCommand(cwd, command, projectConfig.FrontendDevServerURL == "auto")
if err != nil {
return err
}
if devServerURL != "" {
projectConfig.FrontendDevServerURL = devServerURL
flags.frontendDevServerURL = devServerURL
}
defer closer()
}
// Do initial build
logger.Println("Building application for development...")
debugBinaryProcess, appBinary, err := restartApp(buildOptions, nil, flags, exitCodeChannel)
@ -195,15 +208,6 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
}
}()
// frontend:dev:watcher command.
if command := projectConfig.DevWatcherCommand; command != "" {
closer, err := runFrontendDevWatcherCommand(cwd, command)
if err != nil {
return err
}
defer closer()
}
// open browser
if flags.openBrowser {
err = browser.OpenURL(devServerURL.String())
@ -232,6 +236,12 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
}
LogGreen("Using reload debounce setting of %d milliseconds", flags.debounceMS)
// Show dev server URL in terminal after 3 seconds
go func() {
time.Sleep(3 * time.Second)
LogGreen("\n\nTo develop in the browser, navigate to: %s", devServerURL)
}()
// Watch for changes and trigger restartApp()
debugBinaryProcess = doWatcherLoop(buildOptions, debugBinaryProcess, flags, watcher, exitCodeChannel, quitChannel, devServerURL)
@ -411,18 +421,31 @@ func loadAndMergeProjectConfig(cwd string, flags *devFlags) (*project.Project, e
}
// runFrontendDevWatcherCommand will run the `frontend:dev:watcher` command if it was given, ex- `npm run dev`
func runFrontendDevWatcherCommand(cwd string, devCommand string) (func(), error) {
func runFrontendDevWatcherCommand(cwd string, devCommand string, discoverViteServerURL bool) (func(), string, error) {
ctx, cancel := context.WithCancel(context.Background())
scanner := NewStdoutScanner()
dir := filepath.Join(cwd, "frontend")
cmdSlice := strings.Split(devCommand, " ")
cmd := exec.CommandContext(ctx, cmdSlice[0], cmdSlice[1:]...)
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
cmd.Stdout = scanner
cmd.Dir = dir
setParentGID(cmd)
if err := cmd.Start(); err != nil {
cancel()
return nil, fmt.Errorf("Unable to start frontend DevWatcher: %w", err)
return nil, "", fmt.Errorf("unable to start frontend DevWatcher: %w", err)
}
var viteServerURL string
if discoverViteServerURL {
select {
case serverURL := <-scanner.ViteServerURLChan:
viteServerURL = serverURL
case <-time.After(time.Second * 10):
cancel()
return nil, "", errors.New("failed to find Vite server URL")
}
}
LogGreen("Running frontend DevWatcher command: '%s'", devCommand)
@ -443,7 +466,7 @@ func runFrontendDevWatcherCommand(cwd string, devCommand string) (func(), error)
LogGreen("DevWatcher command killed!")
cancel()
wg.Wait()
}, nil
}, viteServerURL, nil
}
// initialiseWatcher creates the project directory watcher that will trigger recompile
@ -550,12 +573,12 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
if dir == "" {
continue
}
path, err := filepath.Abs(dir)
thePath, err := filepath.Abs(dir)
if err != nil {
LogRed("Unable to expand reloadDir '%s': %s", dir, err)
continue
}
dirsThatTriggerAReload = append(dirsThatTriggerAReload, path)
dirsThatTriggerAReload = append(dirsThatTriggerAReload, thePath)
}
quit := false
@ -661,8 +684,8 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
}
if assetDir != "" {
for path := range changedPaths {
if strings.HasPrefix(path, assetDir) {
for thePath := range changedPaths {
if strings.HasPrefix(thePath, assetDir) {
reload = true
break
}

View File

@ -0,0 +1,45 @@
package dev
import (
"bufio"
"bytes"
"github.com/acarl005/stripansi"
"net/url"
"os"
"strings"
)
// stdoutScanner acts as a stdout target that will scan the incoming
// data to find out the vite server url
type stdoutScanner struct {
ViteServerURLChan chan string
}
// NewStdoutScanner creates a new stdoutScanner
func NewStdoutScanner() *stdoutScanner {
return &stdoutScanner{
ViteServerURLChan: make(chan string, 2),
}
}
// Write bytes to the scanner. Will copy the bytes to stdout
func (s *stdoutScanner) Write(data []byte) (n int, err error) {
match := bytes.Index(data, []byte("> Local:"))
if match != -1 {
sc := bufio.NewScanner(strings.NewReader(string(data)))
for sc.Scan() {
line := sc.Text()
index := strings.Index(line, "Local:")
line = strings.TrimSpace(line[index+6:])
viteServerURL := stripansi.Strip(line)
LogGreen("Vite Server URL: %s", viteServerURL)
_, err := url.Parse(viteServerURL)
if err != nil {
LogRed(err.Error())
} else {
s.ViteServerURLChan <- viteServerURL
}
}
}
return os.Stdout.Write(data)
}

View File

@ -4,7 +4,7 @@
"frontend:install": "npm install",
"frontend:build": "npm run build",
"frontend:dev:watcher": "npm run dev",
"frontend:dev:serverUrl": "http://localhost:3000",
"frontend:dev:serverUrl": "auto",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"

View File

@ -4,7 +4,7 @@
"frontend:install": "npm install",
"frontend:build": "npm run build",
"frontend:dev:watcher": "npm run dev",
"frontend:dev:serverUrl": "http://localhost:3000",
"frontend:dev:serverUrl": "auto",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"

View File

@ -4,7 +4,7 @@
"frontend:install": "npm install",
"frontend:build": "npm run build",
"frontend:dev:watcher": "npm run dev",
"frontend:dev:serverUrl": "http://localhost:3000",
"frontend:dev:serverUrl": "auto",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"

View File

@ -1,83 +0,0 @@
package main
import (
"embed"
"log"
"github.com/wailsapp/wails/v2/pkg/options/mac"
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/logger"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/windows"
)
//go:embed frontend/src
var assets embed.FS
//go:embed build/appicon.png
var icon []byte
func main() {
// Create an instance of the app structure
app := NewApp()
// Create application with options
err := wails.Run(&options.App{
Title: "{{.ProjectName}}",
Width: 1024,
Height: 768,
MinWidth: 1024,
MinHeight: 768,
MaxWidth: 1280,
MaxHeight: 800,
DisableResize: false,
Fullscreen: false,
Frameless: false,
StartHidden: false,
HideWindowOnClose: false,
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
Assets: assets,
Menu: nil,
Logger: nil,
LogLevel: logger.DEBUG,
OnStartup: app.startup,
OnDomReady: app.domReady,
OnBeforeClose: app.beforeClose,
OnShutdown: app.shutdown,
WindowStartState: options.Normal,
Bind: []interface{}{
app,
},
// Windows platform specific options
Windows: &windows.Options{
WebviewIsTransparent: false,
WindowIsTranslucent: false,
DisableWindowIcon: false,
// DisableFramelessWindowDecorations: false,
WebviewUserDataPath: "",
},
Mac: &mac.Options{
TitleBar: &mac.TitleBar{
TitlebarAppearsTransparent: true,
HideTitle: false,
HideTitleBar: false,
FullSizeContent: false,
UseToolbar: false,
HideToolbarSeparator: true,
},
Appearance: mac.NSAppearanceNameDarkAqua,
WebviewIsTransparent: true,
WindowIsTranslucent: true,
About: &mac.AboutInfo{
Title: "Plain Template",
Message: "Part of the Wails projects",
Icon: icon,
},
},
})
if err != nil {
log.Fatal(err)
}
}

View File

@ -4,7 +4,7 @@
"frontend:install": "npm install",
"frontend:build": "npm run build",
"frontend:dev:watcher": "npm run dev",
"frontend:dev:serverUrl": "http://localhost:3000",
"frontend:dev:serverUrl": "auto",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"

View File

@ -4,7 +4,7 @@
"frontend:install": "npm install",
"frontend:build": "npm run build",
"frontend:dev:watcher": "npm run dev",
"frontend:dev:serverUrl": "http://localhost:3000",
"frontend:dev:serverUrl": "auto",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"

View File

@ -4,7 +4,7 @@
"frontend:install": "npm install",
"frontend:build": "npm run build",
"frontend:dev:watcher": "npm run dev",
"frontend:dev:serverUrl": "http://localhost:3000",
"frontend:dev:serverUrl": "auto",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"

View File

@ -4,7 +4,7 @@
"frontend:install": "npm install",
"frontend:build": "npm run build",
"frontend:dev:watcher": "npm run dev",
"frontend:dev:serverUrl": "http://localhost:3000",
"frontend:dev:serverUrl": "auto",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"

View File

@ -4,7 +4,7 @@
"frontend:install": "npm install",
"frontend:build": "npm run build",
"frontend:dev:watcher": "npm run dev",
"frontend:dev:serverUrl": "http://localhost:3000",
"frontend:dev:serverUrl": "auto",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"

View File

@ -4,7 +4,7 @@
"frontend:install": "npm install",
"frontend:build": "npm run build",
"frontend:dev:watcher": "npm run dev",
"frontend:dev:serverUrl": "http://localhost:3000",
"frontend:dev:serverUrl": "auto",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"

View File

@ -4,7 +4,7 @@
"frontend:install": "npm install",
"frontend:build": "npm run build",
"frontend:dev:watcher": "npm run dev",
"frontend:dev:serverUrl": "http://localhost:3000",
"frontend:dev:serverUrl": "auto",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"

View File

@ -4,7 +4,7 @@
"frontend:install": "npm install",
"frontend:build": "npm run build",
"frontend:dev:watcher": "npm run dev",
"frontend:dev:serverUrl": "http://localhost:3000",
"frontend:dev:serverUrl": "auto",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"

View File

@ -14,6 +14,7 @@
"@vitejs/plugin-vue": "^2.3.3",
"typescript": "^4.5.4",
"vite": "^2.9.9",
"vue-tsc": "^0.34.7"
"vue-tsc": "^0.34.7",
"@babel/types": "^7.17.10"
}
}

View File

@ -4,7 +4,7 @@
"frontend:install": "npm install",
"frontend:build": "npm run build",
"frontend:dev:watcher": "npm run dev",
"frontend:dev:serverUrl": "http://localhost:3000",
"frontend:dev:serverUrl": "auto",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"

View File

@ -4,7 +4,7 @@
"frontend:install": "npm install",
"frontend:build": "npm run build",
"frontend:dev:watcher": "npm run dev",
"frontend:dev:serverUrl": "http://localhost:3000",
"frontend:dev:serverUrl": "auto",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"

View File

@ -38,6 +38,7 @@ require (
)
require (
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/bep/debounce v1.2.1
github.com/bitfield/script v0.19.0
github.com/go-ole/go-ole v1.2.6

View File

@ -5,6 +5,8 @@ github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF0
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk=
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=

View File

@ -15,7 +15,7 @@ The project config resides in the `wails.json` file in the project directory. Th
"frontend:build": "[The command to build the assets, run in the frontend directory - often `npm run build`]",
"frontend:dev": "[This command is the dev equivalent of frontend:build. If not specified falls back to frontend:build]",
"frontend:dev:watcher": "[This command is run in a separate process on `wails dev`. Useful for 3rd party watchers or starting 3d party dev servers]",
"frontend:dev:serverUrl": "[URL to a 3rd party dev server to be used to serve assets, EG Vite",
"frontend:dev:serverUrl": "[URL to a 3rd party dev server to be used to serve assets, EG Vite. If this is set to 'auto' then the devServerUrl will be inferred from the Vite output]",
"wailsjsdir": "[Relative path to the directory that the auto-generated JS modules will be created]",
"version": "[Project config version]",
"outputfilename": "[The name of the binary]",