Laravel PWA (from webpack.mix.js)

Kristi Tanellari
Codefield community
4 min readMay 4, 2018

Today i will be showing you how to make a laravel project a fully working progressive web app.This will prompt your users to “install” your website on their device and even access it when there’s limited to no internet connection.To get more information about the service worker go to chrome dev tools on the application section.Before i get started there is a great tutorial about this here and this is one of the tutorials i used when i first wanted to implement it on my project.But this example requires making changes on your webpack.config.js file which tends to get a little complicated.I cam across a much simpler solution. Using the webpack.mix.js file.Now lets get started.

What do you need

To get the PWA functionality you first need a couple of things. Here is a list of everything you need but these will do just fine:

  • HTTPS
  • manifest.json
  • service worker
  • A good Responsive design

About the HTTPS if you are working locally don’t worry.Google treats localhost as a safe domain.

The Setup

To get the service worker up and running we will use the sw-precache plugin for webpack .You can install the package like this

npm install — save-dev sw-precache-webpack-plugin

Updating webpack.mix.js

Go to your webpack.mix.js file and add this code to it

var SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');mix.webpackConfig({
plugins: [
new SWPrecacheWebpackPlugin({
cacheId: 'pwa',
filename: 'service-worker.js',
staticFileGlobs: ['public/**/*.{css,eot,svg,ttf,woff,woff2,js,html}'],
minify: true,
stripPrefix: 'public/',
handleFetch: true,
dynamicUrlToDependencies: { //you should add the path to your blade files here so they can be cached
//and have full support for offline first (example below)
'/': ['resources/views/welcome.blade.php'],
// '/posts': ['resources/views/posts.blade.php']
},
staticFileGlobsIgnorePatterns: [/\.map$/, /mix-manifest\.json$/, /manifest\.json$/, /service-worker\.js$/],
navigateFallback: '/',
runtimeCaching: [
{
urlPattern: /^https:\/\/fonts\.googleapis\.com\//,
handler: 'cacheFirst'
},
{
urlPattern: /^https:\/\/www\.thecocktaildb\.com\/images\/media\/drink\/(\w+)\.jpg/,
handler: 'cacheFirst'
}
],
// importScripts: ['./js/push_message.js']
})
]
});

Short description of what this means

  • staticFileGlobs: The files that we want cached.
  • dynamicUrlToDependencies: Map the routes of the blade files. This is very important to achieve offline first
  • runtimeCaching: Allows us to save 3rd party libraries in cache.
  • importScripts: This includes our custom logic to the generated service worker.

Now all you have to do is compile the assets for example like this npm run production

The manifest file

Create a file named manifest.json .This file give you control on how your app behaves.Google has a very good explanation of it.Here’s how i use it:

{
"short_name": "your app",
"name": "your app",
"theme_color": "#fff",
"background_color": "#fff",
"display": "standalone",
"icons": [
{
"src": "icons/icon_48_48_dpi.png",
"type": "image/png",
"sizes": "48x48"
},
{
"src": "icons/icon_72_48_dpi.png",
"type": "image/png",
"sizes": "72x72"
},
{
"src": "icons/icon_96_48_dpi.png",
"type": "image/png",
"sizes": "96x96"
},
{
"src": "icons/icon_144_48_dpi.png",
"type": "image/png",
"sizes": "144x144"
},
{
"src": "icons/icon_168_48_dpi.png",
"type": "image/png",
"sizes": "168x168"
},
{
"src": "icons/icon_192_48_dpi.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "icons/icon_128_128_dpi.png",
"type": "image/png",
"sizes": "128x128"
},
{
"src": "icons/icon_256_128_dpi.png",
"type": "image/png",
"sizes": "256x256"
},
{
"src": "icons/icon_384_128_dpi.png",
"type": "image/png",
"sizes": "384x384"
},
{
"src": "icons/icon_512_128_dpi.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": "http://127.0.0.1:8000/",
"orientation": "portrait"
}
  • short_name: The name shown on the homescreen of the mobile device.
  • name: The name shown on the install banner/popup.
  • theme_color : the color of your theme.
  • background_color: The color that is shown just before you app launches(it’s a good practice to use the same color as theme_color).
  • orientation: The orientation to be used(portrait/landscape).
  • start_url: Your website’s url.
  • display: standalone(for mobile-like feel)or browser(browser adds an address bar).
  • icons: These are the images for our apps icon on the homescreen. Remember google uses images closest to 48 dpi as icons and the ones closest to 128 dpi as splash screen icon.

Checking for PWA support

In the file where you define your layouts add this code:

<script>
if ('serviceWorker' in navigator ) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/service-worker.js').then(function(registration) {
// Registration was successful
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}, function(err) {
// registration failed :(
console.log('ServiceWorker registration failed: ', err);
});
});
}
</script>

This checks for service worker support.if you have the push manager package then use this line

(‘serviceWorker’ in navigator && ‘PushManager’ in window)

instead of

if (‘serviceWorker’ in navigator )

By doing this you have full support for PWA.If you check this on google’s lighthouse extension on localhost you get a score of 82 just because https is not available and you will get these 2 warnings which is perfectly fine for local development

Does not use HTTPS: 1 insecure request found
Does not redirect HTTP traffic to HTTPS

If you run this on a live server with https enabled you will get a perfect score of 100.

--

--

Kristi Tanellari
Codefield community

I've written about coding in the past, I will now mainly focus on writing about my life because I have some stories to tell. Buckle up and enjoy the ride.