Git Product home page Git Product logo

babel-preset's Introduction

babel-preset

NPM version Downloads Build Status Coverage Status Dependency status Dev Dependency status

Babel preset to be used at MOXY.

Installation

$ npm install @moxy/babel-preset @babel/core --save-dev

If you are using Jest for testing, you also need to install babel-jest:

$ npm install babel-jest --save-dev

Motivation

Projects developed at MOXY often use new JavaScript language features that may not be supported in the targets they will run. This preset provides a shareable Babel config that:

Do I need to transpile?

There has been discussion in the community about libraries not being compiled, leaving all compilation efforts to top-level projects consuming them. This makes sense, since developers know what platforms their top-level project target and are able to compile their dependencies accordingly. Furthermore, library maintainers are constantly having to update their compilation options as new features are accepted into different stages of the specification, which creates significant and unnecessary overhead.

Problems arise, however, in libraries which target both Node.js and browser, or if non-standard JavaScript is being used, such as proposals or JSX. In those situations, library authors are required to transpile their libraries code to offer CommonJS and ES module variants or to transform non-standard JavaScript to standard JavaScript.

In conclusion:

  1. For libraries, you need to transpile if you want to publish both in CommonJS and ES or if there are non-standard JavaScript language features being used
  2. For top-level projects, you need to transpile both your code and your dependencies if the JavaScript language features being used are not supported by your targets

Usage

1. Choose a preset-type

There're two preset types available for you to use:

  • For libraries: use the lib type in case you are developing a library to be consumed by others
  • For end-projects: use the end-project type in case you developing a top-level project, such as an Web Application, a Node.js API or CLI

2. Setup babel within your project

The way Babel is configured depends on the the tooling you are using. Below, there are instructions for common scenarios:

Standard project

If you don't use a bundler within your project, this is the setup guide you should follow

  • Create .babelrc.json at the root of your project, replacing <preset-type> with the preset type you chose:

    {
        "presets": ["@moxy/babel-preset/<preset-type>"]
    }

    ...or with options:

    {
        "presets": [["@moxy/babel-preset/<preset-type>", { "react": true }]]
    }
  • Install @babel/cli as a dev dependency because we will need it for the build script:

    $ npm install @babel/cli --save-dev
    
  • Set up your package.json like this:

    "main": "lib/index.js",
    "module": "es/index.js",
    "files": [
      "lib",
      "es"
    ],
    "scripts": {
      "build:commonjs": "BABEL_ENV=commonjs babel src -d lib --delete-dir-on-start",
      "build:es": "BABEL_ENV=es babel src -d es --delete-dir-on-start",
      "build": "npm run build:commonjs && npm run build:es"
    }

    Note that the build process above will produce both CommonJS and ES builds. If you just want to produce a single build, the package.json may be simplified. For example, to produce a single CommonJS build:

    "main": "lib/index.js",
    "files": [
      "lib"
    ],
    "scripts": {
      "build": "BABEL_ENV=commonjs babel src -d lib --delete-dir-on-start"
    }
  • Tweak your .gitignore file:

    Add lib/ and/or es/ folder to the gitignore file so that those output folders are never committed.

  • Create src/index.js and happy coding!

Webpack based project

Tweak your Webpack config JavaScript rule to include babel-loader and MOXY's preset. Here's an example for a website project using React:

{
    test: /\.js$/,
    use: [
        {
            loader: require.resolve('babel-loader'),
            options: {
                cacheDirectory: true,  // Improve performance
                presets: [
                    [require.resolve('@moxy/babel-preset/end-project'), {
                        targets: ['browsers'],
                        react: true,
                        modules: false,
                    }],
                ],
            },
        },
    ],
}

It's important that you do not exclude the node_modules folder so that everything goes through the @babel/preset-env, ensuring that all the produced code was transpiled according to the targets.

3. Tweak the options

Below, you may find a list containing all options you may tweak:

