Handling Images

Bharat Tiwari
A beginner’s guide to Webpack 2
5 min readMay 20, 2017

Usually there are two ways the images are used in a web application — using the <img> tag in the HTML or thru css by setting ‘background-image’ property in an HTML element’s css class or style.

The images would typically be stored either on some CDN or some separate folder on the web server. For the image’s location, you either provide the URL of the image or the relative path location of the image if its stored in a folder on the server.

With Webpack, the image loading can be optimized using the url-loader that converts your images to base64 strings and inlines those within the code. With images stored inline within the application package, the user’s browser will save on the requests to CDN or web-server to fetch those images thereby improving the performance of the application.

Converting images to base64 strings and storing those inline in the code is okay for smaller-size images, however with larger images, the size of the application package will grow significantly to out-weigh the advantage of saving on a trip to server for fetching the image. For this, url-loader provides an option — limit. With limit specified, the url-loader will convert only those images to base64 string that have sizes up to the specified limit

For images with sizes larger than the specified limit, the url-loader, instead of converting it to base64 string, it will pass on the image to file-loader. Along with the image, the url-loader will also pass on any configuration options, that you may have specified for url-loader in webpack.config, to the file-loader.

So lets see how to get our images packed with webpack:

1. Install file-loader and url-loader

$ npm install url-loader file-loader --save-dev

2. Configure url-loader in webpack.config, add below to modules.rules array in webpack.config:

./webpack/webpack.config.js

Above we added a second rule in our webpack config’s module.rules array (lines 12–22).
The 'test' for this rule has been set to /\.(png|jp(e*)g|svg)$/, which means for any file with a filename extension matching with .png, .jpeg, .jpg or .svg, use the loader specified in the 'use' property i.e. the url-loader. Further we specified the options for the url-loader – limit: 8000, which means any image up-to 8kb would be converted to base64 string and inlined in the code. Any image with a size higher than 8kb would be passed on the file-loader to process, along with its options. That’s why we specified name property in the options object, so that when url-loader passes any file with size>8kb to file-loader, it will also pass the name property as part of options, which then the file-url will use for naming the image file in the application package.

3. Now, we will add couple of small-sized images for , lets say a Home Icon and a Settings Icon of our application. Click on the links to download the images. Both of these are less than the 8kb limit that we’ve specified for the url-loader.)

– add a folder 'images' under our ‘src’ folder
– download the two images(Home Icon, Settings Icon) and save those under under 'src/images'

4. Next, we will modify ./src/index.html template file slightly to add an <img> tag as shown below:

./src/index.html

Note lines 13–17 above - we added a new <div> with an <img> tag inside with id=home.

5. Now, for Webpack to see the home image as a dependency and then process it using url-loader, we need to import that image in our javascript.

./src/scripts/app.js

Above, in app.js, we imported home.png as homeIcon (line # 6) and assigned it as src of the <img> tag we added to index.html in step 4 (line # 8–9).

Run npm start command again to restart webpack with the new settings:

$ npm start

6. As webpack starts bundling the package, when it goes thru app.js and encounters the line import homeIcon from '../images/home.png'; it sees this as .png module, so it would apply the rule that passes the test for ‘.png’, which asks it to use ‘url-loader’. url-loader would first check the size of the file, which is 4kb for home.png, less than the 8kb ‘limit’ size specified in the ‘options’ of url-loader. So url-loader would convert the png file to base64 string and store it inline in the srcof the <img> tag.

7. Refresh the browser (http://localhost:9000/index.html) and the Home icon should now be visible on the page.

Images in CSS class

Next, lets see if url-loader/file-loader, that we added in previous section, can also handle the images that we add a background-image in a css-class.

1. In the ./src/styles/app.css file, add the below css class:

./src/styles/app.css

2. In the ./src/index.html, add a div with its class set to above defined class

./src/index.html

Above, we added a <div> with class="settingIcon" so that we can see and test the css class that we created in the step # 1 above.

3. Save the files and run npm start ( it may run by itself because of devServer’s HMR and we didn’t modify webpack.config.js this time )

4. This time, as webpack starts bundling and its css-loader scans our app.css file, when it encounters the line background-image: url('./../images/css3Logo.png'); it would pass on the handling of the url to url-loader. url-loader would again see the file size (4kb) is less than the limit (8kb), so it would convert the image to base64 string and use it inline in the generated css bundle.

5. Again, open/refresh ( or if it reloads by itself because of devServer’s HMR) the page in browser and the settings icon should be visible as background image to the last div we added.

Next, we’ll learn how to make webpack to load larger size images as file resources using file-loader instead of letting url-loader to inline those as base64 string in the code.

--

--