Open spmonahan opened 6 months ago
@miroslavstastny I'm re-assigning this to v-build as we will be shipping it
Update:
Previously I mentioned that in order to make this work, our packages need to be either
type:module
or ship.mjs
underexports#import
mapping.I explored this further and possiblity to add "just .js extensions" is also possible but has some issues which I'll expand on in 1st option description.
1. adding explicit .js
extension on build time
exports#node
mapping within our packages so no matter if we ship native ESM, if our packages are loaded in node, it will always consume commonjs outputs ATM export {Hello} from '@fluentui/hello';
) user is forced to provide import-maps, otherwise it will throw error๐๏ธ This has following gotchas:
We need to enforce that relative imports always point to existing physical file no matter what module loader is in place (node vs browser).
๐งช Example:
// @filename src/index.ts
export {Hi} from './hello'
// @filename src/hello/index.ts
export {Hi} from './hi'
โฌ๏ธ swc transpile ( + @swc/plugin-transform-imports ) โฌ๏ธ
// @filename lib/index.js
// ๐จ๐จ๐จ this is invalid path - will throw in all environements
export {Hi} from './hello.js'
// @filename src/hello/index.js
export {Hi} from './hi.js'
Rollup handles this as expected
// @filename src/index.ts
export {Hi} from './hello'
// @filename src/hello/index.ts
export {Hi} from './hi'
โฌ๏ธ rollup โฌ๏ธ
// @filename lib/index.js
// โ
โ
โ
unwraps the import path to it's source
export {Hi} from './hello/hi.js'
// @filename src/hello/index.js - wont be created
// โ
โ
โ
nested barrel files are completely removed from output as their are not necessary
What are our implementation options:
module.resolveFully
, with that adding extensions via import plugin wont work 2. declaring package as ESM native via type:module
pragma
.js
extension within imports within package scope + everything mentioned in 1) applies3. shipping all ESM files with .mjs
extension
By default in ESM native environments, if a package.json has no type
specified it fallbacks to type:commonjs
by default (our packages situation).
While we have export maps in place, they are invalid for native ESM loader ( it works solely for build tools with current output ).
In order to support native ESM loader without making the package native ESM, all files that are accessed via exports#import
need to:
.mjs
extension.js
extension within imports within package scopeNOTE: solutions need changes to webpack ( because storybook, cypress use webpack v4)
1. adding explicit .js
extension on build time
1st Approach options:
above )2. declaring package as ESM native via type:module
pragma
just-script
patch neededjest
moduleMapper hacks / '^(\\.{1,2}/.*)\\.js$': '$1',
moduleResolution": "NodeNext"
/ modifying all imports in .ts
files to include .js
extension3. shipping all ESM files with .mjs
extension
.mjs
extension and explicit .mjs
within import statementRe-opening since we had to revert this in #30803
I need it. When do you plan to fix it
@spmonahan @Hotell Any update on above issue as i am also getting same issue
SyntaxError: Unexpected token 'export' at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1728:14) at Object.<anonymous> (node_modules/@fluentui/react-provider/lib-commonjs/components/FluentProvider/renderFluentProvider.js:15:20)
Library
React Components / v9 (@fluentui/react-components)
Describe the feature that you would like added
I want Fluent's ESM output (CJS can go either way I think) to include the
.js
extension for all relative JS imports. For example,This update will better allow Fluent's ESM output to be loaded directly in the browser (import maps will still be required to resolve bare package imports but that's no problem).
Ideally we should do this without changing source code and leverage something like SWC's
@swc/plugin-transform-imports
(which transforms exports in addition to imports despite the name).Have you discussed this feature with our team
@hotell @chrisdholt
Additional context
Currently the ESM output from Fluent is "extensionless" which prevents the ESM output from working correctly in a browser.
In this example there is a "bare module" import where code is imported from a package name (that lacks a
.js
extension) and a "bare JS file" import. The latter is typically used within a package to import other JS files using relative paths.We can address "bare modules" with importmaps, allowing
import $whatever from 'some-module-without-an-extension'
to resolve correctly but importmaps cannot, effectivelyโ , handle the internal bare JS imports. To handle the bare JS imports we must update the output to include the.js
extension.โ I say effectively because it is possible to generate an importmap for all the base JS imports within a package but such an importmap would be quite large and then require end users to correctly merge it with any other importmaps they are using. Technically possible but not a good solution :)
Related issues
23508
Validations
Priority
Normal