Skip to content

Commit

Permalink
fix #459: add a "public path" option
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Oct 18, 2020
1 parent eb0190f commit f2bb75e
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 2 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# Changelog

## Unreleased

* Add `--public-path=` for the `file` loader ([#459](https://github.com/evanw/esbuild/issues/459))

The `file` loader causes importing a file to cause that file to be copied into the output directory. The name of the file is exported as the default export:

```js
// Assume ".png" is set to the "file" loader
import name from 'images/image.png'

// This prints something like "image.L3XDQOAT.png"
console.log(name)
```

The new public path setting configures the path prefix. So for example setting it to `https://www.example.com/v1` would change the output text for this example to `https://www.example.com/v1/image.L3XDQOAT.png`.

## 0.7.16

* Fix backward slashes in source maps on Windows ([#463](https://github.com/evanw/esbuild/issues/463))
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ Advanced options:
--main-fields=... Override the main file order in package.json
(default "browser,module,main" when platform is
browser and "main,module" when platform is node)
--public-path=... Set the base URL for the "file" loader
--color=... Force use of color terminal escapes (true | false)

Examples:
Expand Down
1 change: 1 addition & 0 deletions cmd/esbuild/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ Advanced options:
--main-fields=... Override the main file order in package.json
(default "browser,module,main" when platform is
browser and "main,module" when platform is node)
--public-path=... Set the base URL for the "file" loader
--color=... Force use of color terminal escapes (true | false)
Examples:
Expand Down
5 changes: 3 additions & 2 deletions internal/bundler/bundler.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,14 +275,15 @@ func parseFile(args parseArgs) {
hash := hashForFileName([]byte(source.Contents))
ext := path.Ext(args.baseName)
baseName := args.baseName[:len(args.baseName)-len(ext)] + "." + hash + ext
publicPath := args.options.PublicPath + baseName

// Determine the destination folder
targetFolder := args.options.AbsOutputDir

// Export the resulting relative path as a string
expr := js_ast.Expr{Data: &js_ast.EString{Value: js_lexer.StringToUTF16(baseName)}}
expr := js_ast.Expr{Data: &js_ast.EString{Value: js_lexer.StringToUTF16(publicPath)}}
ast := js_parser.LazyExportAST(args.log, source, args.options, expr, "")
ast.URLForCSS = baseName
ast.URLForCSS = publicPath
result.file.ignoreIfUnused = true
result.file.repr = &reprJS{ast: ast}
result.ok = true
Expand Down
1 change: 1 addition & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ type Options struct {
TsConfigOverride string
ExtensionToLoader map[string]Loader
OutputFormat Format
PublicPath string

// If present, metadata about the bundle is written as JSON here
AbsMetadataFile string
Expand Down
2 changes: 2 additions & 0 deletions lib/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ function flagsForBuildOptions(options: types.BuildOptions, isTTY: boolean, logLe
let external = getFlag(options, keys, 'external', mustBeArray);
let loader = getFlag(options, keys, 'loader', mustBeObject);
let outExtension = getFlag(options, keys, 'outExtension', mustBeObject);
let publicPath = getFlag(options, keys, 'publicPath', mustBeString);
let entryPoints = getFlag(options, keys, 'entryPoints', mustBeArray);
let stdin = getFlag(options, keys, 'stdin', mustBeObject);
let write = getFlag(options, keys, 'write', mustBeBoolean) !== false;
Expand All @@ -139,6 +140,7 @@ function flagsForBuildOptions(options: types.BuildOptions, isTTY: boolean, logLe
if (platform) flags.push(`--platform=${platform}`);
if (tsconfig) flags.push(`--tsconfig=${tsconfig}`);
if (resolveExtensions) flags.push(`--resolve-extensions=${resolveExtensions.join(',')}`);
if (publicPath) flags.push(`--public-path=${publicPath}`);
if (mainFields) flags.push(`--main-fields=${mainFields.join(',')}`);
if (external) for (let name of external) flags.push(`--external:${name}`);
if (loader) {
Expand Down
1 change: 1 addition & 0 deletions lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export interface BuildOptions extends CommonOptions {
write?: boolean;
tsconfig?: string;
outExtension?: { [ext: string]: string };
publicPath?: string;

entryPoints?: string[];
stdin?: StdinOptions;
Expand Down
1 change: 1 addition & 0 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ type BuildOptions struct {
ResolveExtensions []string
Tsconfig string
OutExtensions map[string]string
PublicPath string

EntryPoints []string
Stdin *StdinOptions
Expand Down
4 changes: 4 additions & 0 deletions pkg/api/api_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,10 @@ func buildImpl(buildOpts BuildOptions) BuildResult {
ExternalModules: validateExternals(log, realFS, buildOpts.Externals),
TsConfigOverride: validatePath(log, realFS, buildOpts.Tsconfig),
MainFields: buildOpts.MainFields,
PublicPath: buildOpts.PublicPath,
}
if options.PublicPath != "" && !strings.HasSuffix(options.PublicPath, "/") && !strings.HasSuffix(options.PublicPath, "\\") {
options.PublicPath += "/"
}
entryPaths := make([]string, len(buildOpts.EntryPoints))
for i, entryPoint := range buildOpts.EntryPoints {
Expand Down
3 changes: 3 additions & 0 deletions pkg/cli/cli_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ func parseOptionsImpl(osArgs []string, buildOpts *api.BuildOptions, transformOpt
case strings.HasPrefix(arg, "--main-fields=") && buildOpts != nil:
buildOpts.MainFields = strings.Split(arg[len("--main-fields="):], ",")

case strings.HasPrefix(arg, "--public-path=") && buildOpts != nil:
buildOpts.PublicPath = arg[len("--public-path="):]

case strings.HasPrefix(arg, "--global-name="):
if buildOpts != nil {
buildOpts.GlobalName = arg[len("--global-name="):]
Expand Down
60 changes: 60 additions & 0 deletions scripts/js-api-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,66 @@ let buildTests = {
assert.strictEqual(result.__esModule, true)
},

async fileLoader({ esbuild, testDir }) {
const input = path.join(testDir, 'in.js')
const data = path.join(testDir, 'data.bin')
const output = path.join(testDir, 'out.js')
await writeFileAsync(input, `export {default as value} from ${JSON.stringify(data)}`)
await writeFileAsync(data, `stuff`)
const value = await esbuild.build({
entryPoints: [input],
bundle: true,
outfile: output,
format: 'cjs',
loader: { '.bin': 'file' },
})
assert.strictEqual(value.outputFiles, void 0)
const result = require(output)
assert.strictEqual(result.value, 'data.L3XDQOAT.bin')
assert.strictEqual(result.__esModule, true)
},

async fileLoaderPublicPath({ esbuild, testDir }) {
const input = path.join(testDir, 'in.js')
const data = path.join(testDir, 'data.bin')
const output = path.join(testDir, 'out.js')
await writeFileAsync(input, `export {default as value} from ${JSON.stringify(data)}`)
await writeFileAsync(data, `stuff`)
const value = await esbuild.build({
entryPoints: [input],
bundle: true,
outfile: output,
format: 'cjs',
loader: { '.bin': 'file' },
publicPath: 'https://www.example.com/assets',
})
assert.strictEqual(value.outputFiles, void 0)
const result = require(output)
assert.strictEqual(result.value, 'https://www.example.com/assets/data.L3XDQOAT.bin')
assert.strictEqual(result.__esModule, true)
},

async fileLoaderCSS({ esbuild, testDir }) {
const input = path.join(testDir, 'in.css')
const data = path.join(testDir, 'data.bin')
const output = path.join(testDir, 'out.css')
await writeFileAsync(input, `body { background: url(${JSON.stringify(data)}) }`)
await writeFileAsync(data, `stuff`)
const value = await esbuild.build({
entryPoints: [input],
bundle: true,
outfile: output,
loader: { '.bin': 'file' },
publicPath: 'https://www.example.com/assets',
})
assert.strictEqual(value.outputFiles, void 0)
assert.strictEqual(await readFileAsync(output, 'utf8'), `/* scripts/.js-api-tests/fileLoaderCSS/in.css */
body {
background: url(https://www.example.com/assets/data.L3XDQOAT.bin);
}
`)
},

async metafile({ esbuild, testDir }) {
const entry = path.join(testDir, 'entry.js')
const imported = path.join(testDir, 'imported.js')
Expand Down

0 comments on commit f2bb75e

Please sign in to comment.