vite icon indicating copy to clipboard operation
vite copied to clipboard

Support external in dev

Open hasangenc0 opened this issue 3 years ago • 19 comments

Clear and concise description of the problem

When I have external dependencies that are not a npm package, vite dev server throws an error in vite:import-analysis stage. vite build command just works fine but vite command tries to resolve all of the external dependencies in the import-analysis stage.

Suggested solution

Skip resolving the external dependencies in import-analysis.

Alternative

No response

Additional context

No response

Validations

hasangenc0 avatar Jan 21 '22 11:01 hasangenc0

As noted in https://github.com/vitejs/vite/pull/6583#issuecomment-1024148754, it would be great if you can explain how you encountered the issue and what error it gives. That would help us evaluate the correct fix for it.

bluwy avatar Apr 03 '22 14:04 bluwy

I created an example repo to demonstrate the error: https://github.com/hasangenc0/vite-externaldep-error

hasangenc0 avatar Apr 03 '22 20:04 hasangenc0

Thanks for the example @hasangenc0. I tried implementing this at https://github.com/bluwy/vite/tree/rollup-options-external. Turns out there's a lot more to be done to fully support externalizing deps.

I think I got it nearly done, except that we can't just leave import 'external-dep in the browser as it has the import has to start with . or `'/', that means implementing https://rollupjs.org/guide/en/#makeabsoluteexternalsrelative. That might be an endeavor for another day.

If you'd like you can build on top of my changes, or update #6583 with it. I think #6583 at its current state isn't sufficient.

bluwy avatar Jun 12 '22 13:06 bluwy

A workaround mentioned in https://github.com/vitejs/vite/issues/6393#issuecomment-1006819717 might help for now.

bluwy avatar Jun 23 '22 05:06 bluwy

Any updates?

dev external is very useful to build third party libs only privide .d.ts.

terwer avatar May 13 '23 12:05 terwer

Besides the implementation not being done yet, in a recent team meeting we discussed to have the new option at resolve.external to support both dev and build. I haven't got time to follow-up on my changes, so un-assigning myself in case someone is interested in implementing it.

bluwy avatar May 14 '23 17:05 bluwy

I think I got it nearly done, except that we can't just leave import 'external-dep' in the browser as it has the import has to start with . or `'/', that means implementing rollupjs.org/guide/en/#makeabsoluteexternalsrelative. That might be an endeavor for another day.

@bluwy do you have a good example of this one? I think import 'external-dep' may only work if the user defines an import map for it. In that case, we don't need to add something extra (except maybe a warning, but that could be hard to implement if there are multiple HTML entry points or a framework is used).

patak-dev avatar May 15 '23 09:05 patak-dev

I saw that #12711 was closed in favor of keeping this issue open. Is there any plan to resolve this?

In my digging it seems like the dev server uses ESBuild for module resolution. Why is there no built in support for ESBuild's external API?

Djfaucette avatar May 15 '23 16:05 Djfaucette

I'm not sure if this is related or not but I see the exported interface for the ESBuild plugin references exclude instead of internal on this line: https://github.com/vitejs/vite/blob/main/packages/vite/src/node/plugins/esbuild.ts#L42

I could not find an exclude option in ESBuild's API.

Djfaucette avatar May 15 '23 19:05 Djfaucette

@bluwy do you have a good example of this one? I think import 'external-dep' may only work if the user defines an import map for it. In that case, we don't need to add something extra (except maybe a warning, but that could be hard to implement if there are multiple HTML entry points or a framework is used).

I implemented the stuff before I was familiar about importmaps, so yeah I think importmaps could be a good reason that we can leave that as-is for now. Supporting makeAbsoluteExternalsRelative could still be nice but can be implemented later.


@Djfaucette I don't have any plans for now so I added the "contributions welcome" label. Maybe one day I'll revisit if I can get the motivation 😬 This shouldn't meddle with esbuild at all, except for Vite's optimizer that uses esbuild, which we need to pass the external there. We don't use esbuild for module resolution.

bluwy avatar May 16 '23 07:05 bluwy

hello, I am trying to create a lib, that externalize Firebase, but it does not works. rollupOptions: { // make sure to externalize deps that shouldn't be bundled // into your library external: ['firebase'] } I have used this code in vite.config.js, but, but the rollup-plugin-visualizer, I can observe that the firebase dependency is included in my library. Is that normal ? tks

AxeloLabs avatar Jun 28 '23 06:06 AxeloLabs

I have created a plugin to solve this issue during development, until official support is implemented:

https://github.com/MilanKovacic/vite-plugin-externalize-dependencies

MilanKovacic avatar Aug 08 '23 09:08 MilanKovacic

Another use case here: we have a custom browser-like JS runtime that provides built-in modules similar to Node's node:*. That would be great to have an option to externalize by glob, regexp, or a resolver function (similar to rollupOptions.external)

chicoxyzzy avatar Oct 31 '23 19:10 chicoxyzzy

plz notice me once the issue is resolved.

thjjames avatar Dec 05 '23 11:12 thjjames

plz notice me once the issue is resolved.

Hi @thjjames please use the Subscribe button instead of leaving a comment in the future: https://docs.github.com/en/account-and-profile/managing-subscriptions-and-notifications-on-github/viewing-and-triaging-notifications/triaging-a-single-notification#customizing-when-to-receive-future-updates-for-an-issue-or-pull-request

rdela avatar Dec 09 '23 20:12 rdela

As it took me some time to figure out a simple workaround without needing some plugin, I want to share my solution here.

As it is possible to ignore dynamic imports with /* @vite-ignore */ we can make us of this:

const moduleName = '@code/some-module';
const module = await import(/* @vite-ignore */ moduleName);
module.someExportedFunction()

Using the string directly in the import function does not work. My guess is that vite only ignores it if the import is using a variable and not a static string.

AckermannJan avatar Jan 12 '24 09:01 AckermannJan

The error Pre-transform error: Failed to load url XXX when using the workaround proposed in https://github.com/vitejs/vite/issues/6393#issuecomment-1006819717 can be fixed by adding the following method after the resolveId method:

load( id ) {
  if ( dependencies.includes( id ) ) {
    return '';
  }
}

Alternatively, you can disable pre-transformation like so:

// vite.config.js

export default {
  server: {
    preTransformRequests: false
  }
};

filipsobol avatar Mar 11 '24 15:03 filipsobol

In addition to the fix in https://github.com/vitejs/vite/issues/6582#issuecomment-1988662224, the linked code also doesn't handle base url, so here's a fix:

    // 2. push a plugin to rewrite the 'vite:import-analysis' prefix
    configResolved(resolvedConfig) {
      const VALID_ID_PREFIX = '@id/'
      const base = escapeRegExp(resolvedConfig.base ?? '/')
      const externalsString = externals.map(external => escapeRegExp(external)).join('|')
      const reg = new RegExp(
        `${base}${VALID_ID_PREFIX}(${externalsString})`,
        'g',
      )
      resolvedConfig.plugins.push({
        name: 'vite-plugin-ignore-static-import-replace-idprefix',
        transform: (code) => {
          return reg.test(code) ? code.replace(reg, (m, s1) => s1) : code
        },
      })
    },

escapeRegExp if from lodash

unshame avatar May 15 '24 13:05 unshame

FWIW, I was able to get vite to load from CDN in debug mode without any plugins by using the resolve.alias option. See

Once the proper alias is defined vite seems to load the bundles from the url specified in the alias rathe then .vite/deps.

Hope this helps someone!

juliusfriedman avatar Jun 20 '24 00:06 juliusfriedman