Name Description Type Default in lib in end-project
react Adds support for React boolean false
lodash Transform to cherry-pick Lodash modules boolean/Object true
modules Transform ES6 module syntax to another module type string/boolean Based on process.env.BABEL_ENV, commonjs if unspecified
dynamicImport Adds support for import() statements boolean true
loose Enable "loose" transformations for any plugins that allow them boolean true
targets The output targets, see bellow for a more detailed explanation Array/Object ['browsers', 'node']
env The environment (development, production or test) string Based on process.env.NODE_ENV
namedDefaultExport Use add-module-exports plugin to get around babel/babel#2212 boolean true if modules is commonjs

lodash option

Specify which modules will have the cherry-pick transformation applied.

Note that lodash-es, lodash-compat and lodash/fp are always added for you, regardless of having this option defined or not.

For instance, to have smaller bundles when using recompose:

{
    "presets": [
        ["@moxy/babel-preset/<preset-type>", {
            "lodash": { "id": ["recompose"] }
        }],
    ],
}

targets option

The targets option has a very important role. By default, its value is ['browsers', 'node'] which means that the compiled code will work in both the Browser and in Node.js.

When browsers is specified, the compiled code will work on browsers that are supported by Google's browser support policy (modern). When node is specified, the compiled code will work on the last LTS or higher (currently v8.9).

If your project has different requirements in terms of browser or node support, you may specify the targets yourself as an object.

dynamicImport option

Dynamic imports support are enabled by default but are dependent on the modules option. More specifically, the syntax-dynamic-import and dynamic-import-node when the modules option is set to false and commonjs respectively.

For other modules types, such as amd, you must find and include a plugin yourself. Also, you may disable the dynamicImport option by setting it to false in case you want to disable the feature completely or if you want to choose another plugin.

env option

The env's default value respects process.env.NODE_ENV and falls back to production if none are set. When env is production, some plugins that perform code optimization will be enabled.

The modules default value is commonjs unless process.env.BABEL_ENV is set to es.

4. Be aware of the caveats

No, seriously. Read the Caveats section as it contains crucial information and might require you to do a few more steps.

Caveats

Polyfills

In libraries

Shipping polyfills in libraries is, in general, a bad practice because it increases the overall file size of your top-level project due to duplication.

The transform-runtime plugin attempts to solve the polyfills and duplication by transforming Object.assign, Promise and other features to their core-js counter-parts. Though, this doesn't play well with preset-env because it inlines everything, including features that are already supported by our targets. Additionally, if different versions of the runtime are installed, duplication still happens.

For this reason, you, as an author, should state in the README of your library that you expect the environment to be polyfilled with core-js, babel-polyfill, polyfill.io or similar.

In top-level projects

Simply include import 'babel-polyfill'; at the top of your entry file. That statement will be replaced with the necessary polyfills based on the targets you want to support.

// in:
import 'babel-polyfill';

// out:
import 'core-js/modules/es6.object.assign';
import 'core-js/modules/es6.promise';
// ...

Dynamic imports

The support for dynamic imports is enabled by default, please read more on the dynamicImport option.

The caveat is that preset-env is unaware that using import() with Webpack relies on Promise internally. Environments which do not have builtin support for Promise, like Internet Explorer, will require both the promise and iterator polyfills be added manually. Having said that, tweak your top-level project's Webpack config like so:

{
    entry: [
        'core-js/modules/es6.promise',
        'core-js/modules/es6.array.iterator',
        // Path to your entry file
    ],
};

Minifying

You must use a minifier that understands ES6+ syntax because the transpiled code might contain ES6+ code. As an example, UglifyJS v2 only understands ES5 syntax but UglifyJS v3 does support ES6+.

Tests

$ npm test
$ npm test -- --watch # during development

License

MIT License

babel-preset's People

Contributors

afonsovreis avatar andrefgneves avatar andregoncalvesdev avatar areadrill avatar dominguesgm avatar greenkeeper[bot] avatar paulobmarcos avatar rafaelramalho19 avatar satazor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

isabella232

babel-preset's Issues

An in-range update of eslint-config-moxy is breaking the build 🚨

The devDependency eslint-config-moxy was updated from 6.0.1 to 6.1.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

