Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using externalHelpers causes webpack errors 'import' and 'export' may appear only with 'sourceType: module' #6728

Closed
meskill opened this issue Dec 29, 2022 · 8 comments
Labels

Comments

@meskill
Copy link
Contributor

meskill commented Dec 29, 2022

Describe the bug

In my config swc is currently set up to output esm modules in order to let the webpack handle all the stuff with modules. And it mostly works well, but for some packages in node_modules I'm getting the next error:

error GLOBAL:ERROR Module parse failed: 'import' and 'export' may appear only with 'sourceType: module' (2:0)
File was processed with these loaders:
 * ../../node_modules/swc-loader/src/index.js
You may need an additional loader to handle the result of these loaders.
| "use strict";
import _type_of from "@swc/helpers/src/_type_of.mjs";
| exports.__esModule = true;
| exports.calcFontColor = calcFontColor;
Error: Module parse failed: 'import' and 'export' may appear only with 'sourceType: module' (2:0)
File was processed with these loaders:
 * ../../node_modules/swc-loader/src/index.js
You may need an additional loader to handle the result of these loaders.
| "use strict";
import _type_of from "@swc/helpers/src/_type_of.mjs";
| exports.__esModule = true;
| exports.calcFontColor = calcFontColor;
    at /workspaces/Tinkoff/tramvai/packages/cli/lib/builder/webpack/utils/runWebpack.js:10:13
    at finalCallback (/workspaces/Tinkoff/tramvai/node_modules/webpack/lib/Compiler.js:441:32)
    at /workspaces/Tinkoff/tramvai/node_modules/webpack/lib/Compiler.js:458:13
    at Hook.eval [as callAsync] (eval at create (/workspaces/Tinkoff/tramvai/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous\>:33:1)
    at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (/workspaces/Tinkoff/tramvai/node_modules/tapable/lib/Hook.js:18:14)
    at onCompiled (/workspaces/Tinkoff/tramvai/node_modules/webpack/lib/Compiler.js:456:21)
    at /workspaces/Tinkoff/tramvai/node_modules/webpack/lib/Compiler.js:1196:17
    at Hook.eval [as callAsync] (eval at create (/workspaces/Tinkoff/tramvai/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous\>:6:1)
    at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (/workspaces/Tinkoff/tramvai/node_modules/tapable/lib/Hook.js:18:14)
    at /workspaces/Tinkoff/tramvai/node_modules/webpack/lib/Compiler.js:1192:33

There is no such issue for babel though.

I've made some digging to trace the error cause:

  • swc inserts esm imports for helpers anyway - code that later are compiled to commonjs if module is set to commonjs in swc config. And as I'm configured swc to output esm they are not converted to commonjs inside commonjs module
  • the issue surprisingly doesn't affect most of modules. This is because webpack in most cases parses type of file as javascript/auto to provide smart parsing that will dynamically figure out is it esm or commonjs. But some of the packages are explicitly marked with type: "commonjs" in their package.json and it get parsed in webpack more strictly leading to the error above
  • babel outputs the import depending on the package itself so there is no issue when using babel-loader

Input code

const fs = require("fs");

exports.test = async () => {};

Config

{
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": false
    },
    "externalHelpers": true,
    "target": "es5",
    "loose": false,
    "minify": {
      "compress": false,
      "mangle": false
    }
  },
  "module": {
    "type": "es6"
  },
  "minify": false,
  "isModule": true
}

Playground link

https://play.swc.rs/?version=1.3.24&code=H4sIAAAAAAAAA0vOzysuUUgrVrBVKEotLM0sStVQSitW0rTm5eLlSq0oyC8qKdYrSQWqsVVILK7MS1bQ0FSwtVOorrUGALdsYEI7AAAA&config=H4sIAAAAAAAAA0WOSwrDMAxE76K1t%2B3CJ%2BimhxCuElz8Q1IgxvjutYNLdmI0b2YafMWBbVCQhXheUpPiCRa0FhLHvigYUBnShkGoG6BTiROGF4VCLGCVDxoe5J10kCSPgYSchRZkIPrktzoLXI6FSeR%2BYdrD39lHfsyfYwrt2nAFPqHfGYvz8l7G2d9%2Fo%2FC0EMwAAAA%3D

Expected behavior

Generate imports for helpers as it is implemented in babel - based on the sourceType of the module itself, not only bare config

Actual behavior

Generated imports for helpers are always in esm

Version

1.3.24

Additional context

The issue might be related

@kdy1
Copy link
Member

kdy1 commented Jan 19, 2023

Closing as this is not a bug of swc

@kdy1 kdy1 closed this as not planned Won't fix, can't repro, duplicate, stale Jan 19, 2023
@meskill
Copy link
Contributor Author

meskill commented Jan 19, 2023

the issue surprisingly doesn't affect most of module

Little update on this - it actually affects all of those modules, but instead of errors during build it will lead to runtime errors. Because webpack in this case will consider that modules as esm and will ignore any exports.= in the code and will output modules that exports nothing.

Closing as this is not a bug of swc

I agree that swc did what it told to do i.e. to generate esm code. The issue comes more from the different module ecosystems that should work together. But it makes swc actually unusable to generate optimized bundles as we can't change all the npm packages at once to make it work properly for esm build. I see that babel chose to be more flexible in that case to support real projects as it may affect any project that uses different npm packages.

@kdy1
Copy link
Member

kdy1 commented Jan 19, 2023

Why do you transpile packages in node_modules at first?
It's very likely that you are simply doing something wrong

@JSerFeng
Copy link
Contributor

JSerFeng commented Jan 19, 2023

Why do you transpile packages in node_modules at first?

It's very common that some packages use ES6 or higher version syntax in their output, it makes sense to me.

@meskill
Copy link
Contributor Author

meskill commented Jan 19, 2023

It's not a bug anyway IMO, but it's fixed in recent versions

If it's not a bug why is that fixed then? Or is it a bug that it is fixed and that behavior might be rolled back again in the future?

I see that you pointed to the playground, but the link actually uses isModule: false in the config, that is not quite the same as the original issue. Although, I see that with the latest version 1.3.27 the option isModule: 'unknown' is now working and provides imports depending on module system (it doesn't work for 1.3.24 that I've originally tested).

@JSerFeng
Copy link
Contributor

JSerFeng commented Jan 19, 2023

Thats not a bug. you can see the pr fix the polyfill in script not your issue.

You set isModule true manually, so I think its right for swc to inject import

You can set isModule unknown, let swc decide it is script or module

@swc-bot
Copy link
Collaborator

swc-bot commented Feb 19, 2023

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@swc-project swc-project locked as resolved and limited conversation to collaborators Feb 19, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Development

No branches or pull requests

4 participants