asticode/go-astilectron

How to embed resources without bootstrap package ?

Closed this issue · 2 comments

I have a small application that has a one window. I have used the default go-astilectron without the bootstrap package and when running locally (using go run *.go) everything works as expected. When I compile using your bundler package then resources are not added to the output (only .exe, .dmg files are created), the end result is an application that shows a blank window. because it's missing all the html / css / js files.

I have searched the issues and every example is using the bootstrap package, so I'm wondering if this is a required step in order to embed resources ? Do I need to convert my existing code and use the bootstrap ?

Here is the astilectron part of my code:

l := log.New(log.Writer(), log.Prefix(), log.Flags())

gui.astilectronOptions = astilectron.Options{
  AppName:            "Ginker",
  BaseDirectoryPath:  "resources",
  AppIconDarwinPath:  "icon.ico",
  AppIconDefaultPath: "icon.png",
  SingleInstance:     true,
  }


// Set up astilectron.
ginker, err := astilectron.New(l, gui.astilectronOptions)
if err != nil {
  return nil, err
}
defer ginker.Close()
gui.Ginker = ginker

// Handle signals.
gui.Ginker.HandleSignals()

// Start the app
if err = gui.Ginker.Start(); err != nil {
  return nil, err
}

gui.windowOptions = astilectron.WindowOptions{
  Center: astikit.BoolPtr(true),
  Height: astikit.IntPtr(700),
  Width:  astikit.IntPtr(700),
}

// Create a new window.
if gui.window, err = gui.Ginker.NewWindow("resources/app/dist/index.html", &gui.windowOptions); err != nil {
  return nil, err
}

// Create windows
if err = gui.window.Create(); err != nil {
  return nil, err
}

// Create menus.
m := menuItems(gui.Ginker, gui.window)
m.Create()

// This will listen to messages sent by Javascript
gui.window.OnMessage(func(m *astilectron.EventMessage) interface{} {
  e := handleEvent(m)
  return e
})

You have 2 options :

  • either you use go-astilectron only and you develop yourself all the embed/disembed logic
  • or you use go-astilectron, go-astilectron-bundler and go-astilectron-bootstrap to make the most of the already developed embed/disembed logic

I strongly recommend the 2nd option.

Bottom line is, if you want to use the bundler, you have to use the bootstrap in your project.

Luckily for you, it's not that complicated. Your project would look something like :

var (
	VersionAstilectron string
	VersionElectron    string
)

func main() {
	// Create logger
	l := log.New(log.Writer(), log.Prefix(), log.Flags())

	// Run bootstrap
	if err := bootstrap.Run(bootstrap.Options{
		Asset:    Asset,
		AssetDir: AssetDir,
		AstilectronOptions: astilectron.Options{
  			AppName:            "Ginker",
  			BaseDirectoryPath:  "resources",
  			AppIconDarwinPath:  "icon.ico",
  			AppIconDefaultPath: "icon.png",
  			SingleInstance:     true,
  		},
		Logger: l,
		MenuOptions: menuItems(),
		OnWait: func(_ *astilectron.Astilectron, ws []*astilectron.Window, _ *astilectron.Menu, _ *astilectron.Tray, _ *astilectron.Menu) error {
			// This will listen to messages sent by Javascript
			ws[0].OnMessage(func(m *astilectron.EventMessage) interface{} {
  				e := handleEvent(m)
  				return e
			})
			return nil
		},
		RestoreAssets: RestoreAssets,
		Windows: []*bootstrap.Window{{
			Homepage:      "resources/app/dist/index.html",
			MessageHandler: handleMessages,
			Options: &astilectron.WindowOptions{
				Center:          astikit.BoolPtr(true),
				Height:          astikit.IntPtr(700),
				Width:           astikit.IntPtr(700),
			},
		}},
	}); err != nil {
		l.Fatal(fmt.Errorf("running bootstrap failed: %w", err))
	}
}

At first, Asset, AssetDir and RestoreAssets will be unknown but once you run the bundler, they will be created.

You'll also have to adapt a bit menuItems and create handleMessages even if it does nothing.

Let me know if that answers your question.

Yes, thanks for the explanation and the code snippet.