July 16, 2018











Hello! Today we begin a webpack 4 course. We will start with the basic concepts of Webpack, with every part of the course going deeper. This time we will learn the basics of module bundling using ES6 modules. Webpack 4 provide default configuration, which we will go through. Let’s go!

Webpack 4 course begins – but what is Webpack?

Before considering using any kind of tool, you need to ask yourself a very important question. The question is, what problem of yours does the tool solve. Webpack is a module bundler. It means, that its purpose is to merge a group of modules (with their dependencies). The output might be one, or more files. Aside from bundling modules, webpack can do all sorts of things with your files: for example transpile scss to css, or typescript to javascript. It can even compress all of your image files! But why would you want to bundle modules at all?

The purpose of module bundling

Way back in the days, we didn’t have any way of splitting our JavaScript code served for browsers into multiple files other than using many <script> tags. We needed to write a source of every file that we would like to use into the HTML code. It isn’t really convenient. The community came up with some workarounds: CommonJS (implemented into Node.js) and AMD. For an explanation of them, check out an article on the Auth0 blog. Finally, the ES6 came with a brand new import/export syntax.

ES6 modules

With the ES6, the syntax of modules was defined. Thanks to that, we finally got a standard format for modules, built into the JavaScript language specification. It does not mean that it is well implemented in browsers, but it is improving. Even with native support for ES6 modules, you still might want to bundle your modules into fewer files. For the purpose of the course providing all the information that you need to start using Webpack, let’s briefly go through the syntax of ES6 modules.

export

The export statement is used to create JavaScript modules. You can use it to export both objects (including functions) and primitive values. An important thing to notice is that exported modules are in strict mode. There are two types of export: named and default.

Named exports

You can have multiple named exports per module.

lib.js

1 2 3 4 5 6 7 8 9 10 11 12 13 export function sum ( a , b ) { return a + b ; } export function substract ( a , b ) { return a - b ; } function divide ( a , b ) { return a / b ; } export { divide } ;

Note that if you would like to export something after its declaration, you need to wrap it in curly brackets (like the divide function in the example above).

Default exports

You can only have one default export per module.

dog.js

1 2 3 4 5 export default class Dog { bark ( ) { console . log ( 'bark!' ) ; } }

import

The import statement is used to import from other modules.

whole module’s content

index.js

1 2 3 4 5 import * as lib from './lib.js' ; console . log ( lib . sum ( 1 , 2 ) ) ; console . log ( lib . substract ( 3 , 1 ) ) ; console . log ( lib . divide ( 6 , 3 ) ) ;

You can set any name you want for the imported module. If you are importing whole content from a module, that has a default export, it will be placed into a default property.

index.js

1 2 3 4 import * as Dog from './dog.js' ; const dog = new Dog . default ( ) ; dog . bark ( ) ; // 'bark!'

importing one, or more named exports

index.js

1 2 3 4 5 import { sum , substract , divide } from './lib' ; console . log ( sum ( 1 , 2 ) ) ; console . log ( substract ( 3 , 1 ) ) ; console . log ( divide ( 6 , 3 ) ) ;

An important note is that the names of corresponding values must match.

importing a default export

index.js

1 2 3 4 import Dog from './dog.js' ; const dog = new Dog ( ) ; dog . bark ( ) ; // 'bark!'

Note, that the default export can be imported with any name, so we could do something like that:

index.js

1 2 3 4 import Cat from './dog.js' ; const dog = new Cat ( ) ; dog . bark ( ) ; // 'bark!'

The ES6 modules feature also dynamic imports, which we will get to in the future parts of the course.

Check out the MDN web docs for more examples of exports and imports.

Basic concepts of webpack

Since version 4, webpack does not require any configuration. It has a set of defaults. If you want to create a configuration file, you need to name it webpack.config.js. We will now mimic its default configuration to explain the basic concepts connected to Webpack.

webpack.config.js

Note that we write the webpack configuration file in Node.js, therefore it uses CommonJS type of modules.

The webpack.config.js exports a single object. If you run webpack through the console, it is going to look for that file and use it.

Entry

Webpack needs an entry point. It indicates which module webpack should use to begin the module bundling. The default is as follows:

webpack.config.js

1 2 3 module . exports = { entry : './src/index.js' } ;

It means that webpack will go to the './src/index.js' file and start the bundling from that. If you use any imports in the index.js file, webpack will handle them.

You can have more than one entry point, but with single page applications, it is common to have only one.

Output

The output is a configuration of where webpack should output your bundle. It defaults to the './dist/main.js' file.

webpack.config.js

1 2 3 4 5 6 7 8 9 const path = require ( 'path' ) ; module . exports = { entry : './src/index.js' , output : { path : path . resolve ( __dirname , 'dist' ) , filename : 'main.js' } } ;

Running webpack

In the sections before, we created the index.js file that imports functions from lib.js. Let’s finally run webpack! Remember to put those files into the src directory, so that it would match the default configuration.

The first thing you need to do is to install Webpack. I will be using npm for that. Fire up your terminal and write:

1 2 npm init - y npm install webpack

This will create a directory node_modules with webpack in it, and two files: package.json and package-lock.json.

If you would like to know more about dependencies in npm and the package-lock.json file, check out Keeping you dependencies in order when using npm

Now open the package.json file and modify your scripts:

1 2 3 "scripts" : { "build" : "webpack" }

Thanks to that, running npm run build will use webpack from the node_modules directory.

You can see that a file main.js was created in the dist directory. It contains all your code both from the index.js and lib.js files

Multiple entry points

You can achieve all of the above without any config file. If you would like to do some more, now it is a time to create it.

entries

The entry property of our configuration does not have to be a string. If you would like to have multiple entry points, you can use an object.

webpack.config.js

1 2 3 4 5 6 module . exports = { entry : { first : './src/one.js' , second : './src/two.js' , } } ;

With that code, we’ve created two entry points. It might be needed if you are developing a multi-page application.

outputs

There is an issue though: by default, there is only one output file specified. We can easily fix that:

webpack.config.js

1 2 3 4 5 6 7 8 9 10 11 12 const path = require ( 'path' ) ; module . exports = { entry : { first : './src/one.js' , second : './src/two.js' , } , output : { filename : '[name].bundle.js' , path : path . resolve ( __dirname , 'dist' ) } }

With the code above, we indicate that there might be more than one file as the output. All files will have a distinct name now and will be called first.bundle.js and second.bundle.js, just like our entry points.

If you run webpack the same way as before, it will find the webpack.config.js file and apply the configuration.

Summary

Today we’ve learned the basics of module bundling with webpack using the ES6 modules. Webpack 4 provides default configuration, which we went through today while explaining the core concepts like the entry and output. Of course, Webpack can do much more than that. In the upcoming parts of the course, we will cover loaders, and even write one ourselves. Stay tuned!