Starting new (React+Webpack) project from scratch = beginning =(to)=> advanced
I recently had a new challenge, my team and I were facing some issues using Webpack 2, it was taking a lot of time compiling the project in development and building the production bundle, we have to migrate Webpack 2 to 4 for two years old app.
Thanks to that upgrade, we had to learn more and deep concepts about the new Webpack 4, and then I realized that this is actually a good opportunity to write step by step to help others to understand better how Webpack works, performs, and how to start a project from scratch for a scalable application.
What do you need?
You need a least to have some experience with npm and React works if you are starting to learn about Webpack and React you might get overwhelmed.
To follow this tutorial you just need.
- VSCode (Editor)
- node.js
- Git (I’m using GitHub to track every single step) you can also get a copy of the source code.
Creating a new project – fresh start:_
Open your terminal and create a new folder project whenever you like.
$ mkdir webpack-demo $ cd webpack-demo $ npm init
The first thing that we need to do is install Webpack and Webpack-cli
npm install -D webpack webpack-cli --save
Open package.json
and add the start command
"start": "webpack --config webpack.config.js"
Create the Webpack config file $ touch webpack.config.js
After that, we need to add at least one javascript file to make Webpack work
mkdir src touch src/index.js echo "console.log('Hello world')" >> src/index.js
Run npm run start
and if everything is fine so far you will see the following screen.
As you can see above, in Webpack ≥ 4.x, we need to either set the mode to production or development. It sets to production by default.
Webpack team is working hard to make Webpack easy to use and they introduced in version 4 zero-configuration, which means we don’t need to add webpack.config.js
but at the difference of Parcel we will need to add our Loaders to be able to handle and load all assets likejpg, png, svg, fonts, html
and more, this is the main reason why some people prefer Parcel but sometimes we don’t need to add all loaders to our project.
Notice after running npm run start, a new file was added in the dist directory
Advance Webpack configuration
To make Webpack run better, we’re going to add more custom configurations to our webpack.config.js.
First of all, we need to know the structure of our webpack.config.js
this is how it’s looks like:
module.exports = env => { const config = { mode: "", //String entry: {}, //Object output: {}, module: { rules: [] }, resolve: {}, plugins: [], //Array optimization: { splitChunks:{} minimizer: [] }, devServer: {}, devTools: "" }; return config; };
Be aware Webpack is not only limited to the above structure. Our goal is to go through each property, understand it, and set it up.
Mode
This is a new option included in Webpack 4, now is very straightforward to tell Webpack in what mode it needs to perform, by default this option has been settled up production mode, and when production is enabled the optimization plugins will be enabled as well it means we don’t need to enable or disable manually like we used to do in previous versions. The mode expects a string parameter and it can be settled as production
, development
, and others
.
We can set the operational mode through the CLI in our package.json
using the flag, --mode="(development) or (production)"
or using the env
variable. In this demo, we are going to use environmental variables to handle it through the CLI.
module.exports = env => { const config = { mode: env.NODE_ENV === "development" ? "development" : "production" }; return config; }; //note if env.NODE_ENV.development is defined on the CLI set mode as Development if not set it as Production
Now we can pass variables through the CLI like this.
"scripts": { "start": "webpack --config webpack.config.js --env.NODE_ENV=development", "build": "webpack --config webpack.config.js --env.NODE_ENV=production" },
npm run start // will be used for development mode npm run bluid // will be used for production mode
Using this approach you will be able to use the production or development
modes to enable or disabled options in the webpack.config.js
configurations depending on your environment without duplicating the code and using several files one for production
and another for development.
Make npm run start
and you will see the warning is gone.
Entry Point
We need to tell Webpack which file or files to use to start building the project, also we can separate our bundle into App and Vendors.
App
: it’s going to take all the custom code and then make a bundle.
Vendors
: it’s going to take all dependencies and will make vendors bundle.
First of all, we need to include path
to our webpack.config.js
to locate files in our project, also you don’t need to install path
because it included in Node.js
https://gist.github.com/victors1681/9f2f6ef2374bed0014c3b8964c40867d
Please notice that I used the key app inside the entry object, we can use any name like main
mainApp
, after run npm run start
Webpack will generate a new bundle called app.js
and we will use it later in our HTML file.
At this point, we have our first bundle, now is the time to add ReactJS to our project, and will generate a bundle separated one for our App and another for our Vendors.
npm install react react-dom --save
Then add it to our entry point those dependencies
entry: { app: [path.resolve(__dirname, "./src/index.js")], vendors: ["react", "react-dom"] }
$ npm run build
const path = require("path"); module.exports = env => { const config = { mode: env.NODE_ENV === "development" ? "development" : "production", entry: { app: [path.resolve(__dirname, "./src/index.js")] } }; return config; };
Output
Using output we can tell Webpack where we want to put our bundle instead to use the default path and directory /dist
, and also we are able to use the hash sum to our bundle file to improve the cache.
For instance, we have app.js
we are planning to include this bundle in our index.html
and the browser will cache that file app.js
depending on the browser we might have some issues if we redeploy our application with new changes, perhaps the browser will load an old version of our file, to avoid that is a good idea to use hash sum likeapp.23434c.js
even if we make small changes to our app the browser will handle the new version properly.
We are going to add some configuration to our output object.
output: { path: path.join(__dirname, ".", "myDistribution", "ui"), filename: "js/[name]".concat(".[chunkhash:8].js") }
$ npm run build
Because we changed the default directory you will be able to see those files in myDistribution/ui/js
and now the hash sum is appended to app and vendors.
https://github.com/victors1681/webpack-demo/commit/1c0cc7a99d5f0f18215b3448a5b96b57c7c121e5
Resolve
Tell Webpack how to locate our files, for a small project it doesn’t matter but for the biggest one will be very helpful, also this feature allows us to add an alias to use it as a shortcut for our modules.
resolve: { alias: { view: path.resolve(__dirname, "./src/View"), container: path.resolve(__dirname, "./src/Container") }, extensions: [".js"], modules: [ path.resolve(__dirname, "./src"), path.resolve(__dirname, "./node_modules") ] }
At this moment we don’t have any View
andContainer
the directory inside of our src
folder, but using the alias we will be able to reach those folders from anywhere.
Please take a look at the following folder structure.
|-src |--View |--|--Header |--|--|--TestingComponent |--|--|--|--testing.js |--Container |--|--Links |--|--|--LinksContainer |--|--|--|--index.js
Imagine that we’re working in the testing.js
located in src/View/Header/TestingComponent/testing.js
and we need to import LinksContainer
you might accomplish it by doing something like
import LinksContainer from '../../../Container/Links/LinksContainer'
Because we already set an alias and, we will be able to use it like this:
import LinksContainer from 'Container/Links/LinksContainer'
✓
https://github.com/victors1681/webpack-demo/commit/1c0cc7a99d5f0f18215b3448a5b96b57c7c121e5
DevServer
Now we are going to config our development server, and first of all, we need to install it as a development dependency.
$ npm install webpack-dev-server -D --save
Let’s create a public folder in our root project and then create a new file called index.html this file will hold our JSs bundles.
$ mkdir public && touch public/index.html && echo "<html><head><title>My App</title></head><body>Hello</body></html>" >> public/index.html
Open the package.json
and change webpack
to webpack-dev-server
"start": "webpack --config webpack.config.js --env.NODE_ENV=development",
to
"start": "webpack-dev-server --config webpack.config.js --env.NODE_ENV=development",
Add the devServer
configuration
devServer: { contentBase: path.join(__dirname, "public"), compress: true, port: 9000 }
Now we are able to run npm run start
and then open http://localhost:9000/
Next step is to include our bundle js app.js
and vendor.js
into our HTML file index.html
but we can not add the bundle manually into the HTML header because our bundle has a hash remember is app.[chunkhash].js
to inject our bundle we will need to use a plugin called HtmlWebpackPlugin.
https://github.com/victors1681/webpack-demo/commit/1c0cc7a99d5f0f18215b3448a5b96b57c7c121e5
Plugins
In order to customize the Webpack building process, we can use plugins. To inject our bundle.js into our HTML let’s install and config HtmlWebpackPlugin
$ npm install --save-dev html-webpack-plugin
After installing the plugin then import it into webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
...
plugins: [
new HtmlWebpackPlugin()
], ...
Now we need to add a couple of configurations to HtmlWebpackPlugin
plugins: [ newHtmlWebpackPlugin({ filename: "index.html", template: path.join(__dirname, "public/index.html"), inject: true,
chunks: ["app", "vendors"],})
],
$ npm run start
Now you will be able to see app.[chunkhash].js
and vendors.[chunkhash].js
injected in our index.html
Our app is working!
https://github.com/victors1681/webpack-demo/commit/1c0cc7a99d5f0f18215b3448a5b96b57c7c121e5
Modules
The module can be from the application code or a third-party library. The resolver helps Webpack find the module code that needs to be included in the bundle for every such require / import statement.
At this point, we need a plugin to transpile our Javascript code to make it run and compatible with any browsers, Babel can help us to accomplish that.
Babel converts ES6-ES7 syntaxes into a plaint ES5 Javascript.
ECMAScript 5 is also known as ES5 and ECMAScript 2009
ECMAScript 6 is also known as ES6 and ECMAScript 2015.
ES6 code
const sum = (a, b) => a + b;
Babel converts to ES5:
var sum = function sum(a, b) { return a + b; };
Using the result we will be able to execute our code in any browser without worry about compatibility.
Installation and configuration
npm install --save-dev @babel/core @babel/cli @babel/preset-env
In order to make Webpack use Babel, we need a loader
npm install --save-dev babel-loader
Instead, to use Babel in our package.json
it’s a better practice to create a Babel config file move to root directory and run the command below.
$ touch babel.config.js
Note: for a previous version, you might see different name like .babelrc
for new Babel ≥ 7 we are able to use babel.config.js
babel.config.json
.babelrc.js
or .babelrc
It all depends on you, if you want to use the static or dynamic file, babel always will look for one of those names.
After opening our new file babel.config.js
we can declare our new module like this:
module.exports = api => { api.cache(true); //new babel 7 feature return { presets: ["@babel/preset-env"], plugins: [] }; };
Since you want to use React you need to add more configuration to transform the React’s JSX syntax to vanilla Javascript.
npm install --save-dev @babel/preset-react
and then add the new preset installed in webpack.config.js
module.exports = api => { api.cache(true);
return { presets: ["@babel/preset-env", "@babel/preset-react"], plugins: [] }; };
Later we are going to expand our configuration by adding plugins to babel.config.js
Now we have our configuration for Babel completed, and now we need to tell Webpack to load those configurations and transpile the all ES6 code.
Go back to webpack.config.js
and add new rule
modules in the webpack JSON structure.
module: { rules: [{ test: /.(js)$/, exclude: /node_modules/, use: ["babel-loader"] }] },
Adding this rule we are telling to Webpack, find all JS files in our project and transpile it but exclude our vendors, vendors are already transpired.
At this point, our app is ready to use Reactjs
let’s open src/index.js
remove console.log(‘Hello world’)
and add the following code into it.
import React from 'react';
import ReactDOM from 'react-dom';
const content = 'This is my react app';
ReactDOM.render(
{content},
document.getElementById('mainApp')
);
$ npm run start
https://github.com/victors1681/webpack-demo/commit/1c0cc7a99d5f0f18215b3448a5b96b57c7c121e5
Babel Plugins
Our app is transpiring the ES6 basic syntax now we are going to make our app slightly complicated. Create a new directory src
called View
and add a new file to it called Counter.js
$ mkdir src/View
$ touch src/View/Counter.js
https://gist.github.com/victors1681/184ee7f986e32e8d70707dbc0bc807f5
Then open src/index.js
and add the new counter.js component
https://gist.github.com/victors1681/f7c9fc020b9201e36a60c5d6c487045b
After do$ npm run start
you definitely will have an error like this:
It’s because Babel does not recognize classes, to fix that we need to install and add @babel/plugin-proposal-class-properties
to babel.config.js
npm install --save-dev @babel/plugin-proposal-class-properties
https://gist.github.com/victors1681/4e3a313d78472fc8f77aa8a83c1728d0
Then make $ npm run start
https://github.com/victors1681/webpack-demo/commit/1c0cc7a99d5f0f18215b3448a5b96b57c7c121e5
Optimization
It’s really important to optimize our application for production, Webpack ≥ 4 is making our life easy bringing tools to accomplish that.
Note: Webpack ≥ 4 introduced
optimization for chunk splitting
this new feature madeCommonsChunkPlugin
deprecated.
First of all, we’re going to install terser-webpack-plugin
this plugin is similar to UglifyJS-webpack-plugin
I started using terse for Webpack 4 because has better performance at runtime, this plugin allows us to compress and minimize our bundles and optimize them for production.
$ npm install terser-webpack-plugin --save-dev
Open webpack.config.js
import the terser-webpack-plugin
and add the plugin under the optimization/minimizer
object.
const TerserPlugin = require("terser-webpack-plugin");
optimization: { minimizer: [ new TerserPlugin({ cache: true, parallel: true, terserOptions: { compress: { dead_code: true, conditionals: true, booleans: true }, module: false, output: { comments: false, beautify: false, } } }) ] }
Please check the terser-webpack-plugin repository to add more configuration if you need it.
After the configuration has been added you can go ahead and make
$ npm run build
Your production bundle will look like this.
The next screenshot shows our production bundle before minimized, notice there are comments and also functions name will be largest.
https://github.com/victors1681/webpack-demo/commit/1c0cc7a99d5f0f18215b3448a5b96b57c7c121e5
SplitChunksPlugin
Once again we’re going to talk about performance, Split Chunks allow us to split our code into multiples files, you might ask why splitting our code improves the performance of the application, well the fact is browser cache will be better, imagine we make a small change for our application and that change only affect a particular module, instead to load a big bundle will be better only to load a small piece of the app.
SplitChunks also allows for avoiding duplicate code we don’t want to have a new copy of our dependencies for each chunk, to visualize that we are going to introduce webpack-bundle-analyzer
npm install --save-dev webpack-bundle-analyzer
Open package.json and add a new script to activate the analyze plugin also a flag env.analyze
to only run the plugin whenever we want.
"analyze": "npm run start -- --env.analyze"
Add this plugin to webpack.config.js
bellow to the HtmlWebpackPlugin
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; plugins: [ new HtmlWebpackPlugin({ filename: "index.html", template: path.join(__dirname, "public/index.html"), inject: true, chunks: ["app", "vendors"] }), env.analyze && new BundleAnalyzerPlugin() ]
Fixes: The previous code won’t work if we execute
$ npm run start
needs to be fixed. Plugins key is expecting an Array of plugins, if env.analyze is not defined we will setting an invalid array will looks like this :
plugins: [{HtmlWebpackPlugin Object}, false]; //Fail
In order to fix this issue, we can create a new function to return only activated plugins
const getPlugins = env => [ new HtmlWebpackPlugin({ filename: "index.html", template: path.join(__dirname, "public/index.html"), inject: true, chunks: ["app", "vendors"] }), env.analyze && new BundleAnalyzerPlugin() ].filter(plugin => plugin); //if env.analyze is false will return only [HtmlWebpackPlugin]
Then call the get plugins function from the plugin object
... }, plugins: getPlugins(env), module: { ...
https://github.com/victors1681/webpack-demo/commit/1c0cc7a99d5f0f18215b3448a5b96b57c7c121e5
Now we can run the analysis script
npm run analyze
After that, the devServer will run and the analyze plugin will launch a new browser window http://127.0.0.1:8888/.
After the launch, bundle-analyze you might notice that both bundle app.js and vendors.js both have a copy of the dependencies like react-dom
and also have almost the same size ~429 kb and the size or our app 858.97 kb this is really bad, now is time to add split chunk.
Go to webpack.config.js
and reach the optimization object.
optimization: { splitChunks: { cacheGroups: { vendors: { test: /[\/]node_modules[\/]/, name: "vendors", chunks: "all" } } }, minimizer: [ ...
run again the bundle-analyze
npm run analyze
As you can see the size of our app is 431.61 KB because we don’t have a copy of our dependency on each bundle.
https://github.com/victors1681/webpack-demo/commit/1c0cc7a99d5f0f18215b3448a5b96b57c7c121e5
Speeding up the Webpack building process
As our project grows the building process takes longer for production bundle and development, there’re some techniques we can implement to speed up our building time for Webpack ≥ 4, also Webpack team are working to brings more tools to help to face that issues like persistent cache perhaps will be available for futures version of Webpack, some of the time consumed during the building process is taken by Babel converting our code, Cache Loader
Thread Loader
can help us to better performance.
npm install --save-dev cache-loader thread-loader
After installing it we can use those plugins in our bable-loader
, open webpack.config.js
and modify the loader.
module: { rules: [{ test: /.(js)$/, exclude: /node_modules/, use: [ "cache-loader", "babel-loader?cacheDirectory", "thread-loader" ] }] },
The following screenshot was taken before implementing Cache-loader and Thread-loader
After
npm run dist
Because our application is too small we can not see a real improvement but our bundle was built 50% faster than before and it using the base configuration if you take a look at the documentation of thread-loader we also can increase the number of worker parallel jobs up to 50.
https://github.com/victors1681/webpack-demo/commit/1c0cc7a99d5f0f18215b3448a5b96b57c7c121e5
CSS-loader & Sass-loader & SplitChunk
CSS plays a very important role in our front-end application, it means we might have tons of CSS code that also needs to be performed. In this section, we are going to install css-loader sass-loader
and also we are going to extract all CSS and bundle it into a single file to cached.
npm install sass-loader node-sass style-loader css-loader -D
After installation, we can add a new rule to find all css
and sass
in modules in webpack.config.js
{ test: /.(sc|c)ss$/, use: [ "style-loader", "css-loader", "sass-loader" ] }
To make sure everything is working properly let’s add son CSS styles to our project.
Go to src/View/
and add a new file, Counter.scss
$ touch src/View/Counter.scss
, and add some classes;
https://gist.github.com/victors1681/1016c0c7245a014b0ec6eb044d91059a
Import the Counter.scss
into the Counter.js
import './Counter.scss';
and add those classes to the JSX code.
https://gist.github.com/victors1681/aa02e93bbac88618dadc9fee2c800cc9
$ npm run start
Everything is working as expected, the scss was loaded and compiled and applied correctly in our component.
If you notice all CSS properties are loaded inline inside the HTML file, and we can not cache it, the browser will load every time all CSS of our app, to perform the production bundle we can make some adjustments to extract all CSS and compile a new style.css bundle, that way all browsers will able to cache.
mini-css-extract-plugin will help us to extract all CSS.
npm install --save-dev mini-css-extract-plugin
Go to webpack.config.js
import the plugin
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
Go to getPlugins
and add the new one, notice this plugin only can be used in production mode.
env.analyze && new BundleAnalyzerPlugin(), env.production && new MiniCssExtractPlugin({ filename: "css/[name].[chunkhash:8].css" })
and then modify the loader to only extract all CSS in production.
{ test: /.(sc|c)ss$/, use: [ env.NODE_ENV === "development" ? "style-loader" : MiniCssExtractPlugin.loader, "css-loader", "sass-loader" ] } //if development use 'style-loader' if not use MiniCssExtractPlugin
Then locate optimization
the object and add new cacheGroup
splitChunks: { cacheGroups: { vendors: { test: /[\/]node_modules[\/]/, name: "vendors", chunks: "all" }, styles: { test: /.css$/, name: 'styles', chunks: 'all', enforce: true } }, },
To illustrate how splitChunk
and mini-css-extract-plugin
extracted all CSS in one I added another component called Login.js Login.scss
and ViewSelector.js
https://gist.github.com/victors1681/6e3f816e743beff314018cf7f772ef8fhttps://gist.github.com/victors1681/17b4d37da8404e8c979af366e35cffc4https://gist.github.com/victors1681/6aec1cae3f5f73c950e07cad8869ccebhttps://gist.github.com/victors1681/1446e53b6c1454d27aa9ebff14514908
One file was generated app.b96....css
and all CSS combined.
The last thing we need to do is to generate a minimized version of our CSS file.
$ npm install --save-dev optimize-css-assets-webpack-plugin
In webpack.config.js
import, the plugin
const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
optimization.minimizer: []
add the new plugin to the minimizer array
new OptimizeCssAssetsPlugin({ assetNameRegExp: /.css$/g, cssProcessor: require("cssnano"), cssProcessorPluginOptions: { preset: ["default", { discardComments: { removeAll: true } }] }, canPrint: true })
$ npm run build
https://github.com/victors1681/webpack-demo/commit/1c0cc7a99d5f0f18215b3448a5b96b57c7c121e5
HMR (Hot Module Replacement) & React-Hot-Loader
HMR exchanges, adds or removes modules while an application is running, it means every time you make changes in your CSS or JS the browser will update without a full reload.
Let’s try this out!
First of all, we need to add the property hot
to our devServer in webpack.config.js
devServer: { contentBase: path.join(__dirname, "public"), compress: true, port: 9000, hot: true },
Add the HotModuleReplacementPlugin
to our getPlugins
in Webpack configuration.
https://gist.github.com/victors1681/94c418cae460885ae04da7ccb6d3cc4c
//Only on development env.NODE_ENV.development && webpack.HotModuleReplacementPlugin()
Then npm run start
and you will see HMR will be enabled in the WDS (webpack dev server).
To test this out go to src/View/Login/login.scss
to change the button color to
background: green;
Save it and HMR will update our app and the browser will update without full reload.
It’s working, but what about javascript changes.
HMR is not working we have a full load, to fix that issue we need to add some code to our main tileindex.js
if (module.hot) { module.hot.accept("./View/ViewSelector", function() { ReactDOM.render(<ViewSelector />, document.getElementById("mainApp")); }); }
Now change back Sign In without full load
to Sign in
and HRM work’s fine.
Now let’s toggle our view click Toggle View
and then make some changes to Counter.js
<h1 className="counter-header">This is my counter Hot Reload</h1>
Notice we don’t have a full reload but we are losing the React state
To fix this issue we need help from React-Hot-Loader
https://github.com/victors1681/webpack-demo/commit/1c0cc7a99d5f0f18215b3448a5b96b57c7c121e5
Configuring React-Hot-Loader:
npm install react-hot-loader -D
Then move to babel.config.js
// babel.config.js { "plugins": ["react-hot-loader/babel"] }
Please notice there we’re going to add more changes that we don’t have in the getting started React-Hot-Loader documentation
module.exports = api => { api.cache(true); return { presets: [ ["@babel/preset-env", { loose: true, modules: false } ], "@babel/preset-react"], plugins: [ ["@babel/plugin-proposal-class-properties",{ "loose": true }], "react-hot-loader/babel" ] }; };
Then open ViewSelector.js
our parent file included in index.js
import { hot } from 'react-hot-loader'
.....
export default hot(module)(ViewSelector);
Then remove the rerender code added in index.js
// if (module.hot) { // module.hot.accept("./View/ViewSelector", function() { // ReactDOM.render(<ViewSelector />, document.getElementById("mainApp")); // }); // }
Every time we update our component we don’t have a full reload and we not lose the state.
https://github.com/victors1681/webpack-demo/commit/1c0cc7a99d5f0f18215b3448a5b96b57c7c121e5
Cleaning Distribution folder.
You might notice that every time we run npm run dist
new files are generated in the directory, to fix that issue we’re going to use clean-webpack-plugin
this plugin allows us to clean up removing old files.
npm install --save-dev clean-webpack-plugin
Add it into webpack.config.js
and append the plugin into the plugin object, only should be executed for distribution and specify the directories to clean it up, add myDistribution/ui/js
and myDistribution/ui/css.
const CleanWebpackPlugin = require('clean-webpack-plugin');
...
env.NODE_ENV === "production" && new CleanWebpackPlugin(['myDistribution/ui/js', 'myDistribution/ui/css'])
https://gist.github.com/victors1681/b9d610d08b7525bd0a7cc674bfb0b6ff
Then npm run dist
and you will see only the latest
Webpack Configuration Refactorization
So far this is how your Webpack configuration looks like, I prefer to split webpack.config.js into multiples files to make it easy to read and maintain.
Repository of this tutorial
https://github.com/victors1681/webpack-demo/commit/1c0cc7a99d5f0f18215b3448a5b96b57c7c121e5
Webpack Tutorial configuration.
https://gist.github.com/victors1681/20e51bd4d43666ab5be7445d46d66b16
Webpack Refactorized
I created a new repository to make life easy every time I start a new project.
https://github.com/victors1681/webpack-demo/commit/1c0cc7a99d5f0f18215b3448a5b96b57c7c121e5
+ Babel plugins added.
@babel/plugin-proposal-object-rest-spread
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; console.log(x); // 1 console.log(y); // 2 console.log(z); // { a: 3, b: 4 }
@babel/plugin-transform-async-to-generator
async function foo() { await bar(); }
to
var _asyncToGenerator = function (fn) { ... }; var foo = _asyncToGenerator(function* () { yield bar(); });
@babel/plugin-syntax-dynamic-import
@babel/plugin-transform-modules-commonjs
@babel/polyfill Babel plugin that includes a polyfill that includes a custom regenerator runtime and core-js.
@babel/plugin-proposal-export-namespace-from
export * as ns from 'mod';
@babel/plugin-proposal-throw-expressions
function test(param = throw new Error('required!')) { const test = param === true || throw new Error('Falsey!'); }