vitejs / vite

Next generation frontend tooling. It's fast!
http://vitejs.dev
MIT License
66.34k stars 5.93k forks source link

Support external in dev #6582

Open hasangenc0 opened 2 years ago

hasangenc0 commented 2 years ago

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

bluwy commented 2 years ago

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.

hasangenc0 commented 2 years ago

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

bluwy commented 2 years ago

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 commented 2 years ago

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

terwer commented 1 year ago

Any updates?

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

bluwy commented 1 year ago

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.

patak-dev commented 1 year ago

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).

Djfaucette commented 1 year ago

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 commented 1 year ago

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.

bluwy commented 1 year ago

@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.

AxeloLabs commented 1 year ago

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

MilanKovacic commented 11 months ago

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

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

chicoxyzzy commented 8 months ago

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)

thjjames commented 7 months ago

plz notice me once the issue is resolved.

rdela commented 7 months ago

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

AckermannJan commented 6 months ago

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.

filipsobol commented 4 months ago

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
  }
};
unshame commented 2 months ago

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

juliusfriedman commented 1 month ago

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!