Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Be able to create service-worker in typescript #33863

Closed
kristijorgji opened this issue Feb 1, 2022 · 22 comments
Closed

Be able to create service-worker in typescript #33863

kristijorgji opened this issue Feb 1, 2022 · 22 comments
Labels
examples Issue was opened via the examples template. good first issue Easy to fix issues, good for newcomers TypeScript Related to types with Next.js.

Comments

@kristijorgji
Copy link

Describe the feature you'd like to request

There is no example on how to create a serivce-worker.ts, that gets compiled at specified output (example public/service-worker.js)

We want to have this option and service worker for the app

Describe the solution you'd like

One official example, probably with some typescript config on how to achieve this.
Or even better a way for nextjs to extend its webpack tsconfig to also other files like service-worker, server etc

Describe alternatives you've considered

I am trying to create new tsconfig.sw.json right now but without success. I need to build a single bundle .js service-worker butr when I import other ts functions into it cannot create single bundle get tsc error

@balazsorban44 balazsorban44 added examples Issue was opened via the examples template. TypeScript Related to types with Next.js. good first issue Easy to fix issues, good for newcomers and removed template: story labels Feb 1, 2022
@eashish93
Copy link

eashish93 commented Feb 6, 2022

You can setup typescript for service-worker using solution described in example custom-server-typescript. Just copy the config and include your service worker typescript file path in custom tsconfig.

@SukkaW
Copy link
Contributor

SukkaW commented Mar 2, 2022

You can setup typescript for service-worker using solution described in example custom-server-typescript. Just copy the config and include your service worker typescript file path in custom tsconfig.

How do we leverage Next.js built-in features (and Vercel platform) with the example then? Do you mean Service Worker is incompatible with the Vercel platform?

@gallyamb
Copy link

Is there any update? We'd like to create typescript service worker too, but couldn't find how to do that

@HaNdTriX
Copy link
Contributor

There is an example called examples/progressive-web-app that uses next-pwa.

For more detailed examples check out next-pwa/examples.

@SukkaW
Copy link
Contributor

SukkaW commented Apr 21, 2022

There is an example called examples/progressive-web-app that uses next-pwa.

For more detailed examples check out next-pwa/examples.

Does next-pwa allow me to write my own Service Worker logic, beyond caching and offline? E.g. How to implement Service Worker Notification using next-pwa and TypeScript?

@HaNdTriX
Copy link
Contributor

@zdila
Copy link

zdila commented May 29, 2022

I am using this hacky solution:

In /next.config.js:

const { InjectManifest } = require("workbox-webpack-plugin");

module.exports = {
  // ... other configs
  webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
    if (!isServer) {
      config.plugins.push(
        new InjectManifest({
          swSrc: "./sw.ts",
          swDest: "../public/sw.js",
          include: ["__nothing__"],
        })
      );
    }

    return config;
  }
};

and in /sw.ts:

/// <reference lib="webworker" />

declare const self: ServiceWorkerGlobalScope;

const resources = self.__WB_MANIFEST; // this is just to satisfy workbox

// ... your SW code

Generated sw.js is placed to /public/sw.js so you should add it to your .gitignore.

@Sowed
Copy link

Sowed commented Aug 14, 2022

Can also confirm, "next-pwa": "5.5.4" works just fine.

@Yrobot
Copy link

Yrobot commented Feb 20, 2023

I am finding the esaiest way to add the service worker to Next.js project too, the answers i found are all about next-pwa or workbox .

In my opinion, the problem is same as how to add files which needs compile to output public folder.

But when i try to add entry and ouput to webpack config in next.config.js, things not go as i expected. For example, the output file path is under build/_next/static/chunks, and the output file name is within a hash code, etc.

So i opened a discussion on this, hoping for a god.

@nitinTJ
Copy link

nitinTJ commented May 15, 2023

Does next-pwa works fine with the next 13 app directory. Because I am facing an issue where the service worker is not getting registered.

@matallui
Copy link

I'm looking for an answer to this issue as well. Ideally one that doesn't require next-pwa as I just need a very simple service worker file. Any other ideas will be much appreciated!

@Yovach
Copy link
Contributor

Yovach commented Oct 27, 2023

Hi, I've created a webpack plugin for this use case (writing Service worker in TypeScript) because I needed too and plugins like next-pwa add too much stuff (like workbox).

But you can also use this plugin for files that you need to compile from TypeScript to .js in the public folder.

To use it:

npm install --save-dev next-public

Then, create a sw.ts file at [root]/app/+public/sw.ts:

/// <reference lib="WebWorker" />
export type {};
declare let self: ServiceWorkerGlobalScope;

self.addEventListener("install", async () => {
  console.log("Service worker installed (cjs)");
});

self.addEventListener("fetch", (evt: FetchEvent) => {
  // Do your magic here. E.g. if you want to cache third party resources:
});

