This plugin is intended to provide offline experience for webpack projects. It uses ServiceWorker and AppCache as a fallback under the hood. Simply include this plugin in your webpack.config, and the accompanying runtime in your client script, and your project will became offline ready by caching all (or some) output assets.
npm install offline-plugin [--save-dev]
First, instantiate the plugin with options in your webpack.config:
// webpack.config.js example
var OfflinePlugin = require('offline-plugin');
module.exports = {
// ...
plugins: [
// ... other plugins
new OfflinePlugin({
// All options are optional
caches: 'all',
scope: '/',
updateStrategy: 'all',
version: 'v1',
ServiceWorker: {
output: 'sw.js'
},
AppCache: {
directory: 'appcache/'
}
})
]
// ...
}Then, install the runtime in your client script:
require('offline-plugin/runtime').install();All options are optional and offline-plugin could be used without specifying them. Also see full list of default options here.
- caches:
'all' | Object. Tells to the plugin what to cache and how. Default:'all'.all: means that everything (all the webpack output assets) will be cached inmaincache.Object: Object with 3 possible Array sections (properties). All sections are optional and default empty (no assets added). Use special keyword:rest:to match all unused/uncached assets. To match multiple assets or assets with dynamic names, use pattern matching. Any section can contain any assets, not only those which are generated by the webpack build. However, "pattern matching" is executed only against generated assets. When external asset is included you will receive warning about it (missing from generated assets) unless it's explicitly marked as external viaexternalsoption.maincache. Assets listed in this section are cached first (viainstallevent inServiceWorker) and if caching of this section fails -- no assets are cached at all. Hence, it should contain minimal set of assets, for example['index.html', 'main.js'].additionalcache. Assets in this section are loaded aftermainsection is successfully loaded. InServiceWorkerthis section is loaded inactivateevent. If any of assets fails to download, then nothing is cached from theadditionalsection and all the assets are moved to theoptionalsection. If current update strategy ischanged, then only failed to download assets are moved to theoptionalsection, all other are successfully cached.optionalcache. This sections is only supported byServiceWorker. As you may guess from its name, assets are cached only when they are fetched from the server.ServiceWorkerwon't download them ahead of time.
- scope:
string. Scope of the project, for example'/m/'or'/admin/'. Default:'/'. - updateStrategy:
'all' | 'hash' | 'changed'. Cache update strategy. Default:'all'.allstrategy usesversionpassed to options as a cache tag. When version changes, old version cache is removed and new files are downloaded. Of course if files has same name were not changed (304 status returned), then probably browser won't download them again and will just update cache.hashstrategy is basically the same asallstrategy, but uses webpack unique compilation hash as a tag.changedstrategy is more advanced thanallorhash. To work properly it requires output assets to have unique names between compilations, e.g. file's unique hash in its name. With this strategy enabled,index.htmlfile (or other files without dynamic name) should be placed inmainsection of the cache, otherwise they won't be revalidated.- For
ServiceWorkerthis means that only new files will be downloaded and missing files deleted from the cache. - For
AppCacheit's basically same as previous strategies sinceAppCacherevalidates all the assets. 304 HTTP status rule of course still works.
- For
- externals:
Array<string>. Explicitly marks cache asset as external so you won't receive any warnings about it if asset it missing from webpack generated assets. - excludes:
Array<string | globs_pattern>. Excludes selected assets from generation. Exclusion is applied before any assets is added tocachessections, hence global. - relativePaths:
boolean. When set totrue, all assets cache paths are generated relatively toServiceWorkerfile orAppCachefolder receptively. Settingscopeto''(empty string) sets this option totrueand vice-versa. Default:false - version:
string | Function. Version of the cache. Is used only withallupdate strategy. Might be a function, useful in watch-mode when you need dynamic date for each generation. Default: Current date. - rewrites:
Function | Object. Rewrite function or rewrite map (Object). Useful when assets are server in a different way from the client perspective, e.g. usuallyindex.htmlserved as/. Default: function which rewrites/any/path/index.htmlto/any/path/. - ServiceWorker:
Object | null | false. Settings for theServiceWorkercache. Usenullorfalseto disableServiceWorkergeneration.output:string. Relative (from the webpack's configoutput.path) output path for emitted script. Default:'sw.js'.entry:string. Relative or absolute path to file which will be used asServiceWorkerentry. Useful to implement additional function for it. Default: empty file.
- AppCache:
Object | null | false. Settings for theAppCachecache. Usenullorfalseto disableAppCachegeneration.NETWORK:string. ReflectsAppCache'sNETWORKsection. Default:'*'.directory:string. Relative (from the webpack's configoutput.path) output directly path for theAppCachefiles. Default:'appcache/'.caches:Array<string>. List of sections fromcachesoption (main,additionaloroptional). Default:['main', 'additional'].
Besides plugin configuration, you also need to initialize it at runtime phase. This is most easier part:
require('offline-plugin/runtime').install();Runtime install accepts 3 optional arguments: options, successCallback, errorCallback. options is not used at the moment (ignored), so it's better to just put null instead.
Is it possible to minify ServiceWorker script output?
Yes, offline-plugin perfectly works with official webpack.optimize.UglifyJsPlugin, so if it's used your will get minified ServiceWorker script as well (no additional options required).
Is there a way to match assets with dynamic file names, like compilation hash or version?
Yes, it's possible with pattern matching, which is performed by minimatch library.
Example: main: ['index.html', 'scripts/main.*.js'].
Do I need to include cache-polyfill for the ServiceWorker?
No, it's included automatically for you.
- Added
relativePathsoption. Whentrue, all generated paths are relative toServiceWorkerfile orAppCachefolder. Useful in cases when app isn't in the root of domain, e.g. Github Pages. Settingscopeto''(empty string) is the same now asrelativePaths: true. - Added
excludesoption to exclude assets from caches. Exclusion is global and is performed before any assets added to cache sections. - Not specified sections in caches now equals to empty selection. Previously,
:rest:keyword was added automatically, now isn't. - ':rest:' keyword is now handled after all caches sections were handled. Previously it was handled immediately when found.
- Plugin now throws an error when keyword
:rest:is used more than once. ServiceWorkergeneration now used Child Compilation instead weird hacks with entry injections.
Improved ServiceWorker entry generation: use compilation.namedChunks instead of compilation.assets to access service-entry and replace it. See NekR#10 for more details.
Added FALLBACK back section for AppCache and fixed generation of a NETWORK section.
More info in CHANGELOG