evanw / esbuild

An extremely fast bundler for the web
https://esbuild.github.io/
MIT License
38.15k stars 1.15k forks source link

How to build a product without a filesystem (Probably a bug) #2857

Closed Linkontoask closed 1 year ago

Linkontoask commented 1 year ago

I want esbuild to automatically handle the duplicate imports in the file for me, and I also want to use its tree shaking capabilities to help me optimise my code and then output it to a file, I wrote the following code to try and do the above, but I could never get it right

export interface ConfigSource extends Partial<Options> {
  code: string
  name: string
  loader: Loader
}

export interface Config {
  sources: ConfigSource[]
  options?: BuildOptions
}

function babelBuildWithBundle(main: ConfigSource, config: Config) {
  const buildModuleRuntime: Plugin = {
    name: 'buildModuleRuntime',
    setup(build) {
      build.onResolve({ filter: /\.\// }, (args) => {
        return { path: args.path, namespace: 'localModule' }
      })
      build.onLoad({ filter: /\.\//, namespace: 'localModule' }, (args) => {
        const source = config.sources.find(
          (source) =>
            source.name.replace(/\..+$/, '') === args.path.replace(/^\.\//, '')
        )

        const content = source?.code || ''
        return {
          contents: content,
          loader: source?.loader || 'js',
        }
      })
    },
  }
  return build(
     {
        stdin: {
          contents: main.code,
          loader: main.loader,
          sourcefile: main.name,
          resolveDir: path.resolve('.'),
        },
        bundle: true,
        write: false,
        format: 'esm',
        outdir: 'dist',
        plugins: [buildModuleRuntime],
      }
  )
}
const foo = `
      export const Foo = FC(() => {
        return <div>gyron</div>
      })
    `
    const app = `
      import { Foo } from './foo'
      function App(): any {
        console.log(B)
        return <Foo />
      }
    `
    const bundle = await babelBuildWithBundle(
      {
        loader: 'tsx',
        code: app,
        name: 'app.tsx',
      },
      {
        sources: [
          {
            loader: 'tsx',
            code: foo,
            name: 'foo.tsx',
          },
        ],
      }
    )

Then the only answer I got in the final output was

console.log(bundle.outputFiles[0].text)

`
// localModule:. /foo
    var Foo = FC(() => {
      return /* @__PURE__ */ React.createElement("div", null, "gyron");
    });
`

console.log(bundle.outputFiles[1])

`
undefined
`
evanw commented 1 year ago

Sorry, I don’t understand what you’re saying. Are you saying that you expected App to be in the output but it wasn’t? Nothing uses App so it was tree-shaken away.

Linkontoask commented 1 year ago

@evanw Thank you for your reply. Yes, I was expecting the App to output in as well

Linkontoask commented 1 year ago

I have just tried setting treeShaking to false and can pack the app into the product.