Skip to content

can't use any programmatic babel options #110

Closed
@justinhelmer

Description

@justinhelmer

The problem

Currently, this tool supports supplying a custom .babelrc file location via Jest global configuration (jest.globals['vue-jest'].babelRcFile), which is great.

However, .babelrc is not an option for us. Due to the fact that it is JSON, we cannot have any logic in the babel configuration. I tried using .babelrc.js, which babel supports, but the config loader assumes JSON and parses the file.

Additionally, we have moved to the new project-wide configuration file (babel.config.js) which is recommended by babel for our use-case, and exports a function instead of an object.

The solution

expand the global jest configuration for vue-jest to support arbitrary babel options:

{
  "jest": {
    "globals": {
      "vue-jest": {
        "babelOptions": {
          "presets": [
            [
              "env",
              {
                "useBuiltIns": "entry",
                "shippedProposals": true
              }
            ]
          ],
          "plugins": [
            "syntax-dynamic-import"
          ],
          "env": {
            "test": {
              "plugins": [
                "dynamic-import-node"
              ]
            }
          }
        }
      }
    }
  }
}

This generic solution opens up many more possibilities for how the tool can be used. For example, if the --config option is used with Jest, we are no longer restricted to JSON. This allows for the configuration to have logic:

// @file jest.config.js
const path = require('path');
const config = require('./config');

const envPreset = [
  '@babel/preset-env',
];

if (config.foo) {
  envPreset.push({
    useBuiltIns: 'entry',
    shippedProposals: true,
  });
}

module.exports = {
  globals: {
    'vue-jest': {
      babelOptions: {
        presets: [envPreset],
        plugins: ['babel-plugin-*'],
      }
    }
  }
}

It can also be used to support the configFile option to use a project-wide configuration file (babel.config.js), e.g.:

// @file jest.config.js
module.exports = {
  globals: {
    'vue-jest': {
      babelOptions: {
        configFile: path.resolve(__dirname, './babel.config.js'),
      }
    }
  }
};

This configuration file exports a function that can use the config function API and returns babel options:

// @file babel.config.js
module.exports = (api) => {
  api.cache(() => process.env.NODE_ENV === 'production');
  return {
    presets,
    plugins
  };
};

This is especially powerful when used in conjunction with webpack, which can supply the same configuration to it's babel-loader to ensure functional parity when building the application.

This solution also allows for consumers to take advantage of the new configuration file resolution logic built-in to babel by using the root option:

// @file jest.config.js
module.exports = {
  globals: {
    'vue-jest': {
      babelOptions: {
        root: path.resolve(__dirname),
      }
    }
  }
};

Although I have not explored this option, it could provide an alternative approach to circumvent the current logic provided by third-party find-babel-contrib, which is not owned/maintained by the babel core team. I also found an open PR (#93) which indicates there are needs to make it better, or closer to the native behavior of babel.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions