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

How to transform output of presets? #10142

Open
mohsinulhaq opened this issue Jun 28, 2019 · 14 comments

Comments

Projects
None yet
3 participants
@mohsinulhaq
Copy link

commented Jun 28, 2019

I want to transform the core-js imports added by @babel/preset-env, but plugins always run before presets, as such I don't have access to those imports. Is there any other way to achieve this?

@babel-bot

This comment has been minimized.

Copy link
Collaborator

commented Jun 28, 2019

Hey @mohsinulhaq! We really appreciate you taking the time to report an issue. The collaborators
on this project attempt to help as many people as possible, but we're a limited number of volunteers,
so it's possible this won't be addressed swiftly.

If you need any help, or just have general Babel or JavaScript questions, we have a vibrant Slack
community
that typically always has someone willing to help. You can sign-up here
for an invite.

@nicolo-ribaudo

This comment has been minimized.

Copy link
Member

commented Jun 28, 2019

This is a bug with the core-js 3 support.

This works:

const input = `
new Map();
`;

const out = babel.transformSync(input, {
  configFile: false,
  presets: [
    [
      load("preset-env"),
      { corejs: 2, useBuiltIns: "usage", modules: false },
    ],
  ],
  plugins: [
    () => ({
      visitor: {
        ImportDeclaration(path) {
          path.node.source.value = "MODIFIED";
        },
      },
    }),
  ],
});

/* OUTPUT:
import "MODIFIED";
import "MODIFIED";
import "MODIFIED";
import "MODIFIED";
import "MODIFIED";
new Map();
*/

While this doesn't:

const input = `
new Map();
`;

const out = babel.transformSync(input, {
  configFile: false,
  presets: [
    [
      load("preset-env"),
      { corejs: 3, useBuiltIns: "usage", modules: false },
    ],
  ],
  plugins: [
    () => ({
      visitor: {
        ImportDeclaration(path) {
          path.node.source.value = "MODIFIED";
        },
      },
    }),
  ],
});

/* OUTPUT:
import "core-js/modules/es.array.iterator";
import "core-js/modules/es.map";
import "core-js/modules/es.object.to-string";
import "core-js/modules/es.string.iterator";
import "core-js/modules/web.dom-collections.iterator";
new Map();
*/

As a workaround, you can place your plugin inside a preset and visit Program:exit

@mohsinulhaq

This comment has been minimized.

Copy link
Author

commented Jun 29, 2019

Alright, thanks a lot. Will try it out and update here.

@mohsinulhaq

This comment has been minimized.

Copy link
Author

commented Jun 29, 2019

@nicolo-ribaudo I tried putting my plugin inside a preset and use Program:exit, but I still get the imports from corejs:2 but not from corejs:3

@nicolo-ribaudo

This comment has been minimized.

Copy link
Member

commented Jun 29, 2019

Did you also put your plugin inside a preset?
I know that this bug is unfortunate and hard to workaround, I will take a look at it.

@mohsinulhaq

This comment has been minimized.

Copy link
Author

commented Jun 29, 2019

Let me know if I am doing this right, I am quite new to it:

// babel.config.js
module.exports = {
  presets: [
    '@babel/typescript',
    '@babel/react',
    ['@babel/env', {loose: true, useBuiltIns: 'usage', corejs: 3}],
    './config/custom-babel-preset'
  ],
  plugins: [
    'macros',
    'react-hot-loader/babel',
    '@babel/syntax-dynamic-import',
    '@babel/transform-runtime'
  ]
};
// custom-babel-preset.js
const plugin = require('./custom-babel-plugin');

module.exports = function() {
  return {plugins: [plugin]};
};
// custom-babel-plugin.js
module.exports = function() {
  return {
    visitor: {
      Program: {
        exit(path) {
          path.traverse({
            ImportDeclaration(path) {
              console.log(path.node.source.value);
            }
          });
        }
      }
    }
  };
};
@nicolo-ribaudo

This comment has been minimized.

Copy link
Member

commented Jun 29, 2019

I have tested the workaround a bit, and the only working solution seems this:

// custom-babel-plugin.js
module.exports = function() {
  return {
      post({ path }) {
        path.traverse({
          ImportDeclaration(path) {
            console.log(path.node.source.value);
          }
        });
      }
    }
  };
};

And the custom preset should come before preset-env

@mohsinulhaq

This comment has been minimized.

Copy link
Author

commented Jun 29, 2019

I tried the above snippet, keeping the file reference, before or after is not working for me. Earlier keeping my preset before preset-env was not console logging and keeping it after did, but now I am not getting console logs in either case.

@nicolo-ribaudo

This comment has been minimized.

Copy link
Member

commented Jun 29, 2019

It will hopefully be fixed soon (#10146)

@mohsinulhaq

This comment has been minimized.

Copy link
Author

commented Jun 29, 2019

alright, thanks a lot 🙂

@mohsinulhaq

This comment has been minimized.

Copy link
Author

commented Jul 1, 2019

Hi @nicolo-ribaudo , I have one more query. Similar to having access to core-js imports, I want to have access to imports added by @babel/runtime. Here are two such exports:

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose"));

When I use a babel plugin to access the ImportDeclarations, I get only the inheritsLoose and other imports but never the _interopRequireDefault import.
Am I doing this wrong or is this expected?

@nicolo-ribaudo

This comment has been minimized.

Copy link
Member

commented Jul 1, 2019

Yes, because the transformation happens like this:

class A {}

-> Class transform

import inheritsLoose from "@babel/runtime/helpers/inheritsLoose";

function A() { ... }

-> Modules transform (part 1)

var _inheritsLoose = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose"));

function A() { ... }

-> Modules transform (part 2)

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _inheritsLoose = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose"));

function A() { ... }

_interopRequireDefault is never an ImportDeclaration, it is directly injected as a requrie call.

@mohsinulhaq

This comment has been minimized.

Copy link
Author

commented Jul 2, 2019

Ok understood. How do you suggest should I get hold of the _interopRequireDefault transform?

@nicolo-ribaudo

This comment has been minimized.

Copy link
Member

commented Jul 2, 2019

You can try visiting CallExpression and checking if the callee is require

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.