Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions config.example.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
// The wait time for incoming requests to wait for the build process to finish, default is 30 seconds.
"buildWaitTime": 30,

// Maximum time allowed for a single build task before it is canceled, default is 10 minutes.
"buildTimeout": 600,

// Compress http response body with gzip/brotli, default is true.
"compress": true,

Expand Down
25 changes: 17 additions & 8 deletions internal/fetch/fetch.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fetch

import (
"context"
"errors"
"net/http"
"net/url"
Expand Down Expand Up @@ -32,20 +33,28 @@ func NewClient(userAgent string, timeout int, reserveRedirect bool) (client *Fet

// Fetch sends an HTTP GET request to the specified URL and returns the response.
func (c *FetchClient) Fetch(url *url.URL, header http.Header) (resp *http.Response, err error) {
return c.FetchWithContext(context.Background(), url, header)
}

// FetchWithContext sends an HTTP GET request with cancellation support.
func (c *FetchClient) FetchWithContext(ctx context.Context, url *url.URL, header http.Header) (resp *http.Response, err error) {
if ctx == nil {
ctx = context.Background()
}
if c.userAgent != "" {
if header == nil {
header = make(http.Header)
}
header.Set("User-Agent", c.userAgent)
}
req := &http.Request{
Method: "GET",
URL: url,
Host: url.Host,
Proto: "HTTP/1.1",
ProtoMajor: 1,
ProtoMinor: 1,
Header: header,
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url.String(), nil)
if err != nil {
return nil, err
}
req.Host = url.Host
req.Proto = "HTTP/1.1"
req.ProtoMajor = 1
req.ProtoMinor = 1
req.Header = header
return c.Do(req)
}
66 changes: 56 additions & 10 deletions server/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package server

import (
"bytes"
"context"
"crypto/sha512"
"encoding/base64"
"encoding/json"
Expand Down Expand Up @@ -33,6 +34,7 @@ const (
)

type BuildContext struct {
ctx context.Context
npmrc *NpmRC
logger *log.Logger
metaDB *BuildMetaDB
Expand Down Expand Up @@ -119,7 +121,25 @@ func (ctx *BuildContext) Exists() (meta *BuildMeta, ok bool, err error) {
return
}

func (ctx *BuildContext) Build() (meta *BuildMeta, err error) {
func (ctx *BuildContext) Context() context.Context {
if ctx.ctx != nil {
return ctx.ctx
}
return context.Background()
}

func (ctx *BuildContext) checkCanceled() error {
return ctx.Context().Err()
}

func (ctx *BuildContext) Build(buildCtx context.Context) (meta *BuildMeta, err error) {
if buildCtx == nil {
buildCtx = context.Background()
}
ctx.ctx = buildCtx
if err = ctx.checkCanceled(); err != nil {
return
}
if ctx.target == "types" {
return ctx.buildTypes()
}
Expand All @@ -129,6 +149,9 @@ func (ctx *BuildContext) Build() (meta *BuildMeta, err error) {
if err != nil || ok {
return
}
if err = ctx.checkCanceled(); err != nil {
return
}

// install the package
ctx.status = "install"
Expand All @@ -142,6 +165,9 @@ func (ctx *BuildContext) Build() (meta *BuildMeta, err error) {
if err != nil || ok {
return
}
if err = ctx.checkCanceled(); err != nil {
return
}

// analyze splitting modules if bundling
if ctx.pkgJson.Exports.Len() > 1 && !ctx.isNoBundle() {
Expand All @@ -158,6 +184,9 @@ func (ctx *BuildContext) Build() (meta *BuildMeta, err error) {
if err != nil {
return
}
if err = ctx.checkCanceled(); err != nil {
return
}

// save the build result to the storage
key := ctx.Path()
Expand Down Expand Up @@ -225,6 +254,9 @@ func (ctx *BuildContext) buildPath() {
}

func (ctx *BuildContext) buildModule(analyzeMode bool) (meta *BuildMeta, includes [][2]string, err error) {
if err = ctx.checkCanceled(); err != nil {
return
}
entry := ctx.resolveEntry(ctx.esmPath)
if entry.isEmpty() {
err = errors.New("could not resolve build entry")
Expand Down Expand Up @@ -313,6 +345,7 @@ func (ctx *BuildContext) buildModule(analyzeMode bool) (meta *BuildMeta, include
externalAll: ctx.externalAll,
target: ctx.target,
dev: ctx.dev,
ctx: ctx.ctx,
}
err = b.install()
if err != nil {
Expand Down Expand Up @@ -939,7 +972,7 @@ func (ctx *BuildContext) buildModule(analyzeMode bool) (meta *BuildMeta, include
svelteVersion = version
}
if !npm.IsExactVersion(svelteVersion) {
info, err := ctx.npmrc.getPackageInfo("svelte", svelteVersion)
info, err := ctx.npmrc.getPackageInfoContext(ctx.Context(), "svelte", svelteVersion)
if err != nil {
return esbuild.OnLoadResult{}, errors.New("failed to get svelte package info")
}
Expand All @@ -948,7 +981,7 @@ func (ctx *BuildContext) buildModule(analyzeMode bool) (meta *BuildMeta, include
if semverLessThan(svelteVersion, "4.0.0") {
return esbuild.OnLoadResult{}, errors.New("svelte version must be greater than 4.0.0")
}
out, err := transformSvelte(ctx.npmrc, svelteVersion, ctx.esmPath.String(), string(code))
out, err := transformSvelte(ctx.Context(), ctx.npmrc, svelteVersion, ctx.esmPath.String(), string(code))
if err != nil {
return esbuild.OnLoadResult{}, err
}
Expand All @@ -973,7 +1006,7 @@ func (ctx *BuildContext) buildModule(analyzeMode bool) (meta *BuildMeta, include
vueVersion = version
}
if !npm.IsExactVersion(vueVersion) {
info, err := ctx.npmrc.getPackageInfo("vue", vueVersion)
info, err := ctx.npmrc.getPackageInfoContext(ctx.Context(), "vue", vueVersion)
if err != nil {
return esbuild.OnLoadResult{}, errors.New("failed to get vue package info")
}
Expand All @@ -982,7 +1015,7 @@ func (ctx *BuildContext) buildModule(analyzeMode bool) (meta *BuildMeta, include
if semverLessThan(vueVersion, "3.0.0") {
return esbuild.OnLoadResult{}, errors.New("vue version must be greater than 3.0.0")
}
out, err := transformVue(ctx.npmrc, vueVersion, ctx.esmPath.String(), string(code))
out, err := transformVue(ctx.Context(), ctx.npmrc, vueVersion, ctx.esmPath.String(), string(code))
if err != nil {
return esbuild.OnLoadResult{}, err
}
Expand All @@ -995,6 +1028,10 @@ func (ctx *BuildContext) buildModule(analyzeMode bool) (meta *BuildMeta, include
},
}

if err = ctx.checkCanceled(); err != nil {
return
}

nodeFilename := ctx.Path()
nodeDirname, _ := utils.SplitByLastByte(nodeFilename, '/')
nodeEnv := ctx.getNodeEnv()
Expand Down Expand Up @@ -1323,6 +1360,7 @@ REBUILD:
externalAll: ctx.externalAll,
target: ctx.target,
dev: ctx.dev,
ctx: ctx.ctx,
}
err = b.install()
if err == nil {
Expand Down Expand Up @@ -1461,6 +1499,9 @@ func (ctx *BuildContext) buildTypes() (ret *BuildMeta, err error) {
if err != nil {
return
}
if err = ctx.checkCanceled(); err != nil {
return
}

var dts string
if endsWith(ctx.esmPath.SubPath, ".ts", ".mts", ".tsx", ".cts") {
Expand All @@ -1486,7 +1527,7 @@ func (ctx *BuildContext) buildTypes() (ret *BuildMeta, err error) {

func (ctx *BuildContext) install() (err error) {
if ctx.wd == "" || ctx.pkgJson == nil {
p, err := ctx.npmrc.installPackage(ctx.esmPath.Package())
p, err := ctx.npmrc.installPackageContext(ctx.Context(), ctx.esmPath.Package())
if err != nil {
return err
}
Expand Down Expand Up @@ -1540,15 +1581,20 @@ func (ctx *BuildContext) install() (err error) {
// - install '@babel/runtime' and '@swc/helpers' if they are present in the dependencies in `BundleDefault` mode
switch ctx.bundleMode {
case BundleDeps:
ctx.npmrc.installDependencies(ctx.wd, ctx.pkgJson, false, nil)
err = ctx.npmrc.installDependenciesContext(ctx.Context(), ctx.wd, ctx.pkgJson, false, nil)
case BundleDefault:
if v, ok := ctx.pkgJson.Dependencies["@babel/runtime"]; ok {
ctx.npmrc.installDependencies(ctx.wd, &npm.PackageJSON{Dependencies: map[string]string{"@babel/runtime": v}}, false, nil)
err = ctx.npmrc.installDependenciesContext(ctx.Context(), ctx.wd, &npm.PackageJSON{Dependencies: map[string]string{"@babel/runtime": v}}, false, nil)
}
if v, ok := ctx.pkgJson.Dependencies["@swc/helpers"]; ok {
ctx.npmrc.installDependencies(ctx.wd, &npm.PackageJSON{Dependencies: map[string]string{"@swc/helpers": v}}, false, nil)
if err == nil {
if v, ok := ctx.pkgJson.Dependencies["@swc/helpers"]; ok {
err = ctx.npmrc.installDependenciesContext(ctx.Context(), ctx.wd, &npm.PackageJSON{Dependencies: map[string]string{"@swc/helpers": v}}, false, nil)
}
}
}
if err != nil {
return
}
return
}

Expand Down
1 change: 1 addition & 0 deletions server/build_analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ func (ctx *BuildContext) analyzeSplitting() (err error) {
dev: ctx.dev,
wd: ctx.wd,
pkgJson: ctx.pkgJson,
ctx: ctx.ctx,
}
_, includes, err := b.buildModule(true)
if err != nil {
Expand Down
Loading
Loading