It would be good to install it using simple go get instead of installing it as npm package.
With this service,(https://gobinaries.com/) you can get binary without golang at all
Adding a go.mod file is a step in the right direction, but unfortunately go get
is not yet supported due to the project's structure.
$ go get github.com/evanw/esbuild
can't load package: package github.com/evanw/esbuild: no Go files in /Users/tooolbox/go/src/github.com/evanw/esbuild
That makes sense because all of the source files are contained in src
. Go projects sometimes have a a cmd
folder that contains the actual main
package that you go get
so let's try that:
$ go get github.com/evanw/esbuild/src/esbuild/main
unrecognized import path "esbuild/ast": import path does not begin with hostname
unrecognized import path "esbuild/bundler": import path does not begin with hostname
unrecognized import path "esbuild/fs": import path does not begin with hostname
unrecognized import path "esbuild/lexer": import path does not begin with hostname
unrecognized import path "esbuild/logging": import path does not begin with hostname
unrecognized import path "esbuild/parser": import path does not begin with hostname
unrecognized import path "esbuild/resolver": import path does not begin with hostname
(Just checking...)
$ go get github.com/evanw/esbuild/src/esbuild
can't load package: package github.com/evanw/esbuild/src/esbuild: no Go files in /Users/tooolbox/go/src/github.com/evanw/esbuild/src/esbuild
Unfortunately, Go Modules has what you might call a lack of support for import paths that do not begin with a domain (the Go Team wants to reserve such domain-less imports for the standard library). The first segment of the import path has to have a .
in it or else most operations fail. The sole exception seems to be go build
.
Thus, while esbuild has started to use Go Modules 🎉 the best way to enable go get
and similar goodies is to change to a github.com/evanw/esbuild/...
import path.
Note that because replace
directives in go.mod
files are not supported for go get
and similar operations, this is not a matter of dropping in a go.mod
or two and everything Just Worksâ„¢ as before. The actual import paths/project structure would need to be changed.
There are a couple of examples available of how to do this. Note that if the author is concerned about folks using the code as a library, it can be placed in a directory called internal
and no other Go code can import it.
Appendix:
$ GO111MODULE=on go get github.com/evanw/esbuild/src/esbuild/main
go: downloading github.com/evanw/esbuild v0.0.0-20200416222118-5edc934e7a09
go: downloading github.com/evanw/esbuild/src/esbuild v0.0.0-20200416222118-5edc934e7a09
go: found github.com/evanw/esbuild/src/esbuild/main in github.com/evanw/esbuild/src/esbuild v0.0.0-20200416222118-5edc934e7a09
go get: github.com/evanw/esbuild/src/[email protected]: parsing go.mod:
module declares its path as: esbuild
but was required as: github.com/evanw/esbuild/src/esbuild
$ GO111MODULE=on go get github.com/evanw/esbuild/src/esbuild
go: github.com/evanw/esbuild/src/esbuild upgrade => v0.0.0-20200416222118-5edc934e7a09
go get: github.com/evanw/esbuild/src/[email protected]: parsing go.mod:
module declares its path as: esbuild
but was required as: github.com/evanw/esbuild/src/esbuild
md5-ad46d2090d8bdc219f2f2e5a291aeffe
$ GO111MODULE=on go get github.com/evanw/esbuild
go: github.com/evanw/esbuild upgrade => v0.0.0-20200416222118-5edc934e7a09
# Doesn't actually build a binary
Having this available as a Go tool would be a real boon. Lack of speed isn't the only issue with JavaScript build systems. It would be great to be able to reduce JS dependencies to only those required by the actual project. Currently, those account for about 1% of the stuff in most of my node_modules
directories.
I wrote a web browser application using Go to run a HTTP server and supply a REST API. It would be great being able to use Go for bundling the static assets too. I would not need Node.js as a build tool to at all. Just Go :-)
@evanw, how about moving go.mod
and go.sub
to the root of the Github repository, so that it would be recognized as a Go module? Renaming src
to cmd
might not be necessary:
$ go get -u github.com/evanw/esbuild/tree/master/src/esbuild/...
go get github.com/evanw/esbuild/tree/master/src/esbuild/...:
module github.com/evanw/esbuild@upgrade found (v0.0.0-20200506071632-d71e12639799),
but does not contain packages matching github.com/evanw/esbuild/tree/master/src/esbuild/...
$ go get -u github.com/evanw/esbuild/src/esbuild/...
go: downloading github.com/evanw/esbuild/src/esbuild v0.0.0-20200506071632-d71e12639799
go: found github.com/evanw/esbuild/src/esbuild/...
in github.com/evanw/esbuild/src/esbuild v0.0.0-20200506071632-d71e12639799
go get: github.com/evanw/esbuild/src/[email protected]:
parsing go.mod:
module declares its path as: esbuild
but was required as: github.com/evanw/esbuild/src/esbuild
$ go get -u github.com/evanw/esbuild/...
go get github.com/evanw/esbuild/...:
module github.com/evanw/esbuild@upgrade found (v0.0.0-20200506071632-d71e12639799),
but does not contain packages matching github.com/evanw/esbuild/...
Well, I was too naive to say, that just moving go.mod
and go.sub
would do. I inspected the project sources and [made some changes] to get a prototype running. They were pure restructuring. No code changes except for renaming the internal imports were needed.
go.mod
and go.sub
to the project root.github.com/evanw/esbuild
instead of esbuild
./src/esbuild/main
to /cmd/esbuild
./internal
. Some of them can be made public later.github.com/evanw/esbuild/internal/...
instead of esbuild/...
.Makefile
to work with the new structure.In the end I was able to successfully build and test the package. When I tested it externally, I had to rename the package in my fork, but if you imagine evanw
instead of prantlf
there, you will get the idea :-)
go get -u github.com/prantlf/esbuild/...@308fdf459d65
I kept the change in a [separate branch]. Would you be interested in a PR? Of course, that that branch will work only with your [change d71e126], which I forked. I am not sure if rebase on a newer state of your repository will work with so many moved files. If you were interested, I would make the changes again to your latest sources, whenever you were ready.
Ok I attempted to do this. Can someone confirm if this works? I'm not familiar with Go modules, so I'm not sure what to test.
Can someone confirm if this works?
It does. You may need to run GO111MODULE=on go get -u github.com/prantlf/esbuild/...@308fdf459d65
to install it if you're getting the error go: cannot use path@version syntax in GOPATH mode
Thanks for confirming! I'll consider this issue fixed then.
As an additional data point, I was also able to successfully download an esbuild executable from https://gobinaries.com. It appeared to be around the correct size. I didn't run it though.
Thank you, @evanw, it works perfectly! When running in a Go module directory using Go 1.14, the binary esbuild
gets installed and put to PATH
(actually, GOBIN
):
$ go get -u github.com/evanw/esbuild/...
go: downloading github.com/evanw/esbuild v0.0.0-20200507102806-766e48876293
go: found github.com/evanw/esbuild/...
in github.com/evanw/esbuild v0.0.0-20200507102806-766e48876293
go: golang.org/x/sys upgrade => v0.0.0-20200501145240-bc7a7d42d5c3
$ which esbuild
/Users/prantlf/go/bin/esbuild
Beware of git tags, though. You have not tagged any commit in your repository yet. That is why if I run go get -u ...
everyday, I will be able to enjoy your latest changes everyday (if I wanted) :-) As soon as you decide to tag your commits to match your releases, Go will use the latest of them according to the semantic versioning concept. It means that if you do not tag the commit which you want to release, Go users will not get an upgrade offered.
You can work without tags on the road to MVP. If somebody wants to stay with a particular change, they can refer to it by its commit hash, when they install the tool. For example:
go get -u github.com/evanw/esbuild/...@766e48876293
As soon as you decide to start tagging your commits, people who install esbuild
by go get
will get the latest release, not the latest master, just like NPM users do today. Once you decide, I recommend you the usual semantic versioning format used by both Go and NPM packages. For example, your current version that you released to NPM would be tagged byv0.2.8
.
Thanks again for the quick implementation!
About downloading binaries - you can have a look at GoReleaser too. If you write a goreleaser.yml
, tag a commit for a new release and run .goreleaser --rm-dist
. It will build binaries for all platforms, upload them to GitHub and generate a changelog entry with hyperlinks. This is more for the future, when esbuild
gets more stable.
By the way, NPM releases can be automated in a similar way with semantic-release
, if you were interested. Basically, you prefix your commits with chore:
(not versioning change), fix:
(patch version), feat:
(minor version) or include BREAKING CHANGE:
in the commit description (major version) and run npx semantic-release
, when you are ready to push all changes. It will bump the version properly and publish your module at npmjs.org.
Both go-release
and semantic-release
can be run in CI pipelines like Travis, so that you do not need to do the "paperwork" yourself.
Stupendous; can confirm this works.
@evanw It would be nice, when you do a version bump on NPM, to add a git tag for the same version.
I'll add tags for future releases. I want esbuild's command-line tool to be usable for real things, so I don't think downloading master is an appropriate default.
Unfortunately semantic versioning doesn't really apply before 1.0.0. The semver docs say this:
Major version zero (0.y.z) is for initial development. Anything MAY change at any time. The public API SHOULD NOT be considered stable.
However, during the MVP phase I'd like to be a bit more rigorous about this. I'm planning to use patch releases for backwards-compatible changes and bug fixes, and minor releases for either major features or backwards-incompatible changes. So if you stick to just patch releases than the command-line interface should remain pretty stable.
I'll add tags for future releases.
Awesome, thanks.
Unfortunately semantic versioning doesn't really apply before 1.0.0.
That's fine, users of Go Modules will understand that things may break before 1.0.
From https://blog.golang.org/v2-go-modules:
For projects that are still experimental — at major version v0 — occasional breaking changes are expected by users. For projects which are declared stable — at major version v1 or higher — breaking changes must be done in a new major version.
Most helpful comment
Well, I was too naive to say, that just moving
go.mod
andgo.sub
would do. I inspected the project sources and [made some changes] to get a prototype running. They were pure restructuring. No code changes except for renaming the internal imports were needed.go.mod
andgo.sub
to the project root.github.com/evanw/esbuild
instead ofesbuild
./src/esbuild/main
to/cmd/esbuild
./internal
. Some of them can be made public later.github.com/evanw/esbuild/internal/...
instead ofesbuild/...
.Makefile
to work with the new structure.In the end I was able to successfully build and test the package. When I tested it externally, I had to rename the package in my fork, but if you imagine
evanw
instead ofprantlf
there, you will get the idea :-)I kept the change in a [separate branch]. Would you be interested in a PR? Of course, that that branch will work only with your [change d71e126], which I forked. I am not sure if rebase on a newer state of your repository will work with so many moved files. If you were interested, I would make the changes again to your latest sources, whenever you were ready.