Easy Offline First Apps With Webpack's Offline Plugin
Tags: webpack, offline, bundling, building
Published: 2017-02-12 14:20:54

---
title: Easy Offline First Apps With Webpack's Offline Plugin
published: true
description: Creating easy offline first applications with the help of Webpack.
cover_image: 
tags: webpack, offline, bundling, building
---

_TL;DR Here is a [repository](https://github.com/kay-is/webpack-offline-plugin-example) with a working example. :)_

Many of your have probably noticed all the buzz about _offline first_ Web-apps. The Web is full of articles about the _AppCache_ about _Service Workers_ and such and now you ask yourself, _how do I can get my apps work offline, like the cool kids_. Or you simply asked, __how come that data I already have on my device isn't shown to me anymore?!__

Well, there are a bunch of technologies to help you with this, but this seems a rather fast paced topic these days. So first things first.

If you write a single page application, you often have different types of request your app sends. Some get images, some get styles, some code and some _actual user data_.

## Caching User Data

For the last point, the _user data_, you will basically store the whole stuff somewhere on the client. Since this depends mostly on your business logic, it is advisable to write at least part of that logic yourself.

You can use [localStorage](https://en.wikipedia.org/wiki/Web_Storage) for this if a key-value-store is enough or, [indexed DB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) if you need a more sophisticated datastore. There are even libraries that help with the usage of these low-level Web-APIs. Like [PouchDB](https://pouchdb.com/) and [LocalForage](https://github.com/localForage/localForage).

## Caching Assets

But this post is about your assets. Your HTML, CSS, JS and Images.

If you bundle your assets with Webpack, there is a really easy way: The [offline-plugin](https://github.com/NekR/offline-plugin).

After building with this plugin, you can call a function, that will make all Webpack generated assets available offline.

A basic `webpack.config.js` could look like this:

```javascript
const HtmlWebpackPlugin = require('html-webpack-plugin')
const OfflinePlugin = require('offline-plugin')

const html = new HtmlWebpackPlugin({template: './src/index.html'})
const offline = new OfflinePlugin

module.exports = {
  entry: './src/index.js',
  output: {
    filename: '[name].[hash].js',
    path: './assets/',
  },
  plugins: [html, offline],
}
```

## Pitfall: Non-Webpack Assets

Now you probably ask, why does the basic version need another plugin? Well, the _offline-plugin_ has a catch.

It will _only_ cache the assets that are produced by Webpack if it isn't handed any configuration object.

So if you have an `index.html`, which you _don't_ generate with Webpack, it won't be cached and your whole app won't show when there is no connection.

Using the _html-plugin_ is a way to get around this problem. Then the `index.html`will be included.

Another way is using `externals`:

```javascript
const offline = new OfflinePlugin({
  externals: ['index.html'],
})
```

This is also used for assets from another server, for example if you require Bootstrap or jQuery from a content delivery network (CDN.

I found it a bit confusing at first, because I thought of `externals` as API requests and CDN assets. But it basically means: _files not built by Webpack_

The basic config won't give you any warning, only if you try to manually configure the _caches_ you will maybe see this:

 > WARNING in OfflinePlugin: Cache asset [index.html] is not found in the output assets,if it's an external asset, put it to the |externals| option to remove this warning

## Pitfall: Cached Forever

The basic approach is to require the _offline-plugin_ runtime at the beginning at your code and install it. Which basically means _enable caching_.

```javascript
const offlinePluginRuntime = require('offline-plugin/runtime')
offlinePluginRuntime.install()
```

But you don't have to activate the caching automatically on application start. This can lead to unexpected behaviour if you're not used to offline modes.

For example, you could upload another version of a file and give it the same name, so it won't change on the client.

Or you have an API call in `externals` and now only the cached results are shown.

This can greatly help with debugging.

## Conclusion

The _offline-plugin_ is a really easy way to show already downloaded data to your users, even if they aren't online. These days, where more and more people are online via mobile devices, this offline scenario becomes less and less of an exeption.