Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate from bindata to go:embed #22887

Closed
wants to merge 1 commit into from
Closed

Conversation

paralin
Copy link

@paralin paralin commented Feb 13, 2023

Migrate from bindata to go:embed

go:embed is part of the standard library and does not require an extra
go:generate step.

Migrate all usages of bindata to go:embed.

Make embedded the new default (previously required bindata tag).

Add new tag "servedynamic" which serves from filesystem (old !bindata).

Accept-Encoding compression has been dropped. The assets in go:embed are not
available in a compressed form. The compression could be enabled again by adding
a compress middleware: https://github.com/vearutop/statigz

Fixes #17352.

@delvh
Copy link
Member

delvh commented Feb 13, 2023

See also #17352.
Does this PR fix what has been discussed there?

@GiteaBot GiteaBot added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Feb 13, 2023
@paralin
Copy link
Author

paralin commented Feb 13, 2023

@delvh It uses go:embed statements and then references those in other packages. The only thing not addressed is Accept-Encoding compression. The assets in go:embed are not compressed, so I dropped the Accept-Encoding check.

However as mentioned in #17352 it could be added back by adding https://github.com/vearutop/statigz

@paralin paralin force-pushed the go-embed branch 8 times, most recently from b769a8b to 8685a95 Compare February 13, 2023 11:13
@lafriks lafriks added the type/refactoring Existing code has been cleaned up. There should be no new functionality. label Feb 13, 2023
@wxiaoguang
Copy link
Contributor

I haven't looked into details about all changes. But for bindata part, I think it's better to keep the old behavior and the old tag, reasons:

  • Keeping old tag won't break 3rd build pipelines, I know many teams build Gitea by themselves.
  • When a developer runs Gitea, they do not need the embedded data, they just want to use local assets and debug quickly, with default tags. For me, I do not want to set a tag to exclude embedded when developing Gitea everytime.

Just my opinion.

@silverwind
Copy link
Member

silverwind commented Feb 14, 2023

This embeds uncompressed assets so binary size will go up by a few tens of MBs after this. I'm not against landing uncompressed now and doing compression later as having go:embed work at all is good first step towards modernizing the asset embeds.

@lunny
Copy link
Member

lunny commented Feb 15, 2023

Sorry, I think we need a better resolution to replace the old system. uncompressed assets are unacceptable to me.

@silverwind
Copy link
Member

Then let's add statigz or similar. I think we can get away with only compressing to brotli because pretty much all browsers support it.

I guess https://github.com/webpack-contrib/compression-webpack-plugin#using-brotli would be ideal. For options, you can use

  params: {
    [constants.BROTLI_PARAM_MODE]: constants.BROTLI_MODE_TEXT,
    [constants.BROTLI_PARAM_QUALITY]: constants.BROTLI_MAX_QUALITY,
  }

@silverwind
Copy link
Member

silverwind commented Feb 15, 2023

Question is thought whether want to still support serving uncompressed assets or if browser brotli support can be made a requirement.

If we want to serve uncompressed with only brotli embedded, it would require a CGO dependency to decompress at runtime, which I think we should not take.

Otherwise we could do gzip like vfsgen, but that is a suboptimal solution in terms of both binary size and web performance. Or maybe even embed both gzip and brotli at the same time.

@silverwind
Copy link
Member

Actually https://github.com/andybalholm/brotli might work for a pure golang brotli decoder, avoiding CGO.

@silverwind
Copy link
Member

silverwind commented Feb 15, 2023

I think we may not actually need statigz at all, we can just:

  1. Make webpack output .br files, deleting original output files
  2. go:embed the directories as usual
  3. On HTTP request, check Accept-Encoding, if it has "brotli" serve byte stream directly from embed (fast path), if it doesn't, decompress at runtime and serve result (slow path).

Depending on how long these decompressions take, it might be good to keep the results in a memory cache, but I imagine it may be fast enough.

@lunny
Copy link
Member

lunny commented Feb 15, 2023

I think we may not actually need statigz at all, we can just:

1. Make webpack output .br files, deleting original output files

2. go:embed the directories as usual

3. On HTTP request, check Accept-Encoding, if it has "brotli" serve byte stream directly from embed (fast path), if it doesn't, decompress at runtime and serve result (slow path).

Depending on how long these decompressions take, it might be good to keep the results in a memory cache, but I imagine it may be fast enough.

Sounds good. The last requirement is developers don't want compress when it's in dev mode I think.

@silverwind
Copy link
Member

Yes, disable the webpack plugin in development. Development should not use go:embed, but instead use the assets from the filesystem that webpack continously outputs, e.g. same behaviour as now with the bindata tag absent.

go:embed is part of the standard library and does not require an extra
go:generate step.

Migrate all usages of bindata to go:embed.

Make embedded the new default (previously required bindata tag).

Add new tag "servedynamic" which serves from filesystem (old !bindata).

Accept-Encoding compression has been dropped. The assets in go:embed are not
available in a compressed form. The compression could be enabled again by adding
a compress middleware: https://github.com/vearutop/statigz

Drop vfsgen dependency (no longer required).

Fixes go-gitea#17352

Signed-off-by: Christian Stewart <[email protected]>
@wxiaoguang
Copy link
Contributor

Sorry for bothering, is this PR active? It seems there is no progress for some review comments.

