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

feature: single banner/footer per compiled file #3517

Open
dalechyn opened this issue Nov 29, 2023 · 1 comment
Open

feature: single banner/footer per compiled file #3517

dalechyn opened this issue Nov 29, 2023 · 1 comment

Comments

@dalechyn
Copy link

As of now, esbuild inserts a banner before every built file even if it's bundled within a single chunk.

In my case, I insert the use client directive, and it's being inserted multiple times within a single chunk, which leads to the next error when my package is used in nextjs:

ReactServerComponentsError:

The "use client" directive must be placed before other expressions. Move it to the top of the file to resolve this issue.

My proposal is to extend the BannerOrFooter to accept a new option single: boolean which would default to false to ensure backwards compatibility, yet that would insert a banner or a footer only once in a compiled file.

...
banner: {
   js: '"use client";',
   single: true
},
...
@dalechyn dalechyn changed the title feature: one banner/footer per compiled file feature: single banner/footer per compiled file Nov 29, 2023
@dalechyn
Copy link
Author

This is the workaround I'm currently using:

    // banner: {
    //   js: '"use client";',
    // },
    // Hack to avoid multiple `use client` directives in single file instead of using banner.
    // Delete when implemented https://github.com/evanw/esbuild/issues/3517
    async onSuccess() {
      // recursively go through each js file in dist and add "use client" to the top
      const distDir = path.join(__dirname, 'dist')
      const files = await fs.readdir(distDir)

      async function processFilesRecursively(dir: string) {
        // Read dirents of the current folder
        const dirents = await fs.readdir(dir, { withFileTypes: true })
        const promises = dirents.map(async (dirent) => {
          const filePath = dirent.path + '/' + dirent.name
          if (dirent.isDirectory()) return processFilesRecursively(filePath)

          if (dirent.name.endsWith('.js')) {
            const fileContents = await fs.readFile(filePath, 'utf8')
            const newFileContents = `'use client'\n${fileContents
              .replaceAll('"use client"', '')
              .replaceAll("'use client'", '')}`
            await fs.writeFile(filePath, newFileContents)
          }
        })
        return Promise.all(promises.flat())
      }
      await processFilesRecursively(distDir)
    },

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

1 participant