self.addEventListener("error", (err) => {
  console.error("Service worker error", err);
});
// next.config.mjs
import path from "node:path";
import { NextPublicTsPlugin } from "next-public";

const __dirname = new URL(".", import.meta.url).pathname;

/**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  webpack(config, context) {
    config.plugins.push(
      new NextPublicTsPlugin({
        inputDir: path.join(__dirname, "app", "+public"),
        outputDir: path.join(__dirname, "public"),
      })
    );
    return config;
  },
};

export default nextConfig;

Obviously, you need to adapt the above code to your situation.

@mrdomino
Copy link

@Yovach Wow, fortuitous timing, doing this the day before I find myself wanting to write a service worker for Next in TypeScript... thanks, about to try it out.

@Yovach
Copy link
Contributor

Yovach commented Oct 28, 2023

Wow, fortuitous timing, doing this the day before I find myself wanting to write a service worker for Next in TypeScript... thanks, about to try it out.

I've wanted to do this for so long and I'm glad it can help other people.

@mrdomino
Copy link

mrdomino commented Oct 28, 2023

Hmm, somehow my sw.js file (generated from something like the ts you showed) is ending up with an export statement in it at the end that is tripping up my browser. Investigating... any ideas?

EDIT: Ah, type: 'module' in serviceWorker.register is probably it.

@Yovach
Copy link
Contributor

Yovach commented Oct 28, 2023

Hmm, somehow my sw.js file (generated from something like the ts you showed) is ending up with an export statement in it at the end that is tripping up my browser. Investigating... any ideas?

EDIT: Ah, type: 'module' in serviceWorker.register is probably it.

I'll fix the issue because sometimes, you don't need that and it includes unnecessary code

@mrdomino
Copy link

Hmm, next thing is that process.env.NEXT_PUBLIC_* is not getting substituted.

@mrdomino
Copy link

mrdomino commented Oct 28, 2023

And now I'm getting very strange TypeScript behavior — the <reference lib="WebWorker" /> in app/+public/sw.ts seems to be getting applied to the rest of my components, so TypeScript is saying e.g. "Property 'serviceWorker' does not exist on type 'WorkerNavigator'" in App.tsx. If I take the line out of sw.ts, the errors go away elsewhere.

@Yovach
Copy link
Contributor

Yovach commented Oct 28, 2023

And now I'm getting very strange TypeScript behavior — the <reference lib="WebWorker" /> in app/+public/sw.ts seems to be getting applied to the rest of my components, so TypeScript is saying e.g. "Property 'serviceWorker' does not exist on type 'WorkerNavigator'" in App.tsx. If I take the line out of sw.ts, the errors go away elsewhere.

Where did you add the sw.ts file ? (we should go on issues page related to the lib and not this issue)

@genzzo
Copy link

genzzo commented Nov 3, 2023

Here are two solutions that might help

1 - sw.js file with typesciprt capabilities

Create a sw.js file in your public directory and add the following to the top:

/// <reference lib="webworker" /> // 
// @ts-check
/** @type {ServiceWorkerGlobalScope} */
// @ts-ignore
const sw = self;

Explanation:

  • Reference the webworker library to get the needed types for the service-worker
  • Tell the typescript compiler to check this js file
  • Define the type of the service worker using jsdoc
  • Tell the typescript compiler to ignore the next line
  • Reference the service worker through a new variable, that's because the "self" variable cannot have its type overridden which explains the ts-ignore comment

The drawbacks of this is that it's not quite a typescript file and so any explicit typings will need to be in the form of a jsdoc comment, so if you really want to have a typescript file here's solution 2:

2 - Manually handle a sw.ts file

Create a sw.ts file and add the following to the top:

/// <reference lib="webworker" />
const sw = self as unknown as ServiceWorkerGlobalScope; // we still need to override the "self" variable

Now run this command

npx tsc path/to/your/sw.ts --lib "WebWorker" --outDir public --watch

This will watch whenever your service worker changes and compile it again into the public directory, next will handle the rest
You can also use something like concurrently to run "next dev" with this command to watch everything at once

@rjwignar
Copy link

rjwignar commented Jun 5, 2024

I'm trying to make a custom service-worker to implement the Share Target API but I'm confused.
The app I'm working on is written in TypeScript,
Should I write my service worker in sw.js (JavaScript) or sw.ts (TypeScript)?

@samcx
Copy link
Member

samcx commented Jan 3, 2025

We have documentation on this now! → https://nextjs.org/docs/app/building-your-application/configuring/progressive-web-apps#creating-a-pwa-with-nextjs

@samcx samcx closed this as completed Jan 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
examples Issue was opened via the examples template. good first issue Easy to fix issues, good for newcomers TypeScript Related to types with Next.js.
Projects
None yet
Development

No branches or pull requests