@wxiaoguang wxiaoguang added the issue/needs-feedback For bugs, we need more details. For features, the feature must be described in more detail label Apr 25, 2023
@paralin
Copy link
Author

paralin commented Apr 25, 2023

It's active insofar I'm still interested in merging it, but there were a number of comments around wanting to use compression for the assets and I'm not really in a position to implement that right now, so if someone else will have to edit the PR for that.

@wxiaoguang
Copy link
Contributor

Thank you very much for your contribution. Since we have a refactoring PR for "custom/static/builtin" assets, there are a lot of conflicts.

So at the moment I can see some possible decisions for this PR:

  1. Keep it open as-is, but it would be stale forever (does it make sense?).
  2. Resolve conflicts and keep it open (I guess resolving conflicts would spend more time than starting a new PR from latest main branch, because the "assets" system has changed a lot).
  3. Start a clear new PR (according to 2), and at least the "bindata" tag should be kept as before.
  4. Or do you have other proposals?

What do you think about it?

@silverwind
Copy link
Member

I'd merge this even without compression, but some numbers of binary size before and after would be good, so we can judge the impact of missing compression.

It's an important step to get this done as it simplifies the build a lot. I can collaborate adding at least the compressed from webpack side.

@paralin
Copy link
Author

paralin commented Apr 25, 2023

I'll have a look at adjusting this PR to use the bindata tag and resolve conflicts

Edit: I'm quite busy at the moment so it might take a while for me to get around to this, sorry

@wxiaoguang wxiaoguang removed the issue/needs-feedback For bugs, we need more details. For features, the feature must be described in more detail label Apr 25, 2023
@lunny
Copy link
Member

lunny commented Apr 25, 2023

I'd merge this even without compression, but some numbers of binary size before and after would be good, so we can judge the impact of missing compression.

It's an important step to get this done as it simplifies the build a lot. I can collaborate adding at least the compressed from webpack side.

I cannot see it's necessary to merge without compressing. It's a regression for end-user usage. What is the problem of the old embed method for the end user?

@silverwind
Copy link
Member

silverwind commented Apr 25, 2023

You're right, it is a regression for the end user if we don't handle compression. Right now they get gzip assets when the browser indicates it in accept-encoding.

So I guess let's get this branch up to date and then we can potentially collaborate on it to add compression back.

For me, it's mostly about the simplification of the build, so it's better development experience.

@SuperSandro2000
Copy link
Contributor

Then let's add statigz or similar. I think we can get away with only compressing to brotli because pretty much all browsers support it.

brotli is only good for text based files. Anything binary like png's is better compressed using gzip.

@wxiaoguang
Copy link
Contributor

brotli is only good for text based files. Anything binary like png's is better compressed using gzip.

Nope. https://stackoverflow.com/questions/11289369/why-png-size-doesnt-change-after-using-http-gzip-compression

@silverwind
Copy link
Member

silverwind commented May 8, 2023

brotli is only good for text based files. Anything binary like png's is better compressed using gzip.

Brotli has non-text modes as well, but we don't really need to dive into it so deeply. I would compress those anyways for simplicity's sake in the first iteration of this as the difference will be neglible and it simplifies the implementation.

@silverwind
Copy link
Member

silverwind commented May 13, 2023

I've added support for generic and font broti modes in precompress.

I think I will also implement a feature to it to take assets from one directory and output compressed ones into another directory with subfolders intact. I guess such an option would be easiest for gitea to implement so we can leave the public directory alone and output into a temporary public-br directory for go:embed to pick up the files during the build.

@wxiaoguang
Copy link
Contributor

Stale and it seems that nobody is interested in this change?

@wxiaoguang wxiaoguang added the issue/needs-feedback For bugs, we need more details. For features, the feature must be described in more detail label Aug 12, 2023
@silverwind
Copy link
Member

We need compression before we can merge this, gzip is fine, brotli even better.

@wxiaoguang
Copy link
Contributor

If there is no progress ..... there seems no other choice besides close it (also due to the conflicts)

@silverwind
Copy link
Member

silverwind commented Aug 12, 2023

To summarize the situation:

  1. go:embed does not feature compression which is needed for both ideal binary size and client performance. The only way to get it to work with current go:embed is to pre-compress the assets outside of go in a separate tool (precompress module or webpack plugin), which complicates the build
  2. To use brotli (the ideal compression), we need a runtime brotli decoder for better client support and https://github.com/andybalholm/brotli is the only one in existance which is a machine-generated translation from C, which apparently is also very big (5mb+), so not ideal.

https://github.com/thealetheia/broccoli seems to take care of point 1 but seems unmaintained. Point 2 can not be resolved without go:embed gaining compression support, but I can accept it for the sake of better client performance.

@wxiaoguang
Copy link
Contributor

A better solution: Use go:embed with server-side gzip support #26533

@wxiaoguang
Copy link
Contributor

Stale. Free free to reopen if some comments like #22887 (comment) are addressed.

@wxiaoguang wxiaoguang closed this Sep 7, 2023
@go-gitea go-gitea locked as resolved and limited conversation to collaborators Dec 6, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
issue/needs-feedback For bugs, we need more details. For features, the feature must be described in more detail lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. type/refactoring Existing code has been cleaned up. There should be no new functionality.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use go:embed for embedding files instead of vfsgen
8 participants