Path resolution is a mess. One tricky issue is the "module" override for the
"main" field in "package.json" files. Bundlers generally prefer "module" over
"main" but that breaks packages that export a function in "main" for use with
"require()", since resolving to "module" means an object will be returned. We
attempt to handle this automatically by having import statements resolve to
"module" but switch that out later for "main" if "require()" is used too.
Either secondary will be empty, or primary will be "module" and secondary
will be "main"
Secondarylogger.Path(*T) HasSecondary() bool(*T) iter() []*logger.Path
DifferentCase*fs.DifferentCase
If true, any ES6 imports to this file can be considered to have no side
effects. This means they should be removed if unused.
IsExternalbool
If not empty, these should override the default values
// Default if empty: "React.createElement"
// Default if empty: "React.Fragment"
PathPairPathPair
If this was resolved by a plugin, the plugin gets to store its data here
If true, unused imports are retained in TypeScript code. This matches the
behavior of the "importsNotUsedAsValues" field in "tsconfig.json" when the
value is not "remove".
If true, the class field transform should use Object.defineProperty().
func Resolver.ProbeResolvePackageAsRelative(sourceDir string, importPath string, kind ast.ImportKind) *ResolveResult
func Resolver.Resolve(sourceDir string, importPath string, kind ast.ImportKind) *ResolveResult
func Resolver.ResolveAbs(absPath string) *ResolveResult
func github.com/evanw/esbuild/internal/bundler.runOnResolvePlugins(plugins []config.Plugin, res Resolver, log logger.Log, fs fs.FS, importSource *logger.Source, importPathRange logger.Range, path string, kind ast.ImportKind, absResolveDir string, pluginData interface{}) (*ResolveResult, bool)
The absolute path of "compilerOptions.baseUrl"
This is used if "Paths" is non-nil. It's equal to "BaseURL" except if
"BaseURL" is missing, in which case it is as if "BaseURL" was ".". This
is to implement the "paths without baseUrl" feature from TypeScript 4.1.
More info: https://github.com/microsoft/TypeScript/issues/31869
JSXFactory[]stringJSXFragmentFactory[]string
The verbatim values of "compilerOptions.paths". The keys are patterns to
match and the values are arrays of fallback paths to search. Each key and
each fallback path can optionally have a single "*" wildcard character.
If both the key and the value have a wildcard, the substring matched by
the wildcard is substituted into the fallback path. The keys represent
module-style path names and the fallback paths are relative to the
"baseUrl" value in the "tsconfig.json" file.
PreserveImportsNotUsedAsValuesboolUseDefineForClassFieldsbool
func ParseTSConfigJSON(log logger.Log, source logger.Source, jsonCache *cache.JSONCache, extends func(string, logger.Range) *TSConfigJSON) *TSConfigJSON
All relevant information about this directory
// Is there an "index.js" file?
// If non-empty, this is the real absolute path resolving any symlinks
A pointer to the enclosing dirInfo with a valid "browser" field in
package.json. We need this to remap paths after they have been resolved.
entriesfs.DirEntries
// Is there a "node_modules" subdirectory?
// Is there a "package.json" file?
These objects are immutable, so we can just point to the parent directory
and avoid having to lock the cache again
// Is there a "tsconfig.json" file in this directory or a parent directory?
absMainFieldsmap[string]string
Present if the "browser" field is present. This field is intended to be
used by bundlers and lets you redirect the paths of certain 3rd-party
modules that don't work in the browser to other modules that shim that
functionality. That way you don't have to rewrite the code for those 3rd-
party modules. For example, you might remap the native "util" node module
to something like https://www.npmjs.com/package/util so it works in the
browser.
This field contains a mapping of absolute paths to absolute paths. Mapping
to an empty path indicates that the module is disabled. As far as I can
tell, the official spec is a GitHub repo hosted by a user account:
https://github.com/defunctzombie/package-browser-field-spec. The npm docs
say almost nothing: https://docs.npmjs.com/files/package.json.
Note that the non-package "browser" map has to be checked twice to match
Webpack's behavior: once before resolution and once after resolution. It
leads to some unintuitive failure cases that we must emulate around missing
file extensions:
* Given the mapping "./no-ext": "./no-ext-browser.js" the query "./no-ext"
should match but the query "./no-ext.js" should NOT match.
* Given the mapping "./ext.js": "./ext-browser.js" the query "./ext.js"
should match and the query "./ext" should ALSO match.
browserPackageMapmap[string]*stringignoreIfUnusedData*IgnoreIfUnusedData
If this is non-nil, each entry in this map is the absolute path of a file
with side effects. Any entry not in this map should be considered to have
no side effects, which means import statements for these files can be
removed if none of the imports are used. This is a convention from Webpack:
https://webpack.js.org/guides/tree-shaking/.
Note that if a file is included, all statements that can't be proven to be
free of side effects must be included. This convention does not say
anything about whether any statements within the file have side effects or
not.
sideEffectsRegexps[]*regexp.Regexp
A special filtered import order for CSS "@import" imports.
The "resolve extensions" setting determines the order of implicit
extensions to try when resolving imports with the extension omitted.
Sometimes people create a JavaScript/TypeScript file and a CSS file with
the same name when they create a component. At a high level, users expect
implicit extensions to resolve to the JS file when being imported from JS
and to resolve to the CSS file when being imported from CSS.
Different bundlers handle this in different ways. Parcel handles this by
having the resolver prefer the same extension as the importing file in
front of the configured "resolve extensions" order. Webpack's "css-loader"
plugin just explicitly configures a special "resolve extensions" order
consisting of only ".css" for CSS files.
It's unclear what behavior is best here. What we currently do is to create
a special filtered version of the configured "resolve extensions" order
for CSS files that filters out any extension that has been explicitly
configured with a non-CSS loader. This still gives users control over the
order but avoids the scenario where we match an import in a CSS file to a
JavaScript-related file. It's probably not perfect with plugins in the
picture but it's better than some alternatives and probably pretty good.
caches*cache.CacheSet
This cache maps a directory path to information about that directory and
all parent directories
fsfs.FSloglogger.Log
This mutex serves two purposes. First of all, it guards access to "dirCache"
which is potentially mutated during path resolution. But this mutex is also
necessary for performance. The "React admin" benchmark mysteriously runs
twice as fast when this mutex is locked around the whole resolve operation
instead of around individual accesses to "dirCache". For some reason,
reducing parallelism in the resolver helps the rest of the bundler go
faster. I'm not sure why this is but please don't change this unless you
do a lot of testing with various benchmarks and there aren't any regressions.
optionsconfig.Options(*T) PrettyPath(path logger.Path) string(*T) ProbeResolvePackageAsRelative(sourceDir string, importPath string, kind ast.ImportKind) *ResolveResult(*T) Resolve(sourceDir string, importPath string, kind ast.ImportKind) *ResolveResult(*T) ResolveAbs(absPath string) *ResolveResult(*T) dirInfoCached(path string) *dirInfo(*T) dirInfoUncached(path string) *dirInfo(*T) finalizeResolve(result *ResolveResult)(*T) isExternalPattern(path string) bool(*T) loadAsFile(path string, extensionOrder []string) (string, bool, *fs.DifferentCase)(*T) loadAsFileOrDirectory(path string, kind ast.ImportKind) (PathPair, bool, *fs.DifferentCase)
We want to minimize the number of times directory contents are listed. For
this reason, the directory entries are computed by the caller and then
passed down to us.
(*T) loadNodeModules(path string, kind ast.ImportKind, dirInfo *dirInfo) (PathPair, bool, *fs.DifferentCase)
This closely follows the behavior of "tryLoadModuleUsingPaths()" in the
official TypeScript compiler
(*T) parsePackageJSON(path string) *packageJSON
This may return "parseErrorAlreadyLogged" in which case there was a syntax
error, but it's already been reported. No further errors should be logged.
Nested calls may also return "parseErrorImportCycle". In that case the
caller is responsible for logging an appropriate error message.
(*T) resolveWithoutRemapping(sourceDirInfo *dirInfo, importPath string, kind ast.ImportKind) (PathPair, bool, *fs.DifferentCase)(*T) resolveWithoutSymlinks(sourceDir string, importPath string, kind ast.ImportKind) *ResolveResult
*T : Resolver
Package-Level Functions (total 13, in which 5 are exported)
The pages are generated with Goldsv0.3.2-preview. (GOOS=darwin GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.