eslint-config-moxy is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • continuous-integration/travis-ci/push: The Travis CI build could not complete due to an error (Details).

Commits

The new version differs by 3 commits.

  • 853af8e chore(release): 6.1.0
  • 9859072 feat: use built-in prefer-object-spread
  • c7a5c84 chore: remove file name convention

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of babel-plugin-add-module-exports is breaking the build 🚨

Version 0.3.3 of babel-plugin-add-module-exports was just published.

Branch Build failing 🚨
Dependency babel-plugin-add-module-exports
Current Version 0.3.2
Type dependency

This version is covered by your current version range and after updating it in your project the build failed.

babel-plugin-add-module-exports is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.

Status Details
  • continuous-integration/travis-ci/push: The Travis CI build failed (Details).

Release Notes v0.3.3

Bug Fixes

Commits

The new version differs by 5 commits.

  • d76d035 chore: tweaks CI/deploy enviroiment
  • ab74696 0.3.3
  • db82c3f fix: closes #60, #63
  • 8e83ff9 test: Add issues #60, #63 reproducing test
  • c37b6f1 docs: add See also section [ci skip]

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Discuss including babel-plugin-add-module-exports

With our preset, we usually produce two builds:

es/ - Contains ES modules and usually used by bundlers like webpack (enables treeshacking)
lib/ - Contains CommonJS modules and usually used in Node.js

The issue is that, when on Node, we have to require modules like this:

const myModule = require('my-module').default

This is kind of bad, see babel/babel#2212 for more info.
To get around it, there's babel-plugin-add-module-exports that solves this.

Though, this can't be used in isomorphic applications, like react-with-moxy, because the same code must work on the server and on the client:

{
    // Will work on the client but not on the server
    // On the server, it would just be `require('./About')`
    component: require('./About').default,
}

We can choose between:

  • Add the add-module-exports when options.modules is commonjs and add an option to not include this plugin so that we can disable it in isomorphic applications
  • Keep it like this, which means that projects like proper-url-join must activate the plugin manually

I fear that 99% of the cases we want add-module-exports. What do you think?

An in-range update of babel-plugin-transform-react-remove-prop-types is breaking the build 🚨

The dependency babel-plugin-transform-react-remove-prop-types was updated from 0.4.20 to 0.4.21.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

babel-plugin-transform-react-remove-prop-types is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.

Status Details
  • continuous-integration/travis-ci/push: The Travis CI build could not complete due to an error (Details).

Release Notes for v0.4.21
  • Add support for defining additionalLibraries as a regexp expression (#174) @pkuczynski
FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Consider making loose false by default

There's a few moments where loose is causes problems, but when it does we waste a lot of time to understand the issue.

Let's discuss if the default should be changed to false.

Use transform runtime for the regenerator when babel 7 launches

Ideally, any library that uses async await should be used without having to setup regenerator-runtime at the application level.

Using useBuiltIns in babel-preset-env helps with this task because it automatically includes regenerator-runtime when replacing import 'babel-polyfill'. Though, when the targets specified in babel-preset-env do not require transforming async await, the regenerator-runtime is not included. This is mostly fine, except if you are targeting latest node, which already has support for async await, and you are using a dependency that was compiled targeting an environment that doesn't support async await, causes a regeneratorRuntime is not defined error.

To solve this, we need to compile libraries by using regenerator-runtime as a module instead of relying it to be installed globally. To do this, we can use transform-runtime with only regenerator: true active.

We can't do this in babel@6 because different versions of the regenerator-runtime will be included. More specifically, we must use babel-preset-env@1 which is the only release line compatible with babel@6 which uses an older version of regenerator-runtime. This causes the regenerator-runtime code to be duplicated, which is problematic for client-side builds (~20kb unminifed, 4kb minified and gzipped)

When babel@7 launches, we can use the transform-runtime strategy outlined above because the regenerator-runtime versions will not longer mismatch.

Add eslint-plugin-lodash

This would reduce the build sizes if we import lodash like this:

import { pick } from 'lodash';

At the moment we must use:

import pick from 'lodash/pick';

to be sure that our bundle does not contain the whole lodash.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.