webpack: Dynamic imports don't work when `exports` specified in package.json and aliases

Bug report

What is the current behavior?


The same problem in require.context and import.meta.webpackContext, so need to be fixed too

For example, highlight.js has the following in exports of package.json:

{
	"exports": {
		"./lib/languages/*": {
			"require": "./lib/languages/*.js",
			"import": "./es/languages/*.js"
		}
	}
}

I tried to import a language dynamically using the following code in a Vue 3 / TS 4 app:

const langName = ref('')
const message = ref('')
const module = await import(
  `highlight.js/lib/languages/${langName.value}`
)
message.value = module.default.name

This leads to the following error:

 error  in ./src/App.vue?vue&type=script&lang=ts

Module not found: Error: Package path ./lib/languages is not exported from package <path_to_proj>/node_modules/highlight.js (see exports field in <path_to_proj>/node_modules/highlight.js/package.json)

If the current behavior is a bug, please provide the steps to reproduce.

  1. Clone minimum reproduction repo and npm install.
  2. Run the project with npm run serve.
  3. See error.

What is the expected behavior?

Replacing ${langName.value} with a literal value works and imports the file as expected:

const langName = ref('')
const message = ref('')
const module = await import(
  `highlight.js/lib/languages/javascript`
)
message.value = module.default.name

Dynamic import should work equally well.

Workarounds

The comment https://github.com/highlightjs/highlight.js/issues/3223#issuecomment-886143417 contains possible workarounds, if that helps to narrow the problem.

Other relevant information: webpack version: 5 Node.js version: 14 Operating System: mac OS Additional tools: TypeScript 4, Vue 3, Babel 7

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 23
  • Comments: 21 (7 by maintainers)

Commits related to this issue

Most upvoted comments

So how are people dealing with this in real life other than begging package maintainers to stop using imports?

It would be nice to have a workaround to suggest to our users, particular if this is not going to be fixed anytime soon.

I got a temporary hack for this issue. import file normaly from package in a file then do dynamic import of that file.

src/components/externalForm/fwkComponentOnticFormRenderer.tsx

import { OnticFormRenderer } from "fwk-components";  // our internal package. which I was not able to dynamic import directly
export default OnticFormRenderer;
const OnticFormRenderer = dynamic(
    // https://github.com/webpack/webpack/issues/13865
  () => import('./fwkComponentOnticFormRenderer'),
  {
    ssr: false,
  }
);

So how are people dealing with this in real life other than begging package maintainers to stop using imports?

It would be nice to have a workaround to suggest to our users, particular if this is not going to be fixed anytime soon.

To overcome this in an Angular app, I’ve used a relative path to the loaded module, for example:

import(`@angular/common/locales/${this.userLanguageCode}.js`)

became

import(`../../../../node_modules/@angular/common/locales/${this.userLanguageCode}.mjs`)

(ignore path differences, it should not matter)

App builds and successfully loads the languages again

@dominicarrojado the Next.js error you mention is the same that I faced.

So how are people dealing with this in real life other than begging package maintainers to stop using imports?

It would be nice to have a workaround to suggest to our users, particular if this is not going to be fixed anytime soon.

While suboptimal, we switched to an expression.

From:

import(
/* webpackInclude: /(en|nl|tk|de)\.js$/ */
  `/@angular/common/locales/${language}.js`
)

To:

const moduleName = `/@angular/common/locales/${language}.js`;
import(
  /* webpackInclude: /(en|nl|tk|de)\.js$/ */
  moduleName
)

This does yield a warning:

Warning: Critical dependency: the request of a dependency is an expression

But it seems to work in our case for now.


Edit:

Scrap all of that, as @Hypnosphi correctly identified, it does not work on-demand, it seemed to work at first but seemingly our translations are loaded from a different source.