Skip to content

[Bug]: Cannot import @microsoft/teams.client into webpack 5 javascript react project: Module has no exports.#566

Merged
corinagum merged 2 commits into
microsoft:mainfrom
Jesperholmbergmsft:jh/bug542
May 8, 2026
Merged

[Bug]: Cannot import @microsoft/teams.client into webpack 5 javascript react project: Module has no exports.#566
corinagum merged 2 commits into
microsoft:mainfrom
Jesperholmbergmsft:jh/bug542

Conversation

@Jesperholmbergmsft
Copy link
Copy Markdown
Contributor

@Jesperholmbergmsft Jesperholmbergmsft commented May 8, 2026

This PR addresses bug 542. by adding an onSuccess handler to the tsup.config.js to rewrite .mjs import paths to be compliant with the ESM specification.

Webpack 5 strictly requires that ESM code follows specification and includes a file extension on import paths. Other bundlers - Webpack 4, RSPack, Vite/Rollup - are more forgiving, but benefit from code following specification.

Tsup that we're using in these libraries doesn't automatically produce compliant import statements, but we can take care of that with an onSuccess handler to call a script and update the import paths. This was already done for the graph-endpoints package that doesn't use tsup at all, and makes sense to do for the tsupped code also.

Before the change in this PR, a React app using these libraries and relying on Webpack 5 would fail during build with e.g.:

building with released bits, webpack 5:
WARNING in ./src/Tab/App.tsx 35:28-41
export 'ConsoleLogger' (imported as 'ConsoleLogger') was not found in '@microsoft/teams.common' (module has no exports)
 @ ./src/Tab/client.tsx 4:0-24 5:85-88

