When it comes to Go
the program is packaged into other non *.go
resources, before Go1.16
has go-bindata third-party open source support.
In Go1.16
a new feature was introduced embed
, which allows you to embed static resource permissions without relying on third parties.
However, in the project, I didn't use the above two solutions, and instead developed a set of solutions by myself.
If you don't want to listen to my bb's mental journey, just skip to the opening link to see the final realization.
background
In early 2021, when I was involved in the project go-mod-graph-chart , I needed to integrate front-end resources into a command-line program built in Go.
Having said that, let's introduce go-mod-graph-chart , which is a text visualization command line tool (similar to graphviz ) that outputs the go mod graph
command, and executes it in the project directory go mod graph
will output the current project, the third-party packages it depends on, and what packages the third-party packages depend on. But when you actually use it, you'll see a bunch of text,
The output of the command is as follows:
$ go mod graph
go-learn github.com/antlabs/pcurl@v0.0.7
go-learn github.com/bxcodec/faker/v3@v3.6.0
go-learn github.com/go-sql-driver/mysql@v1.5.0
go-learn github.com/jinzhu/copier@v0.3.5
go-learn github.com/pingcap/parser@v0.0.0-20220118030345-6a854bcbd929
go-learn github.com/smartystreets/goconvey@v1.7.2
go-learn golang.org/x/text@v0.3.7
go-learn moul.io/http2curl@v1.0.0
github.com/antlabs/pcurl@v0.0.7 github.com/gin-contrib/gzip@v0.0.1
github.com/antlabs/pcurl@v0.0.7 github.com/gin-gonic/gin@v1.6.3
github.com/antlabs/pcurl@v0.0.7 github.com/guonaihong/clop@v0.0.9
github.com/antlabs/pcurl@v0.0.7 github.com/guonaihong/gout@v0.0.12
github.com/antlabs/pcurl@v0.0.7 github.com/stretchr/testify@v1.6.1
github.com/pingcap/parser@v0.0.0-20220118030345-6a854bcbd929 github.com/cznic/golex@v0.0.0-20181122101858-9c343928389c
github.com/pingcap/parser@v0.0.0-20220118030345-6a854bcbd929 github.com/cznic/mathutil@v0.0.0-20181122101859-297441e03548
...
And use the tool gmchart to visualize it as a multi-level tree structure.
As shown below:
When distributing this command line tool, if you still need to bring static resources, or let the user go to the next graphviz
, the experience will be very bad. So I thought of a way to package the static resources into the *.go
code.
It's unfortunate that at the end of 2020, Go1.16 embed
is not yet available, but I'm going to fix that. go-bindata
was undoubtedly the most popular solution at the time, but it would introduce third-party dependencies. At this time, my code cleanliness came up. I used gin to do http service before, but later found that the project only introduced gin
, I replaced gin
with the built-in http
the service, it becomes a dependency-free project. So, I would like to continue with no dependency . I feel that this function should not be difficult, and I can write it myself.
Realize ideas
Front-end packaging, one step is to integrate all the *.js
files into one js
file. And write the final output js
file name to index.html
as the entry js
.
Go
Static resource packaging is to serialize other types of files and save them to static variables in Go代码
.
Golang
When the program provides http services to the outside world, when it receives a static resource request, it will read the corresponding variable, output it to the http response body, and in http
heder
Set the corresponding Content-Type
heder
c3274d3c2d77ff6f9a760831cc16e6ab---
Then if you find a way to intervene in the output process, let it write main.js
, index.html
file, and write the content to the two variables of the go
code instead. Can realize Go
package static resources.
package gostatic
var IndexHtml = `<!DOCTYPE html>^M
<html lang="en">^M
</html>
var MainJs = `echo "hello";`
var Favicon = `data:image/ico;base64,AAABAAEAmpsAAAEAIAT...`
open up
The front-end construction of the project uses webpack , so let's move on.
A gopher wants to move webpack? a little overconfident
So I opened the official website of webpack
, and I turned around and found that the official plugin is provided. By customizing the plugin, it can affect its construction process.
Here in plugin
, the build result is obtained, and by traversing the build result, the string and file name are obtained, and then we insert a new build result go_static.go
, here Contains the contents of the preceding main.js
, index.html
files.
pack-all-in-go-plugin.js
The content of the file is as follows:
class PackAllInGoPlugin {
apply(compiler) {
// emit is asynchronous hook, tapping into it using tapAsync, you can use tapPromise/tap(synchronous) as well
compiler.hooks.emit.tapAsync('PackAllInGoPlugin', (compilation, callback) => {
// Create a header string for the generated file:
var filelist = '';
var indexHtml, mainJs;
var goCode = `package godist
func GetFile(file string) string {
switch {
case \`index.html\` == file:
return IndexHtml
case \`main.js\` == file:
return MainJs
case \`favicon.ico\` == file:
return Favicon
default:
return ""
}
}
var IndexHtml = \`--index.html--\`
var MainJs = \`--main.js--\`
var Favicon = \`favicon.ico\``
// Loop through all compiled assets,
// adding a new line item for each filename.
for (var filename in compilation.assets) {
if ("main.js" == filename) {
let jsCode = compilation.assets[filename].source()
let jsCodeString = jsCode.slice();
jsCodeString = jsCodeString.replace(/\`/g, "\` + \"\`\" + \`")
goCode = goCode.replace('--main.js--', jsCodeString)
} else if ("index.html") {
let htmlCode = compilation.assets[filename].source()
goCode = goCode.replace('--index.html--', htmlCode)
}
}
// 将这个列表作为一个新的文件资源,插入到 webpack 构建中:
compilation.assets['../godist/static.go'] = {
source: function() {
return goCode;
},
size: function() {
return goCode.length;
}
};
callback();
});
}
}
module.exports = PackAllInGoPlugin;
Introduced in webpack
/*
* 引入自定义插件
*/
const PackAllInGoPlugin = require('./plugin/pack-all-in-go-plugin');
...
config = {
pulbins: [
...
new PackAllInGoPlugin({options: true})
],
}
After this setting, every time you execute npm run build
the latest static resources can be packaged into the go_static.go file. Then execute go build -o main main.go
go
code and static resources are packaged into an executable file.
correct! This webpack plugin is not released to npm, if you want to use it, just copy the source code directly. If you encounter integration problems in the middle, you can take a look at https://github.com/PaulXu-cn/go-mod-graph-chart , this project is actually useful.
at last
In general, this time we solved the problem of packaging static resources from the front-end construction side go
---, which is regarded as spanning Go
and WebPack
, this solution is considered as Relatively small, basically belong to:
-
gopher
I don't want to touch the front end - Why should the front end write
webpack plugin
go
I also foresee that this method is only used by a few people. If you want to try to copy the code directly, this gadget will not open a "pit" alone.
Well, I am a tossing gohper
, this time I filled a hole made by myself. If you also like to fiddle with something different, please share with us.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。