Skip to content

Instantly share code, notes, and snippets.

@6ewis
Forked from ncochard/babel-webpack.md
Created May 15, 2019 06:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 6ewis/931bf29acde4f722e097ca743ed99034 to your computer and use it in GitHub Desktop.
Save 6ewis/931bf29acde4f722e097ca743ed99034 to your computer and use it in GitHub Desktop.
The correct way to compile ES6 using babel...

When you create a npm package, remember it might be used in a browser or a server, or even a command line utility… For each package you create, please pay attention at what it will be used for:

  1. Is it going to be used as a dependency to a nodejs application that is not bundled? (e.g. command line utilities)
  2. Is it going to be used as a dependency to a nodejs application that is bundled? (e.g. AWS Lambdas)
  3. Is it going to be used as a dependency to a browser application (always bundled)?.
  • In cases 2) and 3) you want to allow for tree shaking.
  • In cases 1) and 2) you want to benefit from the "ES6"/"ES next" features supported natively by nodejs.
  • In case 3) you also want to benefit from the native support of "ES6" from your browser.

Note: The examples below will assume that you do not care about people using old browsers or a version of nodejs prior to 6.10.

Dependencies of a nodejs application that is not bundled...

For a package that might be used as a dependency to a nodejs application that is not bundled...

  1. You need to compile your code to the folder ./dist.

  2. You need to define the following entry point in package.json: "main": "./dist/index.js".

  3. And you need to use the preset below.

     "presets": [
     	["babel-preset-env", {
     		"targets": {
     			"node": "6.10"
     		}
     	}]
     ]
    

Dependencies of a nodejs application that is bundled...

For a package that might be used as a dependency to a nodejs application that is bundled...

  1. You need to compile your code to the folder ./module.

  2. You need to define the following entry point in package.json: "module": "./module/index.js".

  3. And you need to use the preset below.

     "presets": [
     	["babel-preset-env", {
     		"targets": {
     			"node": "6.10"
     		},
     		"modules": false
     	}]
     ]
    

Dependencies of a browser application that is bundled...

For a package that might be used as a dependency to a browser application that would obviously be bundled...

  1. You need to compile your code to the folder ./lib.

  2. You need to define the following entry point in package.json: "browser": "./lib/index.js".

  3. And you need to use the preset below.

     "presets": [
     	["babel-preset-env", {
     		"targets": {
     			"browsers": "last 2 versions, ie 10-11"
     		},
     		"modules": false
     	}]
     ]
    

The complete .babelrc

This is an example of how the .babelrc file might look like for an npm package that might be used in any application.

{
    "env": {
        "development": {
	    "presets": [
		["babel-preset-env", {
		    "targets": {
			"node": "6.10"
		    }
		}]
	    ],
	    "plugins": [
		"transform-object-rest-spread",
		"transform-class-properties",
		...
	    ]
	},
        "browser": {
            "presets": [
                ["babel-preset-env", {
                    "targets": {
                        "browsers": "last 2 versions, ie 10-11"
                    },
                    "modules": false
                }]
            ],
	    "plugins": [
		"transform-object-rest-spread",
		"transform-class-properties",
		...
	    ]
        },
        "module": {
            "presets": [
                ["babel-preset-env", {
                    "targets": {
                        "node": "6.10"
                    },
                    "modules": false
                }]
            ],
	    "plugins": [
		"transform-object-rest-spread",
		"transform-class-properties",
		...
	    ]
        }
    },
    "sourceMaps": true
}

package.json

This is an example of how the package.json file might look like for an npm package that might be used in any application.

{
  ...
  "main": "./dist/index.js",
  "browser": "./lib/index.js",
  "module": "./module/index.js",
  "scripts": {
    ...
    "build-browser": "cross-env BABEL_ENV=browser babel ./src --out-dir ./lib --source-maps --copy-files",
    "build-module": "cross-env BABEL_ENV=module babel ./src --out-dir ./module --source-maps --copy-files",
    "build-node": "babel ./src --out-dir ./dist --source-maps --copy-files",
    "build ": "npm run build-node && npm run build-browser && npm run build-module"
  },
  ...
}

Bundling an application for the browser

Finally in the consuming application, you should configure webpack.config.js as followed. If the application runs in the browser, use the following. (Obviously this file would also need to contain configuration for CSS, etc.)

Note that webpack will assume target: 'web'. This is what tells webpack that this bundle is expected to be used in the browser. And webpack will automatically look for the entry point browser rather than main in each dependency.

const webpack = require('webpack');
...
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
    entry: {
        ...
    },
    output: {
        filename: '[name].js',
        path: ...
    },
    ...,
    module: {
        rules: [
            ...
        ]
    },
    plugins: [
        ...,
        new webpack.LoaderOptionsPlugin({
            minimize: true,
            debug: false
        }),
        new UglifyJSPlugin({
            uglifyOptions: {
                beautify: false,
                ecma: 6,
                compress: true,
                comments: false
            }
        }),
        …
    ]
};

Bundling an application for the server

If the application runs on a server, use the following. Note the property target: 'node'. This is what tells webpack that this bundle is expected to be used on the server rather than the browser. And webpack will automatically look for the entry point module rather than main in each dependency.

const webpack = require('webpack');
...
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
    target: 'node',
    entry: {
        app: …
    },
    output: {
        filename: '[name].js',
        path: ...,
        library: '???',
        libraryTarget: 'commonjs'
    },
    ...,
    plugins: [
        new webpack.LoaderOptionsPlugin({
            minimize: true,
            debug: false
        }),
        new UglifyJSPlugin({
            uglifyOptions: {
                beautify: false,
                ecma: 6,
                compress: true,
                comments: false
            }
        }),
        ...
    ]
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment