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 does not respect user's build.lib.formats option. #2

Closed
darkobits opened this issue Feb 4, 2023 · 6 comments
Closed

Plugin does not respect user's build.lib.formats option. #2

darkobits opened this issue Feb 4, 2023 · 6 comments

Comments

@darkobits
Copy link

Provided a configuration such as:

export default {
  build: {
    lib: {
      formats: ['cjs'],
      entry: // ...
    }
  },
  plugins: [
    noBundlePlugin(
      // ...
    )
  ]
}

The output directory will contain files in ESM format. I believe this is happening due to this line, which when commented-out, causes Vite to respect the formats option provided by the user.

@ManBearTM
Copy link
Owner

Yes, you’re right, the plugin forces ESM. It is because the plugin actually does two things: one, it preserves the modules in the output folder, and two, it allows you to copy assets into the output folder instead of inlining them.

For example, given the following configuration:

export default {
  build: {
    lib: {
      entry: // ...
    }
  },
  plugins: [
    noBundlePlugin({
      copy: **/*.png
    })
  ]
}

… and a file like this:

import imgUrl from './img.png'
document.getElementById('hero-img').src = imgUrl

This will result in the png file being copied to the output folder while the import remains unchanged. This allows the consuming bundler to get the imgUrl using import.meta, which is only valid in an ESM environment (more about this here).

I guess there is no harm in removing the forced format to allow for other module systems as long as the caveats are documented. I can see why you might not need that particular functionality. May I know what your use case is with commonjs?

@ManBearTM
Copy link
Owner

I have removed the forced format in the latest release (2.0.1), so you should be able to use commonjs now 🙂

@darkobits
Copy link
Author

Thanks!

An example use-case of mine would be a package published to NPM where bundling isn't necessary. While I write in TypeScript, I still prefer to publish as CommonJS as this is the easiest way for both ESM and CJS consumers of the package to use it, at least until the ESM ecosystem becomes more mature. I know Vite / Rollup aren't technically meant for this, but Vite's speed and tooling ecosystem (Vitest, for example) are fantastic, so I've been trying to develop a purely Vite-based toolchain for developing NPM packages.

@morganney
Copy link

I suppose this implies that having multiple lib.formats defined is not supported? I've noticed that if you define two, for example, ['es', 'cjs'] then the last one always wins, i.e. the vite default behavior of creating appropriate extensions for each build is not preserved.

@ManBearTM
Copy link
Owner

I suppose this implies that having multiple lib.formats defined is not supported? I've noticed that if you define two, for example, ['es', 'cjs'] then the last one always wins, i.e. the vite default behavior of creating appropriate extensions for each build is not preserved.

Interesting problem 🤔 I don't do anything specifically to prevent multiple formats, but I reckon it could have something to do with the entryFileNames defaulting to "[name].js". Have you tried setting fileNames to "[name].[format].js" in the plugin options? I wonder if both formats are being generated, but since the file names are identical, the latter format overwrites the other.

I would like to look more into this, perhaps you could describe your use case so that I can find the right solution? 🙂

@morganney
Copy link

morganney commented Aug 6, 2023

Yes, I can get to a working build by using fileNames with a value of '[name].[format].js' but that requires using the default extensions, which works for the most part. What I would rather, and which I tried first was '[name].[format]', but that produces an error because the .es extension is not resolvable by default. You could probably throw some alias or resolution config at vite to bypass this, but that's more than I'd rather do.

My end goal was a dual build with vite-plugin-no-bundle with configurable file extensions per build, as alluded to by the pattern mentioned above for fileNames (which rollup doesn't support). Something like this:

export default defineConfig({
  build: {
    lib: {
      formats: ['cjs', 'es'],
      entry: ['src/index.ts'],
    },
  },
  plugins: [
    nobundle({
      fileNames: '[name].[format]'
    }),
  ],
})

For now, I've opted to simply use a native vite build in library mode by clearly specifying each lib.entry and combining with vite-plugin-specifier to get the extensions I prefer. The nice feature I was hoping to get from this plugin was not needing to manually list every lib.entry for the build, and instead point it to only the main index file.

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

3 participants