ERROR in ./node_modules/@microsoft/teams.client/dist/index.mjs 1:0-28
Module not found: Error: Can't resolve './app' in 'C:\git\TeamsApps\webpack5app\node_modules\@microsoft\teams.client\dist'
Did you mean 'app.js'?
BREAKING CHANGE: The request './app' failed to resolve only because it was resolved as fully specified
(probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.
 @ ./src/Tab/App.tsx 4:0-64 34:35-49
 @ ./src/Tab/client.tsx 4:0-24 5:85-88

Before the change, after building these libraries, import paths in .e.g packages/common/dist/index.mjs would look like:

export * from './events';
export * from './http';
export * from './logging';
export * from './storage';

After, they're correctly

export * from './events/index.mjs';
export * from './http/index.mjs';
export * from './logging/index.mjs';
export * from './storage/index.mjs';

Similarly, before the change, packages/common/dist/http/client.mjs contained:

import { ConsoleLogger } from '../logging';

And now it's correctly:

import { ConsoleLogger } from '../logging/index.mjs';

How tested:

  • Built from the project root as well as within an individual package and verified that the import paths are correctly rewritten in the dist folder.
  • Built on both Mac and WIndows and looked at the dist folder.
  • Set up a simple Teamss tab app using these libraries to use teams-js context / msal / graph.
  • Before the change: verified that I can build the app with vite/rollup, rspack, and webpack 4; but webpack 5 fails as above
  • After the change, verified that I can build using all four and that the app still runs
  • After the change, also verified that the app tree-shakes properly on all four. Vite gives best results; webpack 4 the worst, but they all do their level best

@Jesperholmbergmsft Jesperholmbergmsft marked this pull request as ready for review May 8, 2026 14:55
Copilot AI review requested due to automatic review settings May 8, 2026 14:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes Webpack 5 “fully specified ESM” build failures for the published packages by rewriting extension-less relative imports/exports in generated .mjs files to include .mjs (or /index.mjs) after tsup finishes.

Changes:

  • Add a tsup onSuccess hook to post-process dist/**/*.mjs output.
  • Introduce a Node script that walks dist and rewrites relative ESM specifiers to be fully specified.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
packages/config/tsup.config.js Runs a post-build step to rewrite .mjs import/export specifiers under dist.
packages/config/rewrite-esm-imports.js Implements filesystem-based rewriting of relative ESM specifiers to include .mjs/index.mjs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/config/tsup.config.js Outdated
Comment thread packages/config/tsup.config.js Outdated
Copy link
Copy Markdown
Collaborator

@corinagum corinagum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pulled and ran to test out; confirm that these changes the same bug on main builds cleanly here. .mjs files went down to 0 extensionless relative imports. This was on mac.

LGTM! Thanks so much @Jesperholmbergmsft!

@corinagum corinagum merged commit 0effb7e into microsoft:main May 8, 2026
3 checks passed
corinagum added a commit that referenced this pull request May 27, 2026
## Summary

Brings `origin/main` into `release` for the **2.0.12** release. **No
carve-outs this time** — Quoted Replies is included.

`version.json`: `2.0.12-preview.{height}` → `2.0.12`.

Aligns with teams.py 2.0.12 (PR #442 already on PyPI / pending publish).

## What's in this release (delta from 2.0.11)

**Features**
- Quoted Replies + new quotes features — previously held back via the
2.0.11 carve-out (#576)
- SuggestedActionSubmitActivity for `suggestedAction/submit` invoke
(#591)
- Default targeted replies for targeted inbound messages (#592)
- Filter colliding keys before `Object.assign` in `ActivityContext`
(#596)
- Prompt Preview support (#536)
- A2A sample (#584)
- AI/MCPClient (#572)
- Allow passing custom HTTP client via `AppOptions`-equivalent
- Reactions API marked GA (#575), Rename `ReactionClient.remove()` →
`delete()` (#567)

**Security & fixes**
- Security hardening: tighten cross-origin policies (#595)
- Lock JsonWebToken trust-boundary contract (#586)
- `fix(deps)`: npm audit fix — clears all high-severity advisories
(#599)
- `fix(apps)`: log inbound activities at info, warn on missing
Authorization (#568)
- `fix`: App user-agent merging (#573)
- `fix`: Add null checks in `local-memory.ts` to prevent role crash
(#438)
- `fix`: `@microsoft/teams.client` import error in webpack 5 (#566)
- Switch to named imports without subpaths (#561)

**Deprecations / package changes**
- Deprecate `DevtoolsPlugin` in favor of Microsoft 365 Agents Playground
(#593)
- Remove in-repo Teams CLI package (#580) — moved to
`teams-sdk/packages/cli`
- Deprecate AI Libraries (#588)
- Correct imports + return types in misc. packages (#589)

**Dependency bumps**
- turbo 2.8.11 → 2.9.14 (#587)
- qs 6.15.0 → 6.15.2 (#594)
- hono 4.12.14 → 4.12.16 (#562)
- npm audit fix bundle (#599): axios 1.13.5 → 1.16.1, fast-uri 3.1.0 →
3.1.2, ws 8.19.0 → 8.21.0, @azure/msal-node hoisted 5.2.2, uuid 11.1.0 →
11.1.1, @azure/identity 4.13.0 → 4.13.1, express-rate-limit, ip-address,
brace-expansion, etc.

## Quoted Replies inclusion notes

- Teams client rendering is in-sync with the wire format as of
2026-05-06.
- APX QR rollout completed: Public 2026-04-10, GCCH/DoD/Gallatin
2026-04-14.
- No SDK-side carve-outs needed; this matches the teams.py 2.0.12 (PR
#442) decision.

## Branch structure note

`prep-release/2.0.12` is reset to `origin/main` + a one-line
`version.json` bump. Diff against `release` (this PR) shows the full
delta from 2.0.11. We deliberately did not use a 2-parent merge commit —
the auto-merge tried to interleave non-overlapping hunks from main's QR
additions with release's QR carve-outs in `activity.ts`, producing a
semantically broken file. Reset-to-main + version bump is the clean way
to express "release should equal main."

## Test plan

- [x] `npm install` clean (post-audit-fix lockfile)
- [x] `npm run build` — 33/33 targets clean
- [x] `npm test` — 14/14 task targets, 279+ tests pass
- [x] E2E echo bot smoke test against `cg-test-bot-py` via canary ABS —
done on `cg/audit-deps-ts` (now merged); covers axios + msal-node code
paths
- [ ] Pipeline Build + Test stages green on `release` after merge
- [ ] Publish pipeline run with **Public** → ESRP → npm
`@microsoft/teams.*@2.0.12`
- [ ] Smoke install: `npm view @microsoft/teams.apps@2.0.12` after
publish
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

Successfully merging this pull request may close these issues.

3 participants