Closed fabiospampinato closed 2 years ago
This is because the default json loader (built-in in esbuild) turns a json file into this form:
// { "a": [42] }
export var a = [42]
export default { a }
// this guarantees that
import X, { a } from "./a.json"
X.a === a // true, is same thing (by reference)
But key names are repeated at least 2 times. In that case, you can write a plugin to alter that behavior if you only want the default export:
var MyJsonLoader = {
name: 'my-json-loader',
setup({ onLoad }) {
onLoad({ filter: /\.json$/ }, async args => {
const text = await fs.promises.readFile(args.path, 'utf8')
return { contents: `export default ${text}` }
})
}
}
(I don't think this behavior should be built-in, since it requires some analysis around the usage of a json file (whether it was imported by names).
(I don't think this behavior should be built-in, since it requires some analysis around the usage of a json file (whether it was imported by names).
Wouldn't this be a trivial check though? It seems worth it to me, the length of the output code can get a little out of hand otherwise.
The reason for this is tree-shaking. For example, the following code:
export { 'application/wasm' as wasm } from './database.json'
currently bundles into the following code (with --bundle --format=esm
):
With your suggested change, you would have to do something like this instead:
import db from './database.js'
export let { 'application/wasm': wasm } = db
which would bundle into the following code (with --bundle --format=esm
):
There's probably something I can do to make this more efficient when only the default
export ends up being used. But only exposing the default
export would be a regression in functionality for tree shaking. As you can see with this example, it would be quite a big size regression in some cases.
Makes sense, it's not as simple as I naively thought 🤔 Still it's probably worth addressing eventually.
esbuild seems to transform json imports relatively inefficiently.
Given the following
index.ts
:The following
database.json
:And the following command:
I'm getting the following code, beautified by me to highlight the problem:
There's basically a huge number of unnecessary intermediate variables, I would have expected to find the input json basically copy/pasted in the output file, but that wasn't the case.