Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[plugin] When return contents, the output path does not meet the expected result #864

Closed
pandagood opened this issue Feb 21, 2021 · 4 comments

Comments

@pandagood
Copy link

pandagood commented Feb 21, 2021

@evanw
I try to convert commonjs to esm:

require('esbuild').build({
  target: 'esnext',
  format: 'esm',
  bundle: true,
  write: true,
  splitting:true,
  entryPoints: [
    'react',
    'react-dom',
    'react-dom/server',
  ],
  outdir: join(process.cwd(),'/packages'),
  define: {
    'process.env.NODE_ENV': JSON.stringify('development')
  },
  plugins: [{
    name: 'transform-plugin',
    setup(build) { 
      build.onResolve({ filter: /.*/ }, args => {
        if (args.importer === '') return { path: args.path, namespace: 'transform' }
      })
      build.onLoad({ filter: /.*/, namespace: 'transform' }, async (args) => {
        const keys = Object.keys(require(args.path))
          .filter(i=>i!="default")
          .join(', ')
        return { 
          contents: `export { ${keys} } from "${args.path}";import m from "${args.path}";export default m;`, 
          resolveDir: process.cwd() 
        }
      })
    }
  }],
})

It works well, but the output path is not the expected result.

expected output path:

- packages
  - chunk.USOOALQH.js 
  - react
     - index.js
  - react-dom
     - index.js
     - server.js

Current output path:

- packages
  - chunk.USOOALQH.js
  - react.js
  - react-dom.js
  - server.js

The same question appears in #744 , but there is no answer.

The description about contents in the esbuild doc:

If this is set, no more on-load callbacks will be run for this resolved path

This seems to be the cause of the problem.

@pandagood
Copy link
Author

In addition, I want to export through the export * from "${args.path}" syntax, but it doesn't work:

 build.onLoad({ filter: /.*/, namespace: 'transform' }, async (args) => {
   return { 
     contents: `export * from "${args.path}";import m from "${args.path}";export default m;`, 
     resolveDir: process.cwd() 
   }
 })

Build and after running:

import React,{ useState } from "./packages/react.js"
               ^^^^^^^^
SyntaxError: The requested module './packages/react.js' does not provide an export named 'useState'

@pandagood pandagood changed the title [plugin] When returning contents via onLoad callback, the output path does not meet the expected result [plugin] When return contents, the output path does not meet the expected result Feb 22, 2021
@pandagood
Copy link
Author

@evanw How can I solve the above problems?

@evanw
Copy link
Owner

evanw commented Feb 23, 2021

It's probably not possible to solve this yet with a single run of esbuild and no other code. One option is to run esbuild multiple times (once for each entry point) and use outfile to set the output file name. Another option might be to manually move the files after esbuild runs.

Closing as a duplicate of #442 for somehow automatically exporting all keys from a CommonJS module as named exports and as a duplicate of #553 for being able to override the output file path of specific output files.

@evanw evanw closed this as completed Feb 23, 2021
@pandagood
Copy link
Author

pandagood commented Feb 23, 2021

@evanw

One option is to run esbuild multiple times (once for each entry point) and use outfile to set the output file name

This is feasible, but it cannot enjoy the benefits of splitting, which is not a good solution.

Another option might be to manually move the files after esbuild runs

This seems a bit clumsy, it still has a problem:

output files share the same path but have different contents

Suppose I execute the following build:

require('esbuild').build({
  format: 'esm',
  entryPoints: [
    'react-dom/server',
    'react-router-dom/server',
  ],
  ....
})

It will throw an error:

output files share the same path but have different contents: server.js

The #553 is a very good solution, and I look forward to its early realization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants