swc-project / swc

Rust-based platform for the Web
https://swc.rs
Apache License 2.0
31.15k stars 1.23k forks source link

Output mjs file extension #3067

Open stefee opened 2 years ago

stefee commented 2 years ago

Describe the feature

A configuration option to output mjs files instead of js files (when using module type es6).

Babel plugin or link to the feature description

https://babeljs.io/docs/en/babel-cli#set-file-extensions

Additional context

https://github.com/swc-project/swc/discussions/2953

https://github.com/babel/babel/pull/9144

snowyu commented 1 year ago

Why has this merged feature not been released for two years?

kdy1 commented 1 year ago

It's not merged

Tjerk-Haaye-Henricus commented 1 year ago

Will this ever be solved :D I would really need this feature.

wintercounter commented 11 months ago

When I transpile to modules, my dynamic imports will stop working in Node, because it either requires an extension to be defined, or the file must have .mjs extension. A simple import('./myModule') will fail without having an extension defined.

himself65 commented 8 months ago

Landed in https://github.com/swc-project/cli/pull/286

Should close this issue

himself65 commented 8 months ago

No, after I tried, even the output file is mjs, but the code is still like import './xxx.js'

shimarulin commented 6 months ago

In https://github.com/swc-project/swc/issues/8742#issuecomment-2040392007 I describe possible workaround. You also need to use the .mts extension of the sources to import them as .mjs.

`tsconfig.json'

⬇⬇⬇

{
  "compilerOptions": {
    "module": "NodeNext",
    "moduleResolution": "NodeNext"
    "...": "..."
  }
}
// ======
// SOURCE
// Import from './pkgs.mts'  to './ctx.mts'
// ======
import { ProjectPackages, getProjectPackages } from "~/pkgs.mjs";

export interface Ctx {
  packages: ProjectPackages | null
}

//...

⬇ swc --out-file-extension mjs ... ⬇

import { getProjectPackages } from "./pkgs.mjs";
//...
josh-i386g commented 2 months ago

@shimarulin thanks that works


  "scripts": {
    "swc-watcher": "npx swc src --out-dir dist --strip-leading-paths --watch --out-file-extension mjs",
    "swc-runner": "node --watch-path=./dist/ ./dist/index.mjs"
  }
Clashsoft commented 2 months ago

Is there an equivalent .swcrc option?

sirzeta commented 2 weeks ago

I have a problem with ESM (mjs) modules, when i use something like this:

// src/bootstrap.mjs
import 'reflect-metadata'
import {RegisterRoutes}      from './routes.mjs'
import {errorRequestHandler} from './my_module/middleware/index.mjs'
import {getContainer}        from './inversify.config.mjs'

and build it with

swc src --out-file-extension mjs --strip-leading-paths -D -d dist

I get the following:

// dist/bootstrap.mjs
import "reflect-metadata";
import { RegisterRoutes } from "./routes.mjs";
// This should be ".mts" extension, no ".js"
import { errorRequestHandler } from "./my_module/middleware/index.js"; 
import { getContainer } from "./inversify.config.mjs";

if I run this, I get the following error

Error: Directory import '/dist/my_module/middleware' is not supported resolving ES modules imported from /dist/bootstrap.mjs

my configuration is

{
  "$schema": "https://swc.rs/schema.json",
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": false,
      "decorators": true,
      "dynamicImport": true,
      "resolveFully": true
    },
    "transform": {
      "decoratorMetadata": true
    },
    "target": "es2022",
    "baseUrl": "."
  },
  "module": {
    "type": "es6",
    "noInterop": true,
    "resolveFully": true
  },
  "sourceMaps": true
}

My workaround is transform the import, but theres a catch, check for {{matches.[1]}}.mjs.

{
  "$schema": "https://swc.rs/schema.json",
  "jsc": {
    "experimental": {
      "plugins": [
        [
          "@swc/plugin-transform-imports",
          {
            "^(.*?)\\.mjs(x)?$": {
              "skipDefaultConversion": true,
              "transform": "{{matches.[1]}}.mjs "
            }
          }
        ]

There's a space at the end of .mjs. This does the job (it's still a valid import), as it ensures it doesn’t end up returning "./my_module/middleware/index.js". This makes my app happy to run but with annoying spaces.

// dist/bootstrap.mjs
import "reflect-metadata";
import { RegisterRoutes } from "./routes.mjs ";
import { errorRequestHandler } from "./my_module/middleware/index.mjs ";
import { getContainer } from "./inversify.config.mjs ";

There's a better way to doing this?.

Thanks.