noobmaster007
noobmaster007

Reputation: 163

CRA-Typescript PWA with Workbox for Background Sync?

Can someone please point me to the right direction on how to use Workbox with a service worker to implement background syncing in a CRA-typescript PWA? I've been combing the internet for weeks now and still no luck of finding a good tutorial or a step-by-step guide.

Is it impossible to have a service worker use Workbox with Typescript?

Upvotes: 2

Views: 853

Answers (2)

LonelySpirit
LonelySpirit

Reputation: 68

Since CRA 4.0 was released, you can simple create

src/service-worker.js

file in root folder of your app, and it will automatically compiled by CRA.

Check this

Upvotes: 1

Grigory Bogush
Grigory Bogush

Reputation: 413

Create react app doesn't support this by default however you can get it to work with libraries like craco which allows to customize create-react-app configuration without ejecting.

In my case I was able to get it to work by adding an extra plugins to the CRA webpack configuration.

const path = require('path');
const { InjectManifest } = require('workbox-webpack-plugin');
const { addPlugins } = require('@craco/craco');
const CopyPlugin = require('copy-webpack-plugin');

module.exports = {
  webpack: {
    configure: (reactAppConfig) => {
      whenProd(() => {
        // Technically CRA copies files using fs
        // but those are not seen by webpack and InjectMainfest
        // I couldn't get those to be included in __WB_MANIFEST
        // with the plugin.

        // "workbox-build" would work using globPatterns
        // but it should be run after CRA has compiled everything
        // and it's not clear how to make sure of that
    
        reactAppConfig.plugins = reactAppConfig.plugins.concat([
          new CopyPlugin({
            patterns: [
              {
                from: 'public',
                to: './',
                globOptions: {
                  dot: false, // ignore hidden files
                  ignore: [
                    '*.txt',
                    '*.map',
                  ],
                },
              }],
          }),
          new InjectManifest({
            swSrc: path.resolve(__dirname, 'src', 'service-worker', 'my-worker.ts'),
            swDest: path.resolve(__dirname, 'build', 'sw.js'), // output js
            include: [ // Stuff to include in __WB_MANIFEST
              /\.(html|js|css|json)$/,
              /static\/.*\.(png|gif|jpg|svg|jpeg)$/
            ],
            exclude: [
              /asset-manifest\.json/,
            ],
            maximumFileSizeToCacheInBytes: 2 * 1024 * 1024, // 2 MB
          })
        ]);
      });
      return reactAppConfig;
    },
  },
};

You will also need to make sure your typescript worker file gets compiled with the right configuration, you can do so by adding tsconfig.json in your worker directory (i.e src/service-worker/)

{
  "compilerOptions": {
    "composite": true,
    "lib": [
      "esnext",
      "webworker"
    ],
  },
  "include": [
    "./**/*.ts"
  ]
}

And make sure your root typescript conifg points to this worker subproject

{
  // .... All the other options
  "exclude": [
    //...
    "./src/service-worker"
  ],

  // point to the service worker subproject
  "references": [{ "path": "./src/service-worker" }]
}

Feel free to point out any mistakes.

Upvotes: 2

Related Questions