Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
ije committed Apr 22, 2024
1 parent 3c0ea6f commit c537282
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 76 deletions.
172 changes: 109 additions & 63 deletions server/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,20 @@ func (task *BuildTask) build() (err error) {
}
}

pkgSideEffects := api.SideEffectsTrue
if npm.SideEffectsFalse {
pkgSideEffects = api.SideEffectsFalse
}

noBundle := task.NoBundle || (npm.SideEffects != nil && npm.SideEffects.Len() > 0)
if npm.Esmsh != nil {
if v, ok := npm.Esmsh["bundle"]; ok {
if b, ok := v.(bool); ok && !b {
noBundle = true
}
}
}

nodeEnv := "production"
if task.Dev {
nodeEnv = "development"
Expand Down Expand Up @@ -290,20 +304,6 @@ func (task *BuildTask) build() (err error) {
browserExclude := map[string]*StringSet{}
implicitExternal := newStringSet()

noBundle := task.NoBundle || (npm.SideEffects != nil && npm.SideEffects.Len() > 0)
if npm.ESMConfig != nil {
if v, ok := npm.ESMConfig["bundle"]; ok {
if b, ok := v.(bool); ok && !b {
noBundle = true
}
}
}

pkgSideEffects := api.SideEffectsTrue
if npm.SideEffectsFalse {
pkgSideEffects = api.SideEffectsFalse
}

esmPlugin := api.Plugin{
Name: "esm",
Setup: func(build api.PluginBuild) {
Expand All @@ -320,30 +320,42 @@ func (task *BuildTask) build() (err error) {

// skip http modules
if strings.HasPrefix(args.Path, "data:") || strings.HasPrefix(args.Path, "https:") || strings.HasPrefix(args.Path, "http:") {
return api.OnResolveResult{Path: args.Path, External: true}, nil
return api.OnResolveResult{
Path: args.Path,
External: true,
}, nil
}

// if `?ignore-require` present, ignore specifier that is a require call
if task.Args.ignoreRequire && args.Kind == api.ResolveJSRequireCall && npm.Module != "" {
return api.OnResolveResult{Path: args.Path, External: true}, nil
return api.OnResolveResult{
Path: args.Path,
External: true,
}, nil
}

// ignore yarn PnP API
if args.Path == "pnpapi" {
return api.OnResolveResult{Path: args.Path, Namespace: "browser-exclude"}, nil
return api.OnResolveResult{
Path: args.Path,
Namespace: "browser-exclude",
}, nil
}

// it's implicit external
if implicitExternal.Has(args.Path) {
return api.OnResolveResult{Path: task.resolveExternalModule(args.Path, args.Kind), External: true}, nil
return api.OnResolveResult{
Path: task.resolveExternalModule(args.Path, args.Kind),
External: true,
}, nil
}

// normalize specifier
specifier := strings.TrimPrefix(args.Path, "node:")
specifier = strings.TrimPrefix(specifier, "npm:")

// bundle "@babel/runtime/helpers/*"
if args.Kind == api.ResolveJSRequireCall && (strings.HasPrefix(specifier, "@babel/runtime/helpers/") || strings.Contains(args.Importer, "/@babel/runtime/helpers/")) && task.npm.Name != "@babel/runtime" {
// bundle "@babel/runtime/*"
if (args.Kind == api.ResolveJSRequireCall || !noBundle) && task.npm.Name != "@babel/runtime" && (strings.HasPrefix(specifier, "@babel/runtime/") || strings.Contains(args.Importer, "/@babel/runtime/")) {
return api.OnResolveResult{}, nil
}

Expand Down Expand Up @@ -443,7 +455,10 @@ func (task *BuildTask) build() (err error) {
if name, ok := npm.Browser[spec]; ok {
if name == "" {
// browser exclude
return api.OnResolveResult{Path: args.Path, Namespace: "browser-exclude"}, nil
return api.OnResolveResult{
Path: args.Path,
Namespace: "browser-exclude",
}, nil
}
if strings.HasPrefix(name, "./") {
specifier = path.Join(task.resolveDir, "node_modules", npm.Name, name)
Expand Down Expand Up @@ -493,7 +508,10 @@ func (task *BuildTask) build() (err error) {
SubModule: toModuleBareName(subPath, true),
SubPath: subPath,
}
return api.OnResolveResult{Path: fmt.Sprintf("npm:%s", pkg.String()), External: true}, nil
return api.OnResolveResult{
Path: fmt.Sprintf("npm:%s", pkg.String()),
External: true,
}, nil
}
}
if specifier == "fsevents" {
Expand Down Expand Up @@ -531,13 +549,20 @@ func (task *BuildTask) build() (err error) {

// embed wasm as WebAssembly.Module
if strings.HasSuffix(fullFilepath, ".wasm") && existsFile(fullFilepath) {
return api.OnResolveResult{Path: fullFilepath, Namespace: "wasm"}, nil
return api.OnResolveResult{
Path: fullFilepath,
Namespace: "wasm",
}, nil
}

// externalize the _parent_ module
// e.g. "react/jsx-runtime" imports "react"
if task.Pkg.SubModule != "" && task.Pkg.Name == specifier && !task.Bundle {
return api.OnResolveResult{Path: task.resolveExternalModule(specifier, args.Kind), External: true}, nil
return api.OnResolveResult{
Path: task.resolveExternalModule(specifier, args.Kind),
External: true,
SideEffects: pkgSideEffects,
}, nil
}

// it's the entry point
Expand All @@ -547,7 +572,10 @@ func (task *BuildTask) build() (err error) {

// it's nodejs internal module
if nodejsInternalModules[specifier] {
return api.OnResolveResult{Path: task.resolveExternalModule(specifier, args.Kind), External: true}, nil
return api.OnResolveResult{
Path: task.resolveExternalModule(specifier, args.Kind),
External: true,
}, nil
}

// bundles all dependencies in `bundle` mode, apart from peer dependencies and `?external` query
Expand Down Expand Up @@ -616,7 +644,11 @@ func (task *BuildTask) build() (err error) {
exportPrefix, _ := utils.SplitByLastByte(name, '*')
url := path.Join(npm.Name, exportPrefix+strings.TrimPrefix(bareName, prefix))
if i := moduleName; url != i && url != i+"/index" {
return api.OnResolveResult{Path: task.resolveExternalModule(url, args.Kind), External: true, SideEffects: pkgSideEffects}, nil
return api.OnResolveResult{
Path: task.resolveExternalModule(url, args.Kind),
External: true,
SideEffects: pkgSideEffects,
}, nil
}
}
} else {
Expand All @@ -639,7 +671,11 @@ func (task *BuildTask) build() (err error) {
if match {
url := path.Join(npm.Name, stripModuleExt(name))
if i := moduleName; url != i && url != i+"/index" {
return api.OnResolveResult{Path: task.resolveExternalModule(url, args.Kind), External: true, SideEffects: pkgSideEffects}, nil
return api.OnResolveResult{
Path: task.resolveExternalModule(url, args.Kind),
External: true,
SideEffects: pkgSideEffects,
}, nil
}
}
}
Expand All @@ -658,7 +694,11 @@ func (task *BuildTask) build() (err error) {
if len(p) == 3 && string(p[0]) == "export*from" && string(p[2]) == ";\n" {
url := string(p[1])
if !isLocalSpecifier(url) {
return api.OnResolveResult{Path: task.resolveExternalModule(url, args.Kind), External: true}, nil
return api.OnResolveResult{
Path: task.resolveExternalModule(url, args.Kind),
External: true,
SideEffects: pkgSideEffects,
}, nil
}
}
}
Expand All @@ -672,22 +712,16 @@ func (task *BuildTask) build() (err error) {
}
}

// workaround for github packages that havn specified `name` field
if task.Pkg.FromGithub && specifier == npm.PkgName {
pkg := Pkg{
Name: npm.Name,
Version: npm.Version,
FromGithub: true,
}
resolvedPath := task.getImportPath(pkg, encodeBuildArgsPrefix(task.Args, pkg, false))
if args.Kind != api.ResolveJSDynamicImport {
task.imports = append(task.imports, [2]string{resolvedPath, resolvedPath})
}
return api.OnResolveResult{Path: resolvedPath, External: true, SideEffects: pkgSideEffects}, nil
}

// dynamic external
return api.OnResolveResult{Path: task.resolveExternalModule(specifier, args.Kind), External: true}, nil
sideEffects := api.SideEffectsFalse
if specifier == npm.Name || specifier == npm.PkgName || strings.HasPrefix(specifier, npm.Name+"/") || strings.HasPrefix(specifier, npm.Name+"/") {
sideEffects = pkgSideEffects
}
return api.OnResolveResult{
Path: task.resolveExternalModule(specifier, args.Kind),
External: true,
SideEffects: sideEffects,
}, nil
},
)

Expand Down Expand Up @@ -721,7 +755,6 @@ func (task *BuildTask) build() (err error) {
},
}

rebuild:
options := api.BuildOptions{
Outdir: "/esbuild",
Write: false,
Expand All @@ -735,25 +768,25 @@ rebuild:
KeepNames: task.Args.keepNames, // prevent class/function names erasing
IgnoreAnnotations: task.Args.ignoreAnnotations, // some libs maybe use wrong side-effect annotations
Conditions: task.Args.conditions.Values(),
// prevent features that can not be polyfilled
Supported: map[string]bool{
"bigint": true,
"top-level-await": true,
},
Plugins: []api.Plugin{esmPlugin},
// for css bundling
Loader: map[string]api.Loader{
".svg": api.LoaderDataURL,
".png": api.LoaderDataURL,
".webp": api.LoaderDataURL,
".gif": api.LoaderDataURL,
".ttf": api.LoaderDataURL,
".eot": api.LoaderDataURL,
".woff": api.LoaderDataURL,
".woff2": api.LoaderDataURL,
},
SourceRoot: "/",
Sourcemap: api.SourceMapExternal,
Plugins: []api.Plugin{esmPlugin},
SourceRoot: "/",
Sourcemap: api.SourceMapExternal,
}
// ignore features that can not be polyfilled
options.Supported = map[string]bool{
"bigint": true,
"top-level-await": true,
}
// bundling image/font assets
options.Loader = map[string]api.Loader{
".svg": api.LoaderDataURL,
".png": api.LoaderDataURL,
".webp": api.LoaderDataURL,
".gif": api.LoaderDataURL,
".ttf": api.LoaderDataURL,
".eot": api.LoaderDataURL,
".woff": api.LoaderDataURL,
".woff2": api.LoaderDataURL,
}
if task.Target == "node" {
options.Platform = api.PlatformNode
Expand Down Expand Up @@ -787,6 +820,8 @@ rebuild:
} else if entryPoint != "" {
options.EntryPoints = []string{entryPoint}
}

rebuild:
result := api.Build(options)
if len(result.Errors) > 0 {
// mark the missing module as external to exclude it from the bundle
Expand Down Expand Up @@ -1085,6 +1120,17 @@ func (task *BuildTask) resolveExternalModule(specifier string, kind api.ResolveK
}
}()

// it's current package from github
if npm := task.npm; task.Pkg.FromGithub && (specifier == npm.Name || specifier == npm.PkgName) {
pkg := Pkg{
Name: npm.Name,
Version: npm.Version,
FromGithub: true,
}
resolvedPath = task.getImportPath(pkg, encodeBuildArgsPrefix(task.Args, pkg, false))
return
}

// node builtin module
if nodejsInternalModules[specifier] {
if task.Args.external.Has("node:"+specifier) || task.Args.external.Has("*") {
Expand Down
14 changes: 7 additions & 7 deletions server/npm.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ type NpmPackageJSON struct {
Exports json.RawMessage `json:"exports,omitempty"`
Files []string `json:"files,omitempty"`
Deprecated interface{} `json:"deprecated,omitempty"`
ESMConfig interface{} `json:"esm.sh,omitempty"`
Esmsh interface{} `json:"esm.sh,omitempty"`
}

func (a *NpmPackageJSON) ToNpmPackage() *NpmPackageInfo {
Expand All @@ -77,10 +77,10 @@ func (a *NpmPackageJSON) ToNpmPackage() *NpmPackageInfo {
deprecated = s
}
}
esmConfig := map[string]interface{}{}
if a.ESMConfig != nil {
if v, ok := a.ESMConfig.(map[string]interface{}); ok {
esmConfig = v
esmsh := map[string]interface{}{}
if a.Esmsh != nil {
if v, ok := a.Esmsh.(map[string]interface{}); ok {
esmsh = v
}
}
var sideEffects *StringSet = nil
Expand Down Expand Up @@ -135,7 +135,7 @@ func (a *NpmPackageJSON) ToNpmPackage() *NpmPackageInfo {
Exports: exports,
Files: a.Files,
Deprecated: deprecated,
ESMConfig: esmConfig,
Esmsh: esmsh,
}
}

Expand All @@ -161,7 +161,7 @@ type NpmPackageInfo struct {
Exports interface{}
Files []string
Deprecated string
ESMConfig map[string]interface{}
Esmsh map[string]interface{}
}

func (a *NpmPackageInfo) UnmarshalJSON(b []byte) error {
Expand Down
2 changes: 1 addition & 1 deletion server/pkg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func TestPackageJsonParse(t *testing.T) {
if info.SideEffectsFalse != true {
t.Fatal("invalid sideEffects")
}
if info.ESMConfig["bundle"] != false {
if info.Esmsh["bundle"] != false {
t.Fatal("invalid esm.sh config")
}
}
Expand Down
4 changes: 1 addition & 3 deletions test/nested-conditions/nested-conditions.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { assertExists } from "https://deno.land/[email protected]/assert/mod.ts";

Deno.test("Nested conditions", async () => {
const utils = await import(
`http://localhost:8080/[email protected]/es2022/vanilla/utils.js`
);
const utils = await import("http://localhost:8080/[email protected]/es2022/vanilla/utils.js");
assertExists(utils.splitAtom);
});
4 changes: 2 additions & 2 deletions test/package-css/package-css.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ Deno.test("package css", async () => {
);
assertEquals(
res.url,
`http://localhost:8080/[email protected]/es2022/monaco-editor.css`,
"http://localhost:8080/[email protected]/es2022/monaco-editor.css",
);
assertEquals(res.headers.get("content-type"), "text/css; charset=utf-8");
res.body?.cancel();

const res2 = await fetch(
`http://localhost:8080/[email protected]/es2022/monaco-editor.css`,
"http://localhost:8080/[email protected]/es2022/monaco-editor.css",
);
assertEquals(res2.headers.get("content-type"), "text/css; charset=utf-8");
res2.body?.cancel();
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit c537282

Please sign